java - 如何在docker内部获取kafka的解析网络?

标签 java docker apache-kafka

我有一个 spring 应用程序,它应该连接到 kafka。这是我的 Docker 文件寻找 spring 应用程序的内容:

FROM maven:3-jdk-11 as builder
# create app folder for sources
RUN mkdir -p /build
WORKDIR /build
COPY pom.xml /build
#Download all required dependencies into one layer
RUN mvn -B dependency:resolve dependency:resolve-plugins
#Copy source code
COPY src /build/src
# Build application
RUN mvn package

FROM openjdk:8-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

kafka/Postgres/zookeeper 其他一切都来自 Docker 镜像。所以想到会在 docker compose 中运行应用程序,所以它看起来像下面这样:
version: '3.1'
services:
    postgres:
        image: debezium/postgres
        environment:
          POSTGRES_PASSWORD: qwerty
          POSTGRES_USER: appuser
        volumes:
           - ./postgres:/data/postgres
        ports:
          - 6532:6532
    zookeeper:
        image: confluentinc/cp-zookeeper
        ports:
          - "2181:2181"
        environment:
          ZOOKEEPER_CLIENT_PORT: 2181
    kafka:
        image: confluentinc/cp-kafka
        depends_on:
          - zookeeper
          - postgres
        ports:
          - "9092:9092"
        environment:
          KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
          KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092
          KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
          KAFKA_LOG_CLEANER_DELETE_RETENTION_MS: 5000
          KAFKA_BROKER_ID: 1
          KAFKA_MIN_INSYNC_REPLICAS: 1
          KAFKA_ADVERTISED_HOST_NAME: kafka
    connector:
        image: debezium/connect:latest
        ports:
          - "8083:8083"
        environment:
          GROUP_ID: 1
          CONFIG_STORAGE_TOPIC: my_connect_configs
          OFFSET_STORAGE_TOPIC: my_connect_offsets
          BOOTSTRAP_SERVERS: kafka:9092
        depends_on:
          - zookeeper
          - postgres
          - kafka
    app-server:
    # Configuration for building the docker image for the backend service
        build:
          context: . # Use an image built from the specified dockerfile in the `polling-app-server` directory.
          dockerfile: Dockerfile
        ports:
          - "8080:8080" # Forward the exposed port 8080 on the container to port 8080 on the host machine
        restart: always
        depends_on: 
          - kafka 
          - zookeeper
          - postgres
          - connector
        environment:
          BOOTSTRAP_SERVERS: kafka:9092  

我传递了一个环境变量 BOOTSTRAP_SERVERS值为 kafka:9092 (因为 localhost:9092 在我的 docker 环境中不起作用)。

在我的 spring 代码中,我得到如下值:
System.getenv("bootstrap.servers")
// or
System.getenv("BOOTSTRAP_SERVERS")

但是,当我运行 docker-compose up ,我得到的值为null对于上面的Java代码。不确定,为我的 kafka 获取 docker 解析网络的最佳方法是什么。

那么如何修复它,以便 java 代码在 docker 环境中获取 Kafka 代理呢?

最佳答案

以下是一些可能无法为您提供完整解决方案的建议(您的问题可能来自其他地方或其他系统问题),但也可能对您有所帮助:

一)未成年人修复和改进 docker-compose 文件

来自 docs您可以使用 字典 列表 定义环境参数。在您的情况下,您决定使用字典,但也许您可以尝试在此处使用列表(或我在下面解释的 .env 文件):

1)您应该在每个新定义的开头添加一个“-”

2)你应该使用等号(不是列)

3) 最后但并非最不重要的 :由于您的变量包含特殊字符(端口列),您应该使用引号转义所有定义:

    environment:
       - 'BOOTSTRAP_SERVERS=kafka:9092'

现在,如果您真的想使用字典表示法,您仍然需要转义列 ("kafka:9092") 否则这可能会(由 YAML 解析器)解释为新的嵌套字典( see here example of host connections strings )

所以 :
environment:
   BOOTSTRAP_SERVERS: 'kafka:9092'

但最佳做法是使用 .env文件,其内容很简单:
BOOTSTRAP_SERVERS=kafka:9092
然后删除您的 environment从您的 docker-compose 定义并传递此选项:
env_file:
  - ./<name_of_your_env_file>.env

现在请记住,如果您决定同时使用 .env,则环境定义中存在优先级。文件,environmentshell变量(例如)(See here) .

  1. Compose file
  2. Shell environment variables
  3. Environment file
  4. Dockerfile
  5. Variable is not defined


二) Tomcat默认嵌入式服务器

我发现的另一件事:

因为您使用的是 Spring:它的默认嵌入式服务器是 Tomcat(除非您在依赖项中更改了它)。
来自 AWS doc (即使您不使用它,它也可以引导您找到解决方案):

the Java SE platform sets environment variables that you retrieve with System.getenv, while the Tomcat platform sets Java system properties that you retrieve with System.getProperty.



所以也许尝试:
System.getProperty("BOOTSTRAP_SERVERS")

三)完全不需要定义这个环境变量 :

最后一件事(正如我在问题评论中所说):当您使用 docker-compose 时, jetty 网是由这个工具为你构建的。

可以通过调用您在 yaml 文件中提供的服务名称来访问每个容器。

所以在你的代码中,你只需要调用“kafka”服务。

现在,如果您使用环境变量,当然,它为您注入(inject)不同的服务名称进行测试提供了一些灵 active (假设明天您想使用 NATS 或 RabbitMQ,您将能够通过更改环境变量来更改依赖关系)但作为第一步,也许您可​​以尝试直接调用“kafka”服务并查看它是否已连接:通过这种方式,您将消除这种可能性......

关于java - 如何在docker内部获取kafka的解析网络?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62129147/

相关文章:

java - 检测 Java 中的 Dll

java - 子模块中不会继承 Maven 配置文件

Java NIO。模拟基本下载应用程序是否有效的解决方案?

docker - 无法连接到Kafka

java - 如何在Java中解析包含多个工作表、内存在50MB以内的xls文件

django - 如何在 Docker Compose 中将目录从一个容器复制到另一个容器?

docker - 如何在 standalone.xml 中注册 keycloak 模块(docker 上的 keycloak)

docker - Sublime 插件在 docker 容器中执行

scala - DataFrame 到 RDD[(String, String)] 的转换

java - 类型不匹配 : cannot convert from Map<String, ConsumerRecords<String,Supplier>> 到 ConsumerRecords<String,Supplier>