使用Docker Compose运行Google Pubsub emulator出现随机运行异常问题
1 不确定运行结果的原因
- 首先docker-compose配置里的依赖配置存在错误:
service_2的depends_on写的是不存在的服务名emulator,service_4的depends_on写的是不存在的服务名postgres,这两条依赖规则完全不生效,等于没配置启动顺序约束。 - 其次
depends_on默认只保证依赖的容器进入running状态,不会等待容器内的应用完全初始化完成:pubsub emulator容器启动后,内部服务还需要1-3秒才能正常处理请求;负责创建主题订阅的service_2执行完成之前,其他服务就算能连上pubsub也找不到对应的主题,自然会报错。 - 你提到的
restart: always不生效,大概率是应用代码只在启动时执行一次pubsub连接/订阅逻辑,失败后要么进程僵死不退出,要么抛出的错误被捕获后进程持续运行但不会重试订阅逻辑,docker只有在进程退出时才会触发重启规则。
2 修改端口后恢复正常属于巧合
端口配置和服务启动顺序、依赖就绪没有任何关联,修改端口后某次运行正常,只是刚好那次容器启动的时间差符合预期:pubsub emulator初始化完成、service_2完成主题创建的时间点,刚好早于其他服务执行订阅逻辑的时间点,属于随机出现的正常结果,没有必然性。
3 修复方案
- 第一步先修正配置错误:把
service_2的depends_on改为service_1,service_4的depends_on改为service_3。 - 第二步给核心依赖服务加健康检查,同时修改
depends_on规则增加就绪校验,3.9版本的compose完全支持该配置:
给service_1(pubsub emulator)增加健康检查,示例如下:
给healthcheck: test: ["CMD", "nc", "-z", "localhost", "8074"] interval: 2s timeout: 5s retries: 5service_2配置健康检查或者将其设置为任务型服务,执行完成退出码为0则视为就绪;
所有依赖pubsub的服务(service_2/service_4/service_5/service_6/service_7)的depends_on都增加condition: service_healthy约束,示例如下:depends_on: service_1: condition: service_healthy service_2: condition: service_healthy - 第三步优化应用重试逻辑:在代码中增加pubsub连接、订阅的退避重试逻辑,首次连接失败后间隔1/2/4秒依次重试,最多重试5-10次;如果不想修改代码,可以在容器启动入口前加入
wait-for类脚本,等待依赖的端口可访问后再启动主进程。 - 最后确认应用异常时的退出逻辑:如果连接pubsub、订阅主题失败且重试后仍不可用,让进程直接退出,触发docker的重启规则,避免僵死进程无法恢复。
内容的提问来源于stack exchange,提问作者Don Draper
相关产品推荐
相关产品推荐

