【kafka学习笔记】PHP接入kafka
安装扩展
# 先安装rdkfka库文件
git clone https://github.com/edenhill/librdkafka.git
或者:
wget https://gitee.com/wanhedigital_1553363148/librdkafka/attach_files/619880/download/librdkafka-1.6.0.tar.gz -O librdkafka.tar.gz
cd librdkafka/
./configure
make
sudo make install
pecl install rdkafka
vim [php]/php.ini
extension=rdkafka.so
生产者
<?php
$conf = new RdKafka\Conf();
$conf->setDrMsgCb(function ($kafka, $message) {
file_put_contents("./dr_cb.log", var_export($message, true).PHP_EOL, FILE_APPEND);
});
$conf->setErrorCb(function ($kafka, $err, $reason) {
file_put_contents("./err_cb.log", sprintf("Kafka error: %s (reason: %s)", rd_kafka_err2str($err), $reason).PHP_EOL, FILE_APPEND);
});
$rk = new RdKafka\Producer($conf);
$rk->setLogLevel(LOG_DEBUG);
$rk->addBrokers("127.0.0.1");
$cf = new RdKafka\TopicConf();
// -1必须等所有brokers同步完成的确认 1当前服务器确认 0不确认,这里如果是0回调里的offset无返回,如果是1和-1会返回offset
// 我们可以利用该机制做消息生产的确认,不过还不是100%,因为有可能会中途kafka服务器挂掉
$cf->set('request.required.acks', 0);
$topic = $rk->newTopic("test", $cf);
$option = 'qkl';
for ($i = 0; $i < 20; $i++) {
//RD_KAFKA_PARTITION_UA自动选择分区
//$option可选
$topic->produce(RD_KAFKA_PARTITION_UA, 0, "qkl . $i", $option);
}
$len = $rk->getOutQLen();
while ($len > 0) {
$len = $rk->getOutQLen();
var_dump($len);
$rk->poll(50);
}
Low Level 消费者
<?php
$conf = new RdKafka\Conf();
$conf->setDrMsgCb(function ($kafka, $message) {
file_put_contents("./c_dr_cb.log", var_export($message, true), FILE_APPEND);
});
$conf->setErrorCb(function ($kafka, $err, $reason) {
file_put_contents("./err_cb.log", sprintf("Kafka error: %s (reason: %s)", rd_kafka_err2str($err), $reason).PHP_EOL, FILE_APPEND);
});
//设置消费组
$conf->set('group.id', 'myConsumerGroup');
$rk = new RdKafka\Consumer($conf);
$rk->addBrokers("127.0.0.1");
$topicConf = new RdKafka\TopicConf();
$topicConf->set('request.required.acks', 1);
//在interval.ms的时间内自动提交确认、建议不要启动
//$topicConf->set('auto.commit.enable', 1);
$topicConf->set('auto.commit.enable', 0);
$topicConf->set('auto.commit.interval.ms', 100);
// 设置offset的存储为file
//$topicConf->set('offset.store.method', 'file');
// 设置offset的存储为broker
$topicConf->set('offset.store.method', 'broker');
//$topicConf->set('offset.store.path', __DIR__);
//smallest:简单理解为从头开始消费,其实等价于上面的 earliest
//largest:简单理解为从最新的开始消费,其实等价于上面的 latest
//$topicConf->set('auto.offset.reset', 'smallest');
$topic = $rk->newTopic("test", $topicConf);
// 参数1消费分区0
// RD_KAFKA_OFFSET_BEGINNING 重头开始消费
// RD_KAFKA_OFFSET_STORED 最后一条消费的offset记录开始消费
// RD_KAFKA_OFFSET_END 最后一条消费
$topic->consumeStart(0, RD_KAFKA_OFFSET_BEGINNING);
//$topic->consumeStart(0, RD_KAFKA_OFFSET_END); //
//$topic->consumeStart(0, RD_KAFKA_OFFSET_STORED);
while (true) {
//参数1表示消费分区,这里是分区0
//参数2表示同步阻塞多久
$message = $topic->consume(0, 12 * 1000);
if (is_null($message)) {
sleep(1);
echo "No more messages\n";
continue;
}
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;
}
}
High LEVEL消费者
<?php
/**
* Created by PhpStorm.
* User: qkl
* Date: 2018/8/22
* Time: 17:58
*/
$conf = new \RdKafka\Conf();
function rebalance(\RdKafka\KafkaConsumer $kafka, $err, array $partitions = null) {
global $offset;
switch ($err) {
case RD_KAFKA_RESP_ERR__ASSIGN_PARTITIONS:
echo "Assign: ";
var_dump($partitions);
$kafka->assign();
// $kafka->assign([new RdKafka\TopicPartition("qkl01", 0, 0)]);
break;
case RD_KAFKA_RESP_ERR__REVOKE_PARTITIONS:
echo "Revoke: ";
var_dump($partitions);
$kafka->assign(NULL);
break;
default:
throw new \Exception($err);
}
}
// Set a rebalance callback to log partition assignments (optional)
$conf->setRebalanceCb(function(\RdKafka\KafkaConsumer $kafka, $err, array $partitions = null) {
rebalance($kafka, $err, $partitions);
});
// Configure the group.id. All consumer with the same group.id will consume
// different partitions.
$conf->set('group.id', 'test-110-g100');
// Initial list of Kafka brokers
$conf->set('metadata.broker.list', '192.168.216.122');
$topicConf = new \RdKafka\TopicConf();
$topicConf->set('request.required.acks', -1);
//在interval.ms的时间内自动提交确认、建议不要启动
$topicConf->set('auto.commit.enable', 0);
//$topicConf->set('auto.commit.enable', 0);
$topicConf->set('auto.commit.interval.ms', 100);
// 设置offset的存储为file
$topicConf->set('offset.store.method', 'file');
$topicConf->set('offset.store.path', __DIR__);
// 设置offset的存储为broker
// $topicConf->set('offset.store.method', 'broker');
// Set where to start consuming messages when there is no initial offset in
// offset store or the desired offset is out of range.
// 'smallest': start from the beginning
$topicConf->set('auto.offset.reset', 'smallest');
// Set the configuration to use for subscribed/assigned topics
$conf->setDefaultTopicConf($topicConf);
$consumer = new \RdKafka\KafkaConsumer($conf);
//$KafkaConsumerTopic = $consumer->newTopic('qkl01', $topicConf);
// Subscribe to topic 'test'
$consumer->subscribe(['qkl01']);
echo "Waiting for partition assignment... (make take some time when\n";
echo "quickly re-joining the group after leaving it.)\n";
while (true) {
$message = $consumer->consume(120*1000);
switch ($message->err) {
case RD_KAFKA_RESP_ERR_NO_ERROR:
var_dump($message);
// $consumer->commit($message);
// $KafkaConsumerTopic->offsetStore(0, 20);
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;
}
}
消费组特别说明
特别注意,High LEVEL消费者设置的消费组,kafka服务器才会记录, Low Level消费者设置的消费组,服务器不会记录
常用脚本实践:https://segmentfault.com/a/1190000016106045
分享一个打包好的php-rdkafka的类库
https://github.com/qkl9527/php-rdkafka-class
【kafka学习笔记】PHP接入kafka的更多相关文章
- Kafka 学习笔记之 Kafka0.11之console-producer/console-consumer
Kafka 学习笔记之 Kafka0.11之console-producer/console-consumer: 启动Zookeeper 启动Kafka0.11 创建一个新的Topic: ./kafk ...
- 大数据 -- kafka学习笔记:知识点整理(部分转载)
一 为什么需要消息系统 1.解耦 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险.许多 ...
- kafka学习笔记(一)消息队列和kafka入门
概述 学习和使用kafka不知不觉已经将近5年了,觉得应该总结整理一下之前的知识更好,所以决定写一系列kafka学习笔记,在总结的基础上希望自己的知识更上一层楼.写的不对的地方请大家不吝指正,感激万分 ...
- kafka学习笔记:知识点整理
一.为什么需要消息系统 1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险. ...
- kafka学习笔记1:测试环境搭建
最近因为架构中引入了kafka,一些之前在代码中通过RPC调用强耦合但是适合异步处理的内容可以用kafka重构一下. 考虑从头学一下kafka了解其特性和使用场景. 环境选择 首先是测试环境的搭建,平 ...
- Kafka学习笔记2: 快速入门
在开始Kafka环境搭建之前,首先要安装Linux系统,并在Linux系统上安装JDK1.8版本,关于linux虚拟机的安装和linux系统下jdk的安装可以参考我的博文: http://blog.c ...
- [Big Data - Kafka] kafka学习笔记:知识点整理
一.为什么需要消息系统 1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险. ...
- kafka学习笔记(七)kafka的状态机模块
概述 这一篇随笔介绍kafka的状态机模块,Kafka 源码中有很多状态机和管理器,比如之前我们学过的 Controller 通道管理器 ControllerChannelManager.处理 Con ...
- kafka学习笔记(二)kafka的基本使用
概述 第一篇随笔从消息队列的定义和各种应用,以及kafka的分类定义和基本知识,第二篇就写一篇关于kafka的基本实际配置和使用的随笔,包括kafka的集群参数的配置,生产者使用机制,消费者使用机制. ...
- KafKa——学习笔记
学习时间:2020年02月03日10:03:41 官网地址 http://kafka.apache.org/intro.html kafka:消息队列介绍: 近两年发展速度很快.从1.0.0版本发布就 ...
随机推荐
- 『与善仁』Appium基础 — 19、元素定位工具(三)
目录 1.Chrome Inspect介绍 2.Chrome Inspect打开方式 3.Chrome Inspect工具的使用 (1)Chrome Inspect工作前提 (2)Chrome Ins ...
- 备忘录:关于.net程序连接Oracle数据库
目录 关于使用MSSM访问Oracle数据库 关于. net 程序中连接Oracle数据库 志铭-2021年12月7日 21:22:15 关于使用MSSM访问Oracle数据库 安装访问接口组件:Or ...
- c#中实现串口通信的几种方法
c#中实现串口通信的几种方法 通常,在C#中实现串口通信,我们有四种方法: 第一:通过MSCOMM控件这是最简单的,最方便的方法.可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册 ...
- Oracle中的DBMS_LOCK包的使用
一.DBMS_LOCK相关知识介绍 锁模式: 名字 描述 数据类型 值 nl_mode Null INTEGER 1 ss_mode Sub Shared: used on an aggregate ...
- 【Java 8】 集合间转换工具——Stream.collect
集合运算 交集 (list1 + list2) List<T> intersect = list1.stream() .filter(list2::contains) .collect(C ...
- 找出1小时内占用cpu最多的10个进程的shell脚本
cpu时间是一项重要的资源,有时,我们需要跟踪某个时间内占用cpu周期最多的进程.在普通的桌面系统或膝上系统中,cpu处于高负荷状态也许不会引发什么问题.但对于需要处理大量请求的服务器来讲,cpu是极 ...
- Mybatis中 SIMPLE、REUSE、BATCH的区别
Executor分成两大类,一类是CacheExecutor,另一类是普通Executor. 普通类又分为: ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情.它为每个语句的执行 ...
- 实现new Date(), 获取当前时间戳
JS 获取时间戳: 我相信大家找了很久了吧! 希望我写的这个对您有些帮助哦~ 大家是不是以为时间戳是关于时间的,都去 new Date() 里面找方法了啊,我来告诉你们正确的吧 其实大家用 JS 里的 ...
- 【spring AOP】AspectJProxyFactory
AspectJProxyFactory,可能大家对这个比较陌生,但是@Aspect这个注解大家应该很熟悉吧,通过这个注解在spring环境中实现aop特别的方便. 而AspectJProxyFacto ...
- java列表组件鼠标双击事件的实现
Swing中提供两种列表组件,分别是列表框(JList)和组合框(JComboBox). 一.JList组件 构造方法: public JList():构造一个空的.具有只读模型的JList.publ ...