spring-boot - Spring Boot 容器在另一个容器中找不到 kafka 代理
问题描述
我有一个简单的 springboot 应用程序在 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());
}
}
控制器类
@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);
}
}
在同一个项目中,以下是 kafka 的 docker-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 应用程序并尝试将消息发送到主题时,它工作正常。但是,当我使用 dockerize springboot 应用程序docker build -t my/app
然后docker run --publish=8080:8080 my/app
尝试在主题上发送消息时,我收到以下错误
[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 的各种建议,但仍然无法正常工作。 感谢您对此的任何帮助。
编辑:我的 dockerfile 是
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"]
解决方案
根据评论,有一些事情可以在与 Kafka 相同的网络中运行您的 Spring Boot。
找出卡夫卡在什么网络下,
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
但是不需要将它们分配给现有网络,因为它们都包含在同一个组合中,所以默认情况下它们都将被分配到同一个网络,所以类似于:
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 Boot 应用程序)
推荐阅读
- activemq-artemis - Apache Artemis 没有 clientId 显示在 management-console.UI 的使用者部分
- mysql - 使用 sql 和 vb.net 将条目更改为指定范围数
- java - 使用流过滤 POJO 列表 - 无法投射 ClassCastException java.util.LinkedHashMap
- amazon-web-services - 如何将 iam:PermissionsBoundary 添加到通过 CloudFormation 模板创建的角色
- mysql - 无法添加或更新子行:
- java - 在java JDBC中将参数附加到准备好的语句并打印查询
- javascript - 类型错误:MOD.hasPermissions 不是函数
- email - 在 mailgun 上使用子域时如何接收发送到 rootdomain 的电子邮件?
- java - 使用opencsv beanwriter时如何指定列顺序?
- python - Count business day between using pandas columns