depends_on 解决 docker 容器依赖问题

news/2024/11/23 3:58:47/

如果你经常使用docker-compose启动服务的话,可能会遇到下面的问题:服务 B 依赖服务 A,需要服务 A 先启动,再启动服务 B

举个例子,在部署 kafka 集群的时候,需要启动两个kafka,并使用zookeeper做注册中心,docker-compose.yaml 文件如下

version: '3'
services:zookeeper:image: wurstmeister/zookeepercontainer_name: zookeeperports:- "2181:2181"networks:- kafka_netkafka1:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka1ports:- "9092:9092"environment:KAFKA_BROKER_ID: 1# 对应 server.properties 中 advertised.listeners 配置KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092# 对应 server.properties 中 listeners 配置KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka1:/kafkanetworks:- kafka_netkafka2:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka2ports:- "9093:9092"environment:KAFKA_BROKER_ID: 2KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka2:/kafkanetworks:- kafka_netnetworks:kafka_net:driver: bridge

此时会同时启动 3 个容器,zookeeper、kafka1 和 kafka2

$ docker-compose up -d
[+] Running 3/3⠿ Container kafka1     Started                                                                            11.6s⠿ Container kafka2     Started                                                                            11.5s⠿ Container zookeeper  Started                                                                            11.5s

使用docker logs查看kafka1启动日志

$ docker logs kafka1
...
[2023-05-06 02:20:49,851] FATAL [Kafka Server 1], Fatal error during KafkaServer startup. Prepare to shutdown (kafka.server.KafkaServer)
java.lang.RuntimeException: A broker is already registered on the path /brokers/ids/1. This probably indicates that you either have configured a brokerid that is already in use, or else you have shutdown this broker and restarted it faster than the zookeeper timeout so it appears to be re-registering.at kafka.utils.ZkUtils.registerBrokerInZk(ZkUtils.scala:417)at kafka.utils.ZkUtils.registerBrokerInZk(ZkUtils.scala:403)at kafka.server.KafkaHealthcheck.register(KafkaHealthcheck.scala:70)at kafka.server.KafkaHealthcheck.startup(KafkaHealthcheck.scala:50)at kafka.server.KafkaServer.startup(KafkaServer.scala:280)at kafka.server.KafkaServerStartable.startup(KafkaServerStartable.scala:38)at kafka.Kafka$.main(Kafka.scala:65)at kafka.Kafka.main(Kafka.scala)
[2023-05-06 02:20:49,854] INFO [Kafka Server 1], shutting down (kafka.server.KafkaServer)
[2023-05-06 02:20:49,860] INFO [Socket Server on Broker 1], Shutting down (kafka.network.SocketServer)
[2023-05-06 02:20:49,874] INFO [Socket Server on Broker 1], Shutdown completed (kafka.network.SocketServer)
...

日志抛出了个timeout异常,连接zookeeper超时了,这是因为在启动kafka1的时候,zookeeper还没启动完成,kafka1 在连接 zookeeper 的时候,就会报连接超时

这时候我们可以用depends_on来解决容器依赖问题,depends_on表示在启动本容器前,确保depends_on的容器先启动

加上depends_on后的docker-compose.yaml文件如下

version: '3'
services:zookeeper:image: wurstmeister/zookeepercontainer_name: zookeeperports:- "2181:2181"networks:- kafka_netkafka1:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka1ports:- "9092:9092"environment:KAFKA_BROKER_ID: 1# 对应 server.properties 中 advertised.listeners 配置KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092# 对应 server.properties 中 listeners 配置KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka1:/kafkadepends_on:- zookeepernetworks:- kafka_netkafka2:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka2ports:- "9093:9092"environment:KAFKA_BROKER_ID: 2KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka2:/kafkadepends_on:- zookeepernetworks:- kafka_netnetworks:kafka_net:driver: bridge

再次启动服务

$ docker-compose up -d 
[+] Running 3/3⠿ Container zookeeper  Started                                                                             0.5s⠿ Container kafka2     Started                                                                             0.9s⠿ Container kafka1     Started                                                                             1.0s

docker logs查看kafka启动日志,发现容器正常启动

到这里我们已经解决了容器的启动顺序问题,但是多启动几次会发现,kafka连接zookeeper超时的问题还是会发生,而且是偶发性的,这是为什么呢?查阅资料发现,**depends_on**只是解决容器启动顺序的问题,但是无法保证容器启动完成,或者说并不会等待**zookeeper**就绪就直接启动**kafka**,这时候如果zookeeper还在启动中,kafka就发起连接请求,此时请求就会超时

解决方案是在depends_on中加入condition属性,conditon能使用下面三种状态

  • serveice_started: 容器启动完成
  • service_healthy:容器处于healthy状态,healthy状态的检查依赖healthcheck
  • service_completed_successfully:在启动依赖服务之前,需要确保依赖服务已经成功完成运行

这里我们使用service_healthy,当zookeeper处于healthy状态的时候,再启动kafka

version: '3'
services:zookeeper:image: wurstmeister/zookeepercontainer_name: zookeeperports:- "2181:2181"networks:- kafka_netkafka1:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka1ports:- "9092:9092"environment:KAFKA_BROKER_ID: 1# 对应 server.properties 中 advertised.listeners 配置KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092# 对应 server.properties 中 listeners 配置KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka1:/kafkadepends_on:zookeeper:condition: service_healthynetworks:- kafka_netkafka2:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka2ports:- "9093:9092"environment:KAFKA_BROKER_ID: 2KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka2:/kafkadepends_on:zookeeper:condition: service_healthynetworks:- kafka_netnetworks:kafka_net:driver: bridge

启动服务试一下

$ docker-compose up -d
[+] Running 3/4⠿ Network kafka_kafka_net  Created                                                                         0.0s⠿ Container zookeeper      Waiting                                                                         1.0s⠿ Container kafka1         Created                                                                         0.1s⠿ Container kafka2         Created                                                                         0.1s
container for service "zookeeper" has no healthcheck configured

这里提示zookeeper服务没有配置healthcheck,这是因为,docker 只能启动服务,并不知道容器内的进程什么时候处于healthy状态,所以需要我们自己配置健康检查,不同的进程有不同的健康检查方法,检查zookeeper是否正常启动完成,可以执行echo 'stat' | nc localhost 2181 || exit 1命令,命令返回 0 表示容器healthy,返回 1 表示unhealthyhealthy还能配置其他参数,如时间间隔、超时等,完整的配置如下

version: '3'
services:zookeeper:image: wurstmeister/zookeepercontainer_name: zookeeperports:- "2181:2181"networks:- kafka_nethealthcheck:test: echo 'stat' | nc localhost 2181 || exit 1interval: 5stimeout: 5sretries: 6kafka1:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka1ports:- "9092:9092"environment:KAFKA_BROKER_ID: 1# 对应 server.properties 中 advertised.listeners 配置KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092# 对应 server.properties 中 listeners 配置KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka1:/kafkadepends_on:zookeeper:condition: service_healthynetworks:- kafka_netkafka2:image: wurstmeister/kafka:2.11-0.11.0.3container_name: kafka2ports:- "9093:9092"environment:KAFKA_BROKER_ID: 2KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka2:9092KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092KAFKA_ADVERTISED_PORT: 9092KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181volumes:- ./data/kafka2:/kafkadepends_on:zookeeper:condition: service_healthynetworks:- kafka_netnetworks:kafka_net:driver: bridge
$ docker-compose up -d
[+] Running 4/4⠿ Network kafka_kafka_net  Created                                                                         0.0s⠿ Container zookeeper      Healthy                                                                         6.0s⠿ Container kafka1         Started                                                                         6.5s⠿ Container kafka2         Started                                                                         6.4s

可以看到,kafka会等待zookeeper启动,并处于healthy状态,再启动

到这里我们已经彻底解决docker容器依赖问题啦,如果喜欢我的文章的话可以关注公众号:huangxy,不定期分享技术知识

在这里插入图片描述


http://www.ppmy.cn/news/82074.html

相关文章

Python常见面试题. Python中的解包操作及其应用场景

这是个简单的知识点,但有的同学并不理解 unpacking解包 解,对应的是*或者**,也有自动解包之说 包对应的可迭代对象 Python助学大礼包点击跳转获取 目录 一、自动解包二、数据过多的解包*三、星号在函数中的使用四、两个星号的解包五、场…

面试官:MySQL自增主键一定是连续的吗?

测试环境: MySQL版本:8.0 数据库表:T (主键id,唯一索引c,普通字段d) 如果你的业务设计依赖于自增主键的连续性,这个设计假设自增主键是连续的。但实际上,这样的假设是错的…

在 windows 下如何安装 pytorch?

在 Windows 上安装 PyTorch 可以使用 pip 或 conda 管理包。 以下是使用 pip 安装 PyTorch 的步骤: 打开命令提示符或 PowerShell; 运行以下命令安装 PyTorch: pip install torch torchvision torchaudio如果你需要指定安装的版本&#xff…

Linux(Ubuntu)安装和使用Edge浏览器

全文内容完全由AI创作,并通过人工核验,感谢各位的阅读。 Microsoft Edge是一款现代化的浏览器,它拥有众多功能和强大的性能,为用户带来更加流畅的浏览体验。 Edge最近推出了分屏功能,支持一个窗口同时显示两个选项卡&…

VS Code Remote Development

1、Ubuntu 上启用 SSH (1)打开终端,并且安装openssh-server软件包: sudo apt update sudo apt install openssh-server 当被提示时,输入你的密码并且按 Enter,继续安装。 (2)安…

Kubectl-AI: 一款 OpenAI GPT 自动生成应用 K8s yaml神器

首页: 官网 下载安装 wget https://github.com/sozercan/kubectl-ai/releases/download/v0.0.10/kubectl-ai_linux_amd64.tar.gz tar xvf kubectl-ai_linux_amd64.tar.gz -C /usr/local/bin/kubectl-ai需要OpenAI API密钥或Azure OpenAI服务 API密钥和端点以及有效的Kubernet…

SpringBoot整合Mybatis(3000字)

SpringBoot整合Mybatis 文章目录 SpringBoot整合Mybatis依赖导入配置信息(application.yml)代码分层数据库(建库建表语句)各层代码enity:dao:service:controller: 测试 Mybatis分页查询和模糊查询分页查询:测试: 模糊查询:测试: Mybatis的分布查询多对一:测试:一对多: Mybatis的…

数据结构之堆详解

目录 1.什么是堆 堆的定义 结构体定义与函数接口 堆的初始化 堆的销毁 入堆 向上调整算法 大堆 出堆 向下调整算法 返回堆顶元素 判空 堆的应用 1.什么是堆 知道以上的存储方法,对于完全二叉树,有一个叫做堆的结构,堆本质就是一…