简体   繁体   English

带有 Python 消费者的 Docker Kafka

[英]Docker Kafka w/ Python consumer

I am using dockerized Kafka and written one Kafka consumer program.我正在使用 dockerized Kafka 并编写了一个 Kafka 消费者程序。 It works perfectly when I run Kafka in docker and application at my local machine.当我在本地机器上的 docker 和应用程序中运行 Kafka 时,它可以完美运行。 But when I configured the local application in docker I am facing issues.但是当我在 docker 中配置本地应用程序时,我遇到了问题。 The issue may be due to a topic not created until time application started.该问题可能是由于在应用程序启动之前未创建主题。

docker-compose.yml码头工人-compose.yml

version: '3'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
  kafka:
    image: wurstmeister/kafka
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: localhost
      KAFKA_CREATE_TOPICS: "test:1:1"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  parse-engine:
    build: .
    depends_on:
      - "kafka"
    command: python parse-engine.py
    ports:
     - "5000:5000"

parse-engine.py解析引擎.py

from kafka import KafkaConsumer
import json

try:
    print('Welcome to parse engine')
    consumer = KafkaConsumer('test', bootstrap_servers='localhost:9092')
    for message in consumer:
        print(message)
except Exception as e:
    print(e)
    # Logs the error appropriately. 
    pass

Error log错误日志

kafka_1         | [2018-09-21 06:27:17,400] INFO [SocketServer brokerId=1001] Started processors for 1 acceptors (kafka.network.SocketServer)
kafka_1         | [2018-09-21 06:27:17,404] INFO Kafka version : 2.0.0 (org.apache.kafka.common.utils.AppInfoParser)
kafka_1         | [2018-09-21 06:27:17,404] INFO Kafka commitId : 3402a8361b734732 (org.apache.kafka.common.utils.AppInfoParser)
kafka_1         | [2018-09-21 06:27:17,431] INFO [KafkaServer id=1001] started (kafka.server.KafkaServer)
**parse-engine_1  | Welcome to parse engine
parse-engine_1  | NoBrokersAvailable 
parseengine_parse-engine_1 exited with code 0**
kafka_1         | creating topics: test:1:1

As I already added depends_on property in docker-compose but before starting topic application connecting so error occurred.因为我已经在 docker-compose 中添加了depends_on属性,但是在开始连接主题应用程序之前发生了错误。

I read that I can possible to add the script in the docker-compose file but I am looking for some easy way.我读到我可以在 docker-compose 文件中添加脚本,但我正在寻找一些简单的方法。

Thanks for help感谢帮助

Your problem is the networking.你的问题是网络。 In your Kafka config you're setting在您的 Kafka 配置中,您正在设置

KAFKA_ADVERTISED_HOST_NAME: localhost

but this means that any client (including your python app) will connect to the broker, and then be told by the broker to use localhost for any connections.但这意味着任何客户端(包括您的 python 应用程序)都将连接到代理,然后代理会告诉代理使用localhost进行任何连接。 Since localhost from your client machine (eg your python container) is not where the broker is, requests will fail.由于来自您的客户端机器(例如您的 Python 容器)的 localhost 不是代理所在的位置,因此请求将失败。

You can read more about fixing problems with your Kafka listeners in detail here您可以在此处详细阅读有关修复 Kafka 侦听器问题的更多信息

