1
votes

I am running into a problem with spring boot kafka docker, tried all the things mentioned in the below link but the issues still remain.

Spring Boot containers can not connect to the Kafka container

Attaching my docker-compose.yml

version: '2'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    container_name: zookeeper
    ports:
    - "2181:2181"
  kafka:
    image: wurstmeister/kafka
    container_name: kafka
    ports:
    - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
  my-app:
    image: my-app
    container_name: my-app
    ports:
      - "8081:8081"
    depends_on:
      - zookeeper
      - kafka

The error log

-1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available.
my-app     | 2020-11-03 08:10:21.444  WARN 1 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient   : [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available.

I am running wrustmiester/kafka and wrustmiester/zookeeper. If I run locally the spring boot app, everything runs smoothly.
The issue comes when I try to build an image of my spring boot app and run that image. Then the error is Broker may not be available.
Please if anyone can guide me.

Adding my application.yml

spring:
  kafka:
    consumer:
      bootstrap-servers: localhost:9092
      group-id: group_id
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      #org.apache.kafka.common.serialization.StringDeserializer
      properties.spring.json.trusted.packages: com.myapp.pojo

    producer:
      bootstrap-servers: localhost:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
      #org.apache.kafka.common.serialization.StringSerializer

Updated my docker-compose.yml as

version: '3'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    container_name: zookeeper
    network_mode: bridge
    ports:
    - "2181:2181"
  kafka:
    image: wurstmeister/kafka
    container_name: kafka
    network_mode: bridge
    ports:
    - "9092:9092"
    hostname: kafka
    environment:
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
     # KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:9094
     # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
     # KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
      KAFKA_ADVERTISED_PORT: 9092
    links:
      - zookeeper
  my-app:
    image: my-app
    container_name: my-app
    network_mode: bridge
    ports:
      - "8081:8081"
    depends_on:
      - zookeeper
      - kafka

Updated my application.yml as

spring:
  kafka:
    consumer:
      bootstrap-servers: kafka:9092
      group-id: group_id
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
      #org.apache.kafka.common.serialization.StringDeserializer
      properties.spring.json.trusted.packages: com.myapp.pojo

    producer:
      bootstrap-servers: kafka:9092
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
      #org.apache.kafka.common.serialization.StringSerializer

Error log is same

WARN 1 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient   : [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available.
my-app     | 2020-11-03 17:05:39.585  WARN 1 --- [| adminclient-1] org.apache.kafka.clients.NetworkClient   : [AdminClient clientId=adminclient-1] Connection to node -1 (localhost/127.0.0.1:9092) could not be established. Broker may not be available.
5
Just providing a link won't help , please tell me where i have made errorAjinkya Karode
As mentioned in the blog, connecting to localhost is incorrect. Within the app container, it refers to the app container, not the broker. Your producer and consumer cannot connect to anything within the app containerOneCricketeer

5 Answers

1
votes

I was able to resolve my issue.

Here is my updated docker-compose.yml that works and the rest of the configuration is the same as above

version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper:latest
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
      ZOOKEEPER_TICK_TIME: 2000

  kafka:
    image: confluentinc/cp-kafka:latest
    depends_on:
      - zookeeper
    ports:
      - 9092:9092
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1

  my-app:
    image: my-app
    container_name: my-app
    environment:
      SPRING_KAFKA_BOOTSTRAPSERVERS: kafka:29092
    ports:
      - "8081:8081"
    depends_on:
      - kafka

Changes made were

  1. I have used confluent Kafka and zookeeper but even the above docker-compose.yml with wrustmeister Kafka and zookeeper would work.

  2. Most important property

    environment: SPRING_KAFKA_BOOTSTRAPSERVERS: kafka:29092

  3. Also as suggested by @OneCricketeer

Alternatively, if all three clients are communicating with the same cluster, remove bootstrap servers from the producer and consumer, and set it globally with spring.kafka.bootstrap-servers

Even this should work I feel.
Maybe I can try this sometime later and will update my answer.

0
votes

I had done same thing in almost same way(small difference), just have a look at the below compose-file, if this works for you

version: '3'

services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - 2181:2181
  kafka:
    image: wurstmeister/kafka
    ports:
      - 9092:9092
    hostname: kafka
    environment:
      - KAFKA_ADVERTISED_HOST_NAME=kafka
      - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
      - KAFKA_ADVERTISED_PORT=9092
    links:
      - zookeeper
0
votes

Your error is coming from the AdminClient, so if you aren't manually creating an instance of that in your code, you need to add a config section for spring.kafka.admin.* with bootstrap-servers set there as well

Alternatively, if all three clients are communicating with the same cluster, remove bootstrap servers from the producer and consumer, and set it globally with spring.kafka.bootstrap-servers

Since you're using Docker networking, the address will need to be the Kafka container's hostname. Also note that links are a deprecated Compose feature and shouldn't be relied on

0
votes

can you try this once

version: '3'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    container_name: zookeeper
    ports:
    - "2181:2181"
  kafka:
    image: wurstmeister/kafka
    container_name: kafka
    ports:
    - "9092:9092"
    hostname: kafka
    environment:
      KAFKA_ADVERTISED_HOST_NAME: kafka
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
     # KAFKA_LISTENERS: INSIDE://:9092,OUTSIDE://:9094
     # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT
     # KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
      KAFKA_ADVERTISED_PORT: 9092
    links:
      - zookeeper
  my-app:
    image: my-app
    container_name: my-app
    ports:
      - "8081:8081"
    depends_on:
      - zookeeper
      - kafka
networks:
  default:
    external:
      name: bridge
0
votes

I fixed by configuring a KafkaAdmin bean in my Spring-Boot application and passing the bootstrap-servers property:

@SpringBootApplication
public class CpoExecutorApplication {

    @Value("${spring.kafka.template.default-topic}")
    private String topicName;

    @Value("${spring.kafka.bootstrap-servers}")
    private String bootstrapAddress;

    @Bean
    public KafkaAdmin kafkaAdmin() {
        Map<String, Object> configs = new HashMap<>();
        configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress);
        return new KafkaAdmin(configs);
    }

    @Bean
    public NewTopic processTopic() {
        return TopicBuilder.name(topicName).partitions(2).build();
    }
....

application.yml

server:
  port: 8000
spring:
  kafka:
    bootstrap-servers: localhost:9094
    consumer:
      auto-offset-reset: false
    template:
      default-topic: process-topic
.....

This way I didn't need to pass the SPRING_KAFKA_BOOTSTRAPSERVERS environment variable in docker-compose.yml.