Spring 引导容器无法在另一个容器中找到 kafka 代理
Spring boot container cannot find kafka broker in another container
我有一个简单的 springboot 应用 运行ning 在 docker 容器中,配置如下。
@Configuration
public class ProducerConfiguration {
private static final String KAFKA_BROKER = "kafka:9092";
@Bean
public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigurations());
}
@Bean
public Map<String, Object> producerConfigurations() {
Map<String, Object> configurations = new HashMap<>();
configurations.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_BROKER);
configurations.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
configurations.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return configurations;
}
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
}
控制器class
@RestController
public class KafkaController {
private static final Logger LOGGER= LoggerFactory.getLogger(KafkaController.class);
private KafkaTemplate<String, String> template;
public KafkaController(KafkaTemplate<String, String> template) {
this.template = template;
}
@GetMapping("/kafka/produce")
public void produce(@RequestParam String message) {
template.send("test_topic", message);
}
}
在同一个项目中,下面是kafkadocker-compose.yml
version: '2.1'
services:
app:
restart: always
build:
context: ./
dockerfile: Dockerfile
image: app
container_name: app
ports:
- 8080
depends_on:
- kafka
- zookeeper
networks:
- network1
kafka:
image: wurstmeister/kafka
container_name: 'kafka'
environment:
JVM_OPTS: -Xmx1g -Xms1g -XX:MaxPermSize=1024m
KAFKA_ADVERTISED_HOST_NAME: kafka
KAFKA_ADVERTISED_PORT: 9092
KAFKA_CREATE_TOPICS: test_topic:1:1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
KAFKA_LISTENERS: INSIDE://kafka:9093,OUTSIDE://0.0.0.0:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9093,OUTSIDE://localhost:9092
depends_on:
- zookeeper
ports:
- 9092:9092
- 9093:9093
networks:
- network1
zookeeper:
container_name: 'zookeeper'
image: wurstmeister/zookeeper
networks:
- network1
networks:
network1:
问题:
当我在本地 运行 springboot 应用程序并尝试将消息发送到主题时,它有效 fine.but,当我 docker 使用 docker build -t my/app
然后 [=16] 化 springboot 应用程序时=] 然后尝试发送有关主题的消息 我收到以下错误
[Producer clientId=producer-1] Connection to node -1 (kafka/127.0.0.1:9092) could not be established. Broker may not be available.
我已经尝试了关于 KAFKA_ADVERTISED_HOST_NAME 的各种建议,但仍然没有用。
感谢对此的任何帮助。
编辑:我的 docker 文件是
FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn package
FROM openjdk:8-jre-alpine
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/app-0.0.1-SNAPSHOT.jar /app/
ENTRYPOINT ["java", "-jar", "app-0.0.1-SNAPSHOT.jar"]
根据评论,运行 您的 spring 在与 Kafka 相同的网络中启动有几件事。
找出Kafka在什么网络下,
docker inspect --format='{{json .NetworkSettings.Networks}}' <kafka_container_id>
response: {"<this_is_network_name>": ...}
要获得kafka_container_id
,可以使用docker ps
。
当您知道网络名称时,您可以像现在这样执行 运行 命令:
docker run --network <network_name> --publish=8080:8080 my/app
我注意到你更新了你的撰写文件,网络应该是这样的:
networks:
default:
external:
name: my-pre-existing-network
但是不需要将它们分配给现有网络,因为它们都包含在同一个 compose 中,因此默认情况下它们都将分配给同一个网络,因此类似于:
version: '2.1'
services:
app:
restart: always
build:
context: ./
container_name: app
ports:
- 8080:8080
depends_on:
- kafka
- zookeeper
kafka:
image: wurstmeister/kafka
container_name: 'kafka'
environment:
JVM_OPTS: -Xmx1g -Xms1g -XX:MaxPermSize=1024m
KAFKA_ADVERTISED_HOST_NAME: kafka
KAFKA_ADVERTISED_PORT: 9092
KAFKA_CREATE_TOPICS: test_topic:1:1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
KAFKA_LISTENERS: INSIDE://kafka:9093,OUTSIDE://0.0.0.0:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9093,OUTSIDE://localhost:9092
depends_on:
- zookeeper
ports:
- 9092:9092
- 9093:9093
zookeeper:
container_name: 'zookeeper'
image: wurstmeister/zookeeper
Dockerfile 也应该公开 8080(假设你想点击 spring 引导应用程序)
我有一个简单的 springboot 应用 运行ning 在 docker 容器中,配置如下。
@Configuration
public class ProducerConfiguration {
private static final String KAFKA_BROKER = "kafka:9092";
@Bean
public ProducerFactory<String, String> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigurations());
}
@Bean
public Map<String, Object> producerConfigurations() {
Map<String, Object> configurations = new HashMap<>();
configurations.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, KAFKA_BROKER);
configurations.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
configurations.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return configurations;
}
@Bean
public KafkaTemplate<String, String> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
}
控制器class
@RestController
public class KafkaController {
private static final Logger LOGGER= LoggerFactory.getLogger(KafkaController.class);
private KafkaTemplate<String, String> template;
public KafkaController(KafkaTemplate<String, String> template) {
this.template = template;
}
@GetMapping("/kafka/produce")
public void produce(@RequestParam String message) {
template.send("test_topic", message);
}
}
在同一个项目中,下面是kafkadocker-compose.yml
version: '2.1'
services:
app:
restart: always
build:
context: ./
dockerfile: Dockerfile
image: app
container_name: app
ports:
- 8080
depends_on:
- kafka
- zookeeper
networks:
- network1
kafka:
image: wurstmeister/kafka
container_name: 'kafka'
environment:
JVM_OPTS: -Xmx1g -Xms1g -XX:MaxPermSize=1024m
KAFKA_ADVERTISED_HOST_NAME: kafka
KAFKA_ADVERTISED_PORT: 9092
KAFKA_CREATE_TOPICS: test_topic:1:1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
KAFKA_LISTENERS: INSIDE://kafka:9093,OUTSIDE://0.0.0.0:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9093,OUTSIDE://localhost:9092
depends_on:
- zookeeper
ports:
- 9092:9092
- 9093:9093
networks:
- network1
zookeeper:
container_name: 'zookeeper'
image: wurstmeister/zookeeper
networks:
- network1
networks:
network1:
问题:
当我在本地 运行 springboot 应用程序并尝试将消息发送到主题时,它有效 fine.but,当我 docker 使用 docker build -t my/app
然后 [=16] 化 springboot 应用程序时=] 然后尝试发送有关主题的消息 我收到以下错误
[Producer clientId=producer-1] Connection to node -1 (kafka/127.0.0.1:9092) could not be established. Broker may not be available.
我已经尝试了关于 KAFKA_ADVERTISED_HOST_NAME 的各种建议,但仍然没有用。 感谢对此的任何帮助。
编辑:我的 docker 文件是
FROM maven:3.5.2-jdk-8-alpine AS MAVEN_BUILD
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn package
FROM openjdk:8-jre-alpine
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/app-0.0.1-SNAPSHOT.jar /app/
ENTRYPOINT ["java", "-jar", "app-0.0.1-SNAPSHOT.jar"]
根据评论,运行 您的 spring 在与 Kafka 相同的网络中启动有几件事。
找出Kafka在什么网络下,
docker inspect --format='{{json .NetworkSettings.Networks}}' <kafka_container_id>
response: {"<this_is_network_name>": ...}
要获得kafka_container_id
,可以使用docker ps
。
当您知道网络名称时,您可以像现在这样执行 运行 命令:
docker run --network <network_name> --publish=8080:8080 my/app
我注意到你更新了你的撰写文件,网络应该是这样的:
networks:
default:
external:
name: my-pre-existing-network
但是不需要将它们分配给现有网络,因为它们都包含在同一个 compose 中,因此默认情况下它们都将分配给同一个网络,因此类似于:
version: '2.1'
services:
app:
restart: always
build:
context: ./
container_name: app
ports:
- 8080:8080
depends_on:
- kafka
- zookeeper
kafka:
image: wurstmeister/kafka
container_name: 'kafka'
environment:
JVM_OPTS: -Xmx1g -Xms1g -XX:MaxPermSize=1024m
KAFKA_ADVERTISED_HOST_NAME: kafka
KAFKA_ADVERTISED_PORT: 9092
KAFKA_CREATE_TOPICS: test_topic:1:1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
KAFKA_LISTENERS: INSIDE://kafka:9093,OUTSIDE://0.0.0.0:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9093,OUTSIDE://localhost:9092
depends_on:
- zookeeper
ports:
- 9092:9092
- 9093:9093
zookeeper:
container_name: 'zookeeper'
image: wurstmeister/zookeeper
Dockerfile 也应该公开 8080(假设你想点击 spring 引导应用程序)