kafka

1 篇文章 0 订阅

1. 安装

docker-compose.yml

version: '3.7'

services:
  zookeeper:
    image: bitnami/zookeeper:latest  ## 镜像
    container_name: zookeeper  ## 容器名称
    restart: always   ## 重启策略
    ports:
      - "2181:2181"   ## 对外暴露的端口号
    network_mode: 'host' ## 网络模式
    environment:
      ALLOW_ANONYMOUS_LOGIN: yes
    volumes:
      - /etc/localtime:/etc/localtime  ## 挂载时区(kafka镜像和宿主机器之间时间保持一致)
  kafka:
    image: bitnami/kafka:latest ## 镜像
    container_name: kafka ## 容器名称
    ports:
      - "9092:9092" ## 对外暴露的端口号
    network_mode: 'host'  ## 网络模式
    environment: ## 环境变量
      KAFKA_BROKER_ID: 1
      ALLOW_PLAINTEXT_LISTENER: 'yes'
      KAFKA_ZOOKEEPER_CONNECT: 47.97.102.116:2181  ## 按实际写入宿主IP
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_ADVERTISED_HOST_NAME: 47.97.102.116
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://47.97.102.116:9092
    depends_on: ## 依赖情况
      - zookeeper

kafka tool: https://www.kafkatool.com/download.html

2. 简述

  • Topic:一组消息数据的标记符;
  • Producer:生产者,用于生产数据,可将生产后的消息送入指定的Topic;
  • Consumer:消费者,获取数据,可消费指定的Topic;
  • Group:消费者组,同一个group可以有多个消费者,一条消息在一个group中,只会被一个消费者获取;
  • Partition:分区,为了保证kafka的吞吐量,一个Topic可以设置多个分区。同一分区只能被一个消费者订阅。

3. 命令

# 在较新版本(2.2 及更高版本)的 Kafka 不再需要 ZooKeeper 连接字符串使用Kafka Broker
$ --bootstrap-server localhost:9092 替代- -zookeeper localhost:2181。

# 新建Topic
$ kafka-topics.sh --create --bootstrap-server localhost:9092  --replication-factor 1 --partitions 2 --topic topic_name

# 查看当前所有Topic 
$ kafka-topics.sh --bootstrap-server localhost:9092 --list

# 消费者消费消息
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic_name --from-beginning


4. kafka-python

from kafka import KafkaProducer, KafkaConsumer
from kafka.errors import kafka_errors
import traceback
import json

# Master
def producer_demo():
    # 假设生产的消息为键值对(不是一定要键值对),且序列化方式为json
    producer = KafkaProducer(
        bootstrap_servers=['localhost:9092'], 
        key_serializer=lambda k: json.dumps(k).encode(),
        value_serializer=lambda v: json.dumps(v).encode())
    # 发送三条消息
    for i in range(0, 3):
        future = producer.send(
            'kafka_demo',
            key='count_num',  # 同一个key值,会被送至同一个分区
            value=str(i),
            partition=1)  # 向分区1发送消息
        print("send {}".format(str(i)))
        try:
            future.get(timeout=10) # 监控是否发送成功           
        except kafka_errors:  # 发送失败抛出kafka_errors
            traceback.format_exc()

# Slave
def consumer_demo():
    consumer = KafkaConsumer(
        'kafka_demo', 
        bootstrap_servers=':9092',
        group_id='test'
    )
    for message in consumer:
        print("receive, key: {}, value: {}".format(
            json.loads(message.key.decode()),
            json.loads(message.value.decode())
            )
        )
参数设置
  • group_id

    高并发量,需要多个消费者协作,由group_id统一消费进度。例如:消费者A与消费者B在初始化时使用同一个group_id。当一条消息被A消费后(正确commit),在kafka中会被标记,这条消息不会在被B消费。

  • key_deserializer, value_deserializer

    与生产者中的参数一致,自动解析。

  • auto_offset_reset

    消费者启动的时刻,消息队列中或许已经有堆积的未消费消息,有时候需求是从上一次未消费的位置开始读(则该参数设置为earliest),有时候的需求为从当前时刻开始读之后产生的,之前产生的数据不再消费(则该参数设置为latest)。

  • enable_auto_commit, auto_commit_interval_ms

    是否自动commit,当前消费者消费完该数据后,需要commit,才可以将消费完的信息传回消息队列的控制中心。enable_auto_commit设置为True后,消费者将自动commit,并且两次commit的时间间隔为auto_commit_interval_ms。

    手动commit

    def consumer_demo():
        consumer = KafkaConsumer(
            'kafka_demo', 
            bootstrap_servers=':9092',
            group_id='test',
            enable_auto_commit=False
        )
        for message in consumer:
            print("receive, key: {}, value: {}".format(
                json.loads(message.key.decode()),
                json.loads(message.value.decode())
                )
            )
            consumer.commit()
    
  • 查看kafka堆积剩余量

    在线环境中,需要保证消费者的消费速度大于生产者的生产速度,所以需要检测kafka中的剩余堆积量是在增加还是减小。可以用如下代码,观测队列消息剩余量:

    consumer = KafkaConsumer(topic, **kwargs)
    partitions = [TopicPartition(topic, p) for p in consumer.partitions_for_topic(topic)]
    
    print("start to cal offset:")
    
    # total
    toff = consumer.end_offsets(partitions)
    toff = [(key.partition, toff[key]) for key in toff.keys()]
    toff.sort()
    print("total offset: {}".format(str(toff)))
        
    # current
    coff = [(x.partition, consumer.committed(x)) for x in partitions]
    coff.sort()
    print("current offset: {}".format(str(coff)))
    
    # cal sum and left
    toff_sum = sum([x[1] for x in toff])
    cur_sum = sum([x[1] for x in coff if x[1] is not None])
    left_sum = toff_sum - cur_sum
    print("kafka left: {}".format(left_sum))
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值