PHP Apache Pulsar 消息队列使用
pulsar 毕竟是一个新生代的工具,PHP的客户端链接库几乎可以说没有,找了半天才只找到一个: pulsar-client-phpcpp 那么我们就来安装这个PHP扩展,我使用的是 MacOS 所以就以这个环境来安装。
根据README.MD,先看看扩展的依赖情况:
然后就是先安装依赖,最后再安装 pulsar-client-cpp
。
安装 Pulsar C++ client library
Pulsar C++ client library 是 Pulsar 官方提供的一个 C++ 的客户端链接库,用来连接 Pulsar 的。
在 MacOS 下我们有方便的工具 brew
,先来搜索看看 brew search
有没有有,有的就可以直接安装了
~ brew search pulsar
==> Formulae
libpulsar ✔
可以看到我们可以正常找到了 libpulsar
,那么就安装就行:
~ brew install libpulsar
==> Downloading https://mirrors.aliyun.com/homebrew/homebrew-bottles/bottles/libpulsar-2.7.1.big_sur.bottle.1.tar.gz
Already downloaded: /Users/mrcong/Library/Caches/Homebrew/downloads/23ecf52715abd669569c82f1a35be1c29bc76fe9ba971791f479a87a4505cb9b--libpulsar-2.7.1.big_sur.bottle.1.tar.gz
==> Reinstalling libpulsar
==> Pouring libpulsar-2.7.1.big_sur.bottle.1.tar.gz
? /usr/local/Cellar/libpulsar/2.7.1: 54 files, 19.9MB
编译安装 PHP-CPP
PHP-CPP是一个用于开发PHP扩展的C++库,依赖这个库证明 pulsar-client-phpcpp
是使用了这个 C++ 库来开发的。
//git 克隆下来
~ git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP.git
Cloning into 'PHP-CPP'...
remote: Enumerating objects: 5992, done.
remote: Total 5992 (delta 0), reused 0 (delta 0), pack-reused 5992
Receiving objects: 100% (5992/5992), 1.92 MiB | 2.16 MiB/s, done.
Resolving deltas: 100% (4224/4224), done.
//编译
~ make
//编译好后直接安装
~ sudo make install
编译安装 pulsar-client-cpp 扩展
安装好了 Pulsar C++ client library
和 PHP-CPP
后,就来编译安装 pulsar-client-cpp
扩展。
~ git clone git@github.com:oraoto/pulsar-client-phpcpp.git
~ cd pulsar-client-phpcpp
~ make -j4 // -j4 里面的 4是指 CPU的核数,可以提升编译速度
本身以为也一样顺利的,但是没想到在这一步居然出现了编译错误的问题。 ̄□ ̄||
过程中遇到了错误,信息如下:
g++ -Wall -shared -O2 -o pulsar-phpcpp.so src/Client.o src/Consumer.o src/ConsumerConfiguration.o src/Message.o src/MessageBuilder.o src/MessageId.o src/Producer.o src/Pulsar.o -lphpcpp -lpulsar
Undefined symbols for architecture x86_64:
"MessageId::latest(Php::Parameters&)", referenced from:
void Php::ZendCallable::invoke<&(MessageId::latest(Php::Parameters&))>(_zend_execute_data*, _zval_struct*) in MessageId.o
"MessageId::earliest(Php::Parameters&)", referenced from:
void Php::ZendCallable::invoke<&(MessageId::earliest(Php::Parameters&))>(_zend_execute_data*, _zval_struct*) in MessageId.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [pulsar-phpcpp.so] Error 1
去 pulsar-client-phpcpp
仓库的 ISSUE 看了一下,发现去年就有人提到了 MacOS 下编译不成功。然后作者还说不一定能解决,?,好尴尬,咋办了?
这对于一个没写过C++项目的人来说,是在不愿意去看这个错误信息啊。 考虑换一个扩展? 但是已经没得换了,搜索了一圈,发现只有这一个 PHP 的 Pulsar 扩展。
脑阔痛,要放弃么?换 Go 来?
总感觉不太甘心啊。PHP 是时间上最强大的语言(笑),所以坚决不能放弃。
既然都不想放弃,那么硬着头皮上吧。 不折腾会死星人不能这样服输,拿出当年大学学的那点 C++ 基础来看看能不能解决这个报错。
首先是 Undefined symbols for architecture x86_64
,符号引用错误?
从编译日志看 g++ -Wall -shared -O2 -o pulsar-phpcpp.so src/Client.o src/Consumer.o src/ConsumerConfiguration.o src/Message.o src/MessageBuilder.o src/MessageId.o src/Producer.o src/Pulsar.o -lphpcpp -lpulsar
来看,编译的文件里面是有 src/MessageId.o
不是少文件的问题。
换一个关键词 "MessageId::earliest(Php::Parameters&)", referenced from
?
按这个说明是没有或者访问不到这个静态方法?打开 MessageId.cpp 看看
去找了PHP-CPP的文档,提到类方法需要导出,再回来看 MessageId.cpp 文件,类方法也都有做导出
void registerMessageId(Php::Namespace &pulsarNamespace)
{
Php::Class<MessageId> messageId("MessageId");
messageId.method<&MessageId::earliest>("earliest");
messageId.method<&MessageId::latest>("latest");
messageId.method<&MessageId::getTopicName>("getTopicName");
messageId.method<&MessageId::serialize>("serialize");
messageId.method<&MessageId::deserialize>("deserialize");
}
只是唯一不同的有一个点,就是有的静态函数是 MessageId::
做前缀,有的是使用 static
做前缀,这个有什么不一样么?从报错信息看,提示引用错误的都是使用 static
做装饰前缀的,难道是没使用 MessageId::
作为前缀的被当成了私有方法?
改天得回去看看继续学学C和C++了。
那么试试改ta,在 void registerMessageId(Php::Namespace &pulsarNamespace)
顶端新增两新方法,使用 MessageId::
做装饰前缀~~
Php::Value MessageId::earliest(Php::Parameters ¶ms) { return ::earliest(); }
Php::Value MessageId::latest(Php::Parameters ¶ms) { return ::latest(); }
然后再来重新编译
~ make clean //清理一下上一次的编译结果
~ make -j4 // 嘿嘿嘿,完美通过了
执行完 make 就已经生成了 pulsar-phpcpp.so
文件了,把这个文件拷贝到php 7.4 的扩展目录下,在 php.ini 里面启用这个动态扩展,然后重启 PHP,去看看
嘿嘿嘿~,成功了。 看来我是瞎猫碰上死耗子了…… 后面就是来测试一下生产消息和消费消息了。
消息生产者
在安装 pulsar-client-phpcpp
扩展后,我们就可以使用了,我们先来写一个生产者,往消息系统里面生产数据:
<?php
use Pulsar\Client;
use Pulsar\MessageBuilder;
date_default_timezone_set('PRC');
$client = new Client("pulsar://127.0.0.1:6650");
$producer = $client->createProducer("persistent://public/default/test001/topic");
while (true)
{
$data = [
'body' => ['time' => date('Y-m-d H:i:s')],
];
$builder = new MessageBuilder();
$builder->setContent(json_encode($data));
$message = $builder->setDeliverAfter(5000)->build();
$producer->send($message);
unset($builder, $message);
echo date('Y-m-d H:i:s') . ' done' . PHP_EOL;
usleep(10);
}
消息消费者
生产完了数据,我们就来消费数据,写一个消费者
<?php
use Pulsar\Client;
use Pulsar\Consumer;
use Pulsar\ConsumerConfiguration;
use Pulsar\MessageBuilder;
$client = new Client("pulsar://127.0.0.1:6650");
$config = new ConsumerConfiguration();
$config->setConsumerType(Consumer::ConsumerShared);
$consumer = $client->subscribe("persistent://public/default/test001/topic", "consumer-1", $config);
while (true)
{
$message = $consumer->receive();
var_dump($message->getDataAsString());
$consumer->acknowledge($message);
}
到这,就OK了,能正常使用了。然后关于 Pulsar 连接的配置属性的等,后面会开新的文章说明。
Pulsar PHP IDE Helpers
这个扩展在 PHPStorm 里面没有语法提示,很难受,于是顺手做了一个 pulsar-php-ide-helpers 。
怎么使用呢?
先把项目克隆下来
~ git clone https://github.com/cong5/pulsar-php-ide-helpers ~/Downloads/pulsar-php-ide-helpers
然后在 PHPStorm 项目右侧项目文件栏里面,拉到底部,找到 External Libraries
,右键选择 Configure PHP Include Paths...
,选择上这个项目的路径就行。