Kafka's introduction and PHP-based kafka installation and testing

This article is to share content and presentation based on Kafka's kafka PHP installation and testing

About
Kafka is a high throughput of distributed publish-subscribe messaging system

kafka must know the role of
producer: producer.
consumer: the consumer.
topic: topic message as category record, Kafka seed message (your feed) classification, each class is called a message topic (Topic).
broker: running in a cluster, may consist of one or more services, each service is called a broker; consumers can subscribe to one or more topics (topic), and pull the data from the Broker, so consumption of these published news .

Classical model

  1. A partition under the theme can not be less than the number of consumers that a number of consumers can not be greater than under the theme partition is a big wasted idle for a
  2. A partition under a theme can simultaneously be a different consumer group in which a consumer spending
  3. A partition under a theme can only be a consumer spending with a consumer group

3315151442-5b5832bb37224_articlex.png

Common Parameters
request.required.acks
Kafka producer 3 has the ack mechanism, producerconfig producer when initialization may be achieved by configuring different request.required.acks values.

0: This means that the producers do not wait for a producer (grant) continues to send the next message from the broker confirming the synchronization is complete. This option provides the lowest latency but the weakest durability guarantee (when the server fails some data will be lost, as leader is dead, but the producer did not know, sent out information broker not receive).

1: This means that the producer after the data has been successfully received by the leader and get a confirmation message is sent. This option provides better durability for customers waiting server acknowledges the request was successful (yet to be written to the death of leader but lost the only copy of the message).

-1: This means that the producer confirmed follower replica upon receiving a data transmission considered complete.
This option provides the best durability, we ensure that no information is lost, as long as at least one synchronized copy kept alive.

Three mechanisms, followed by decreasing performance (throughput degradation Producer), the robustness of the data is sequentially incremented.

auto.offset.reset

  1. earliest: automatically reset to the first offset Offset
  2. latest: automatically resets the offset to the latest offset (default)
  3. none: If no previous consumer group offset found, an exception is thrown to the consumer.
  4. Other parameters: throw an exception (invalid parameter) to the consumer

kafka simple test installation and
mounting kafka (no need to install, can be unpacked)

# 官方下载地址:http://kafka.apache.org/downloads
# wget https://www.apache.org/dyn/closer.cgi?path=/kafka/1.1.1/kafka_2.12-1.1.1.tgz
tar -xzf kafka_2.12-1.1.1.tgz
cd kafka_2.12-1.1.0

Start kafka server

# 需先启动zookeeper
bin/zookeeper-server-start.sh config/zookeeper.properties
bin/kafka-server-start.sh config/server.properties

Start kafka client test

# 创建一个话题,test话题2个分区

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 2 --topic test
Created topic "test".
# 显示所有话题
bin/kafka-topics.sh --list --zookeeper localhost:2181
test
# 显示话题信息
bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic test
Topic:test    PartitionCount:2    ReplicationFactor:1    Configs:
Topic: test    Partition: 0    Leader: 0    Replicas: 0    Isr: 0
Topic: test    Partition: 1    Leader: 0    Replicas: 0    Isr: 0

 # 启动一个生产者(输入消息)
bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
[等待输入自己的内容 出现>输入即可]
>i am a new msg !
>i am a good msg ?
# 启动一个生产者(等待消息) 
# 注意这里的--from-beginning,每次都会从头开始读取,你可以尝试去掉和不去掉看下效果
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
[等待消息]
i am a new msg !
i am a good msg ?

Kafka installation of php extension

git clone https://github.com/arnaud-lb/php-rdkafka.git
cd php-rdkafka
phpize
./configure
make all -j 5
sudo make install
vim [php]/php.ini
extension=rdkafka.so

php coding practices
producer

<?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();
$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);
}

Run producer

php producer.php
# output
int(20)
int(20)
int(20)
int(20)
int(0)
# 你可以查看你刚才上面启动的消费者shell应该会输出消息
qkl . 0
qkl . 1
qkl . 2
qkl . 3
qkl . 4
qkl . 5
qkl . 6
qkl . 7
qkl . 8
qkl . 9
qkl . 10
qkl . 11
qkl . 12
qkl . 13
qkl . 14
qkl . 15
qkl . 16
qkl . 17
qkl . 18
qkl . 19

consumer

<?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);
    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;
    }
}

View server metadata (Topic / Partition / Broker)
<PHP?
$ Conf = new new RdKafka \ Conf ();

$conf->setDrMsgCb(function ($kafka, $message) {

    file_put_contents("./xx.log", var_export($message, true), FILE_APPEND);

});
$conf->setErrorCb(function ($kafka, $err, $reason) {
    printf("Kafka error: %s (reason: %s)\n", rd_kafka_err2str($err), $reason);

});
$conf->set('group.id', 'myConsumerGroup');
$rk = new RdKafka\Consumer($conf);
$rk->addBrokers("127.0.0.1");
$allInfo = $rk->metadata(true, NULL, 60e3);
$topics = $allInfo->getTopics();
echo rd_kafka_offset_tail(100);
echo "--";
echo count($topics);
echo "--";
foreach ($topics as $topic) {
    $topicName = $topic->getTopic();
    if ($topicName == "__consumer_offsets") {
        continue ;
    }
    $partitions = $topic->getPartitions();
    foreach ($partitions as $partition) {
//        $rf = new ReflectionClass(get_class($partition));
//        foreach ($rf->getMethods() as $f) {
//            var_dump($f);
//        }
//        die();
        $topPartition = new RdKafka\TopicPartition($topicName, $partition->getId());
        echo  "当前的话题:" . ($topPartition->getTopic()) . " - " . $partition->getId() . " - ";
        echo  "offset:" . ($topPartition->getOffset()) . PHP_EOL;
    }
}
Released five original articles · won praise 3 · Views 1827

Guess you like

Origin blog.csdn.net/dongdonggegelovezcj/article/details/104774217