So to fix your issue, you can do one of two things:因此,要解决您的问题,您可以执行以下两项操作之一:

  1. Simply change your compose to use the internal hostname for Kafka ( KAFKA_ADVERTISED_HOST_NAME: kafka ).只需更改您的撰写以使用 Kafka 的内部主机名( KAFKA_ADVERTISED_HOST_NAME: kafka )。 This means any clients within the docker network will be able to access it fine, but no external clients will be able to (eg from your host machine):这意味着泊坞窗网络中的任何客户端将能够精细访问它,但是没有外部客户端将能够(例如,从您的主机):

     version: '3' services: zookeeper: image: wurstmeister/zookeeper ports: - "2181:2181" kafka: image: wurstmeister/kafka ports: - "9092:9092" environment: KAFKA_ADVERTISED_HOST_NAME: kafka KAFKA_CREATE_TOPICS: "test:1:1" KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 volumes: - /var/run/docker.sock:/var/run/docker.sock parse-engine: build: . depends_on: - "kafka" command: python parse-engine.py ports: - "5000:5000"

    Your clients would then access the broker at kafka:9092, so your python app would change to然后您的客户将在 kafka:9092 处访问代理,因此您的 Python 应用程序将更改为

     consumer = KafkaConsumer('test', bootstrap_servers='kafka:9092')
  2. Add a new listener to Kafka.向 Kafka添加一个新的侦听器。 This enables it to be accessed both internally and externally to the docker network.这使得它可以在 docker 网络内部和外部访问。 Port 29092 would be for access external to the docker network (eg from your host), and 9092 for internal access.端口 29092 用于访问 docker 网络外部(例如从您的主机),而 9092 用于内部访问。

    You would still need to change your python program to access Kafka at the correct address.您仍然需要更改您的 python 程序以在正确的地址访问 Kafka。 In this case since it's internal to the Docker network, you'd use:在这种情况下,由于它在 Docker 网络内部,您可以使用:

     consumer = KafkaConsumer('test', bootstrap_servers='kafka:9092')

    Since I'm not familiar with the wurstmeister images, this docker-compose is based on the Confluent images which I do know:由于我不熟悉wurstmeister图像,这个wurstmeister -compose 基于我知道的 Confluent 图像:

    (editor has mangled my yaml, you can find it here ) (编辑器损坏了我的 yaml,你可以在 这里找到

     --- version: '2' services: zookeeper: image: confluentinc/cp-zookeeper:latest environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 kafka: # "`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,- # An important note about accessing Kafka from clients on other machines: # ----------------------------------------------------------------------- # # The config used here exposes port 29092 for _external_ connections to the broker # ie those from _outside_ the docker network. This could be from the host machine # running docker, or maybe further afield if you've got a more complicated setup. # If the latter is true, you will need to change the value 'localhost' in # KAFKA_ADVERTISED_LISTENERS to one that is resolvable to the docker host from those # remote clients # # For connections _internal_ to the docker network, such as from other services # and components, use kafka:9092. # # See https://rmoff.net/2018/08/02/kafka-listeners-explained/ for details # "`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,-'"`-._,- # image: confluentinc/cp-kafka:latest depends_on: - zookeeper ports: - 29092:29092 environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

Disclaimer: I work for Confluent免责声明:我为 Confluent 工作

This line这条线

KAFKA_ADVERTISED_HOST_NAME: localhost

Says the broker is advertising itself as being available only on localhost , which means all Kafka clients would only get back itself, not the actual list of real broker addresses.说代理将自己宣传为仅在localhost上可用,这意味着所有 Kafka 客户端只会取回自己,而不是实际代理地址的实际列表。 This would be fine if your clients are only located on your host - requests always go to localhost, which is forwarded to the container .如果您的客户端仅位于您的主机上,这会很好 - 请求始终转到 localhost,然后转发到容器

But, for apps in other containers, they need to point at the Kafka container, so it should say KAFKA_ADVERTISED_HOST_NAME: kafka , where kafka here is the name of the Docker Compose Service.但是,对于其他容器中的应用程序,它们需要指向 Kafka 容器,因此应该说KAFKA_ADVERTISED_HOST_NAME: kafka ,这里的kafka是 Docker Compose 服务的名称。 Then clients in other containers would try to connect to that one然后其他容器中的客户端会尝试连接到那个容器


That being said, then, this line话虽如此,那么这条线

consumer = KafkaConsumer('test', bootstrap_servers='localhost:9092')

You are pointing the Python container at itself , not the kafka container.您将 Python 容器指向自身,而不是kafka容器。

It should say kafka:9092 instead它应该改为kafka:9092

In my case I wanted to access the Kafka Container from an external python client running locally (as a producer) and here is the combination of containers and python code that worked for me (Platform MAC OS and docker version 2.4.0):就我而言,我想从本地运行的外部 python 客户端(作为生产者)访问 Kafka 容器,这里是对我有用的容器和 python 代码的组合(平台 MAC OS 和 docker 版本 2.4.0):

zookeeper container:动物园管理员容器:

docker run -d \
-p 2181:2181 \
--name=zookeeper \
-e ZOOKEEPER_CLIENT_PORT=2181 \
confluentinc/cp-zookeeper:5.2.3

kafka container:卡夫卡容器:

docker run -d \ 
-p 29092:29092 \ 
-p 9092:9092 \ 
--name=kafka \ 
-e KAFKA_ZOOKEEPER_CONNECT=host.docker.internal:2181 \ 
-e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=BROKER:PLAINTEXT,PLAINTEXT:PLAINTEXT \ 
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:29092,BROKER://localhost:9092 \ 
-e KAFKA_INTER_BROKER_LISTENER_NAME=BROKER \ 
-e KAFKA_BROKER_ID=1 \ 
-e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \ 
-e KAFKA_CREATE_TOPICS="test:1:1" \ 
confluentinc/cp-enterprise-kafka:5.2.3

python client:蟒客户端:

from kafka import KafkaProducer
import json
producer = KafkaProducer(bootstrap_servers=['localhost:29092'],
value_serializer=lambda v: json.dumps(v).encode('utf-8'),
security_protocol='PLAINTEXT')
acc_ini = 523416
print("Sending message")
producer.send('test', {'model_id': '1','acc':str(acc_ini), 'content':'test'})
producer.flush()

In my local setup, I had the same issue where all the containers were working fine inside the docker but the connectors were unable to connect to the Kafka.在我的本地设置中,我遇到了同样的问题,所有容器在 docker 内都工作正常,但连接器无法连接到 Kafka。

My Kafka configuration inside docker-compose.yml :我在docker-compose.yml的 Kafka 配置:

  broker:
    image: confluentinc/cp-server:7.0.1
    hostname: broker
    container_name: broker
    depends_on:
      - zookeeper
    ports:
      - "29092:29092"
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_LISTENERS: INTERNAL://:29092,EXTERNAL://:9092
      KAFKA_ADVERTISED_LISTENERS: INTERNAL://:29092,EXTERNAL://:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL

Based on google responses I tried localhost:port , 127.0.0.1:port , and 0.0.0.0:port as the URL in my connector config but nothing worked.根据谷歌的回复,我尝试了localhost:port127.0.0.1:port0.0.0.0:port作为连接器配置中的 URL,但没有任何效果。

Eventually, I had to pass the actual IP address of my local system and it worked.最终,我不得不传递本地系统的实际 IP 地址,并且它起作用了。 I'm using Docker on Windows 10.我在 Windows 10 上使用 Docker。

ActiveMQ Connector congif: ActiveMQ 连接器配置文件:

{
  "connector.class": "io.confluent.connect.activemq.ActiveMQSourceConnector",
  "activemq.url": "tcp://<my-system-ip>:61616", <-- my system's IP address
  "max.poll.duration": "60000",
  "tasks.max": "1",
  "batch.size": "1",
  "name": "activemq-jms-connector",
  "jms.destination.name": "jms-test",
  "kafka.topic": "topic-1",
  "activemq.password": "password",
  "jms.destination.type": "topic",
  "use.permissive.schema": "false",
  "activemq.username": "username"
}

I hope this will help anyone struggling with the Kafka-connect setup on Windows and Docker.我希望这能帮助任何在 Windows 和 Docker 上苦苦挣扎的Kafka-connect设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM