php版本为:7.2
# cd /var/www/html/
生产者,producer.php
<?php
$rk = new RdKafka\Producer();
$rk->setLogLevel(LOG_DEBUG); // 设置日志级别
$rk->addBrokers('127.0.0.1'); // 添加经纪人,就是ip地址
$topic = $rk->newTopic("test2"); // 新建主题
// 第一个参数:是分区。RD_KAFKA_PARTITION_UA代表未分配,并让librdkafka选择分区
// 第二个参数:是消息标志,必须为0
// 第三个参数:消息,如果不为NULL,它将被传递给主题分区程序
$topic->produce(RD_KAFKA_PARTITION_UA, 0, 'Message'); // 生成并发送单个消息
低级消费者,consumer.php
低级消费者就是:当你重启后消费过的消息队列还会存在,也就是说:低级消费者是用来处理可重复消费的数据的。
<?php
$rk = new RdKafka\Consumer();
$rk->setLogLevel(LOG_DEBUG); // 设置日志级别
$rk->addBrokers("127.0.0.1"); // 添加经纪人,就是ip地址
$topic = $rk->newTopic("test2"); // 这里的$rk和生产者是不同的类哦
// 第一个参数分区ID
// 第二个参数是开始消费的偏移量,有效值
$topic->consumeStart(0, RD_KAFKA_OFFSET_BEGINNING);
while (true) {
// 第一个参数是要消耗的分区
// 第二个参数是等待收到消息的最长时间,1000是一秒
$msg = $topic->consume(0, 1000);
if (@$msg->err) {
echo $msg->errstr(), "\n"; // 输出错误
break;
} else {
echo @$msg->payload, "\n"; // 输出消息
}
}
测试
# cd /var/www/html/
# php consumer.php
新打开一个终端,运行生产者,发送消息
# php producer.php
每当生产者运行一次就会发送一条消息,消费者那边就会接收到这条消息并进行相应的处理。
然而,上面只是为了好理解,实际上我们用的时候是需要处理完队列的某一条数据后就使其出列。也就是不需让它再出现。
高级消费者
将低级消费者代码注释。
<?php
$conf = new RdKafka\Conf();
$conf->setRebalanceCb(function (RdKafka\KafkaConsumer $kafka, $err, array $partitions = null) {
switch ($err) {
case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS:
echo "Assign: ";
var_dump($partitions);
$kafka->assign($partitions);
break;
case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS:
echo "Revoke: ";
var_dump($partitions);
$kafka->assign(NULL);
break;
default:
throw new \Exception($err);
}
});
$conf->set('group.id', 'myConsumerGroup');
$conf->set('metadata.broker.list', '127.0.0.1');
$topicConf = new RdKafka\TopicConf();
$topicConf->set('auto.offset.reset', 'smallest');
$conf->setDefaultTopicConf($topicConf);
$consumer = new RdKafka\KafkaConsumer($conf);
$consumer->subscribe(['test2']);
while (true) {
$message = $consumer->consume(120*1000);
switch ($message->err) {
case RD_KAFKA_RESP_ERR_NO_ERROR:
var_dump($message);
break;
case RD_KAFKA_RESP_ERR__PARTITION_EOF:
echo "No more messages; will wait for more\n";
break;
case RD_KAFKA_RESP_ERR__TIMED_OUT:
echo "Timed out\n";
break;
default:
throw new \Exception($message->errstr(), $message->err);
break;
}
}
启动消费者
# php consumer.php
启动生产者
# php producer.php
查看消费者终端,出现了消息。
ctrl+c
,重新启动消费者。
你会发现,之前消费过的就不会重新输出了。
但是现在有个问题,如果服务挂了未消费的数据会丢失吗?我们来试试看吧。
用php的sleep('3')
来延时,放在while
循环中。
启动消费者,然后运行十次生产者。把消费者ctrl+c。
重启前消费到3。
重启linux再启动kafka。
重启linux后,启动消费者,从4开始了。