Spring boot 在kafka重新启动后,Spring boot producer无法发送任何消息
在kafka重新启动后,spring boot consumer micro服务无法向主题发送消息 使用docker swarm配置,我设置了单节点集群,其中有1个kafka代理和2个spring boot微服务(一个生产者和消费者)。 我使用的是spring boot 2.0.3Spring boot 在kafka重新启动后,Spring boot producer无法发送任何消息,spring-boot,docker,apache-kafka,Spring Boot,Docker,Apache Kafka,在kafka重新启动后,spring boot consumer micro服务无法向主题发送消息 使用docker swarm配置,我设置了单节点集群,其中有1个kafka代理和2个spring boot微服务(一个生产者和消费者)。 我使用的是spring boot 2.0.3 消费者和生产者(spring boot micro services)位于同一覆盖网络“net broker”上,因此他们使用服务名称“kafka:9092”访问kafka 第一次出发时一切都很顺利 然后,仅重新启
- 消费者和生产者(spring boot micro services)位于同一覆盖网络“net broker”上,因此他们使用服务名称“kafka:9092”访问kafka
- 第一次出发时一切都很顺利
- 然后,仅重新启动kafka,此后消费者将无法再发送来自kafka topic的消息
- 由于docker-compose.yml中的一个小更改,kafka服务重新启动(例如max_尝试次数:3=>max_尝试次数:4)
kafka:
image: wurstmeister/kafka:2.12-2.2.0
depends_on:
- zookeeper
networks:
- net-broker
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
max_attempts: 3
# ports:
# - target: 9094
# published: 9094
# protocol: tcp
# mode: host
environment:
HOSTNAME_COMMAND: "echo ${HOST_IP:-192.168.99.100}"
KAFKA_CREATE_TOPICS: "gnss-topic-${GNSS_TAG}:3:1"
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: INSIDE://:9092,OUTSIDE://_{HOSTNAME_COMMAND}:9094
KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:9094
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
BROKER_ID_COMMAND: "echo 101"
KAFKA_LOG_DIRS: "/kafka/kafka-logs"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- kafka-data:/kafka
KafkaProducerConfig类
@Bean
公共生产工厂生产工厂(){
Map configProps=new HashMap();
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,gnssConfig.getkafkabootstapserver());
//高吞吐量生产者(以牺牲一点延迟和CPU使用为代价)
configProps.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,“snappy”);
configProps.put(ProducerConfig.LINGER\u MS\u CONFIG,“20”);
configProps.put(ProducerConfig.BATCH\u SIZE\u CONFIG,Integer.toString(32*1024));//32 KB批大小
//序列化程序
configProps.put(ProducerConfig.KEY\u SERIALIZER\u CLASS\u CONFIG,StringSerializer.CLASS);
configProps.put(ProducerConfig.VALUE\u SERIALIZER\u CLASS\u CONFIG,JsonSerializer.CLASS);
返回新的DefaultKafkaProducerFactory(configProps);
}
kafka重启后的spring引导生成器日志:
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for gnss-topic-11.2.1-B5607-1: 30030 ms has passed since batch creation plus linger time
gnss_data-access.1.ll948jogpqil@GDN-S-GNSS2 | 2019-05-08 09:42:33.984 INFO 1 --- [ gnss-view-data] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer-1, groupId=gnss-view-data] Marking the coordinator fe7091944126:9092 (id: 2147483546 rack: null) dead
kafka重启后的spring引导使用者日志:
org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for gnss-topic-11.2.1-B5607-1: 30030 ms has passed since batch creation plus linger time
gnss_data-access.1.ll948jogpqil@GDN-S-GNSS2 | 2019-05-08 09:42:33.984 INFO 1 --- [ gnss-view-data] o.a.k.c.c.internals.AbstractCoordinator : [Consumer clientId=consumer-1, groupId=gnss-view-data] Marking the coordinator fe7091944126:9092 (id: 2147483546 rack: null) dead
我正在使用生产者/消费者微服务的“spring-kafka-2.1.7.RELEASE.jar”库
使用远程调试模式,我了解到使用者试图将消息发送到旧的“killed”容器ID,而不是使用服务名称“kafka:9092”。我不知道为什么。我找到了解决这个问题的办法 只是提醒一下:
- 卡夫卡只能从Docker net broker的覆盖虚拟网络访问
- 出于安全原因,不应从Docker主机IP访问Kafka
KAFKA\u advised\u侦听器中的以下更改修复了该问题
旧值(重新启动后不工作):
卡夫卡广播的监听器:内部://:9092,外部://{HOSTNAME\u COMMAND}:9094
新值(重新启动后工作):
KAFKA\u播发的\u侦听器:内部://{KAFKA:9092,外部://{HOSTNAME\u COMMAND}:9094
因此,修复方法是为内部播发侦听器指定kafka服务名称kafka:9092
问题是,即使spring引导生成器被配置为使用kafka:9092
configProps.put(ProducerConfig.BOOTSTRAP\u SERVERS\u CONFIG,kafka:9092);
制作人实际上是在使用kafka容器ID进行通信,而不是使用服务名称
kafka:9092
,因此在kafka重新启动后,创建了一个新容器(新容器ID),但制作人仍然指向旧容器ID,我找到了解决此问题的方法
只是提醒一下:
- 卡夫卡只能从Docker net broker的覆盖虚拟网络访问
- 出于安全原因,不应从Docker主机IP访问Kafka
KAFKA\u advised\u侦听器中的以下更改修复了该问题
旧值(重新启动后不工作):
卡夫卡广播的监听器:内部://:9092,外部://{HOSTNAME\u COMMAND}:9094
新值(重新启动后工作):
KAFKA\u播发的\u侦听器:内部://{KAFKA:9092,外部://{HOSTNAME\u COMMAND}:9094
因此,修复方法是为内部播发侦听器指定kafka服务名称kafka:9092
问题是,即使spring引导生成器被配置为使用kafka:9092
configProps.put(ProducerConfig.BOOTSTRAP\u SERVERS\u CONFIG,kafka:9092);
生产者实际上是在使用kafka容器ID进行通信,而不是使用服务名称
kafka:9092
,因此在kafka重新启动后,创建了一个新容器(新容器ID),但生产者仍然在:`configProps.put>中指向旧容器ID(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,gnssConfig.getKafkaBootstapServers());`gnssConfig.getKafkaBootstapServers()是IP、Docker容器ID还是simbolic名称?您好Pablo,首先非常感谢您考虑我的问题。gnssConfig.getKafkaBootstapServers()
将返回kafka:9092
中的服务名称:`configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,gnssConfig.getkafkabootstatservers());`gnssConfig.getkafkabootstatservers()是IP、Docker容器ID还是simbolic名称?您好,Pablo,首先非常感谢您考虑我的问题。gnssConfig.getkafkabootstapserver()
将返回kafka:9092
,这是服务名称