首页 > 解决方案 > 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"]

标签: spring-bootapache-kafkadocker-composespring-kafka

解决方案


根据评论,有一些事情可以在与 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 应用程序)


推荐阅读