docker容器优雅停机导致的问题说明

现象

测试同学反馈页面某功能有时候不能使用。

分析

根据页面返回结果和URL,从开发同学那里了解到该现象是新环境里a服务调b服务返回异常导致的。从多次请求的结果看来,大概50%的几率返回异常。按常理判断如果b服务有多个节点的,可能有其中个别节点异常会导致此现象发生,但是b服务只有一个节点,请求的同时,观察b服务的日志,在a调用结果异常的情况下,b没有任何日志输出,正常情况日志输出返回结果,说明请求没有到达b服务,如果对调用链路不熟的情况下完全可以抓包明确请求是否到达。那么调用失败的请求是去哪里了呢?调用链路如下:

图1
图1可以看出a调用b的地址是从consul-server上拿到的,在consul-server控制台看到的情况入下图:

图2
注:图中gw-mini是服务b
图2 中看到单节点的b服务,在consul注册中心上注册了两个实例,实际是这样吗?继续看下图:

图3
图3中b服务是单节点,ip是10.100.73.72,而consul-server中的另外一个地址10.100.73.75是其他服务的ip地址。在consul上b服务下面的两个实例健康检查都是正常状态,难怪a调用b老是出现异常的返回结果,a拿到的地址list里面有一个地址是不对的。为什么consul上b服务会有两个实例?看看异常实例10.100.73.75的详情,如下图:

图4
健康检查URL是b服务的没错,返回结果也正常,http status_code 200,跳了统一登录认证,此处其实是有拦截器导致返回结果是200。在此服务中还有其他实例,但是处于异常状态,下图所示:

图5
在k8s集群中,服务所在pod的ip(即:注册到consul上的ip地址)是根据网络插件配置自动分配的,每次更新服务都会重建pod,pod ip也会随之改变。此时基本可以确定,在更新的时候,注册在consul上的老版本实例没有及时移除掉,其使用的ip在k8s回收之后重新分配给了新服务的pod,且新服务里面有拦截器,所有请求先跳转登录,因此导致了这样的问题出现,如果服务多了问题会更加严重。
拉了开发同学一起看看,是不是服务在关闭的时候不会反注册,从consul上下线自己。开发同学在本地IDE启动服务,点停止按钮(发送SIGTERM信号)的时候日志打印出deregister service相关内容,且在几秒钟后测试consul上服务也自动下线了。但是在出问题的新环境里面,更新服务时没有看到任何反注册日志,服务也不会从consul上自动下线,可以判定是优雅停机出现了问题。有查阅docker官方文档,在docker中,容器停止的时候会给进程号为1的进程发送SIGTERM,且在默认10s之后进程还没退出的话发送SIGKILL信号强制关闭。查看此项目dockerfile,其中entrypoint是以shellform格式运行了一个bash脚本,在bash脚本中启动了java进程,以此种方式运行的进程,实际上上是sh –c的子命令,且不会传递信号给entrypoint进程,所以在关闭的时候java进程并没有收到优雅停机信号,自然也没机会通知consul下线服务。

处理

两方面,一个是让java进程能够接收到SIGTERM信号,另一个是健康检查的问题。
第一个问题,整改dockerfile,entrypoint采用execform的格式写,且完全没必要放在bash脚本里面,直接启动java进程。
第二个问题,对健康检查URL去掉拦截。
还有一方面就是设置pod lifecycle,添加prestop钩子。

结果

整改之后,服务关闭的时候正常输出deregister service信息,consul-server上也会自动下线服务。此异常页面再没出现过类似问题。

原文地址:https://blog.51cto.com/weifan/2483460

时间: 2024-10-02 11:31:31

docker容器优雅停机导致的问题说明的相关文章

Docker 容器与宿主机网段冲突导致网络无法 ping 通的解决方案

docker 容器网络默认使用 bridge 桥接模式,正常情况下,容器会使用 daemon.json 中定义的虚拟网桥来与宿主机进行通讯. 最近更新 Docker for mac 之后,发现以前容器中可以访问的局域网内服务(使用宿主机所在的局域网 IP 访问),变得不可访问了.一开始以为是新版本改了默认网络配置,查了半天 release log 并没有找到相关条目. 后来在同事的帮助下发现问题所在: 由于换了新的工位,宿主机的局域网 IP 网段由 172.16.*.* 切换到了 172.17.

理解Docker容器的进程管理

摘要: Docker在进程管理上有一些特殊之处,如果不注意这些细节中的魔鬼就会带来一些隐患.另外Docker鼓励"一个容器一个进程(one process per container)"的方式.这种方式非常适合以单进程为主的微服务架构的应用.然而由于一些传统的应用是由若干紧耦合的多个进程构成的,这些进程难以 Docker在进程管理上有一些特殊之处,如果不注意这些细节中的魔鬼就会带来一些隐患.另外Docker鼓励"一个容器一个进程(one process per contain

Dubbo源码学习--优雅停机原理及在SpringBoot中遇到的问题

相关文章: Dubbo源码学习文章目录 前言 主要是前一阵子换了工作,第一个任务就是解决目前团队在 Dubbo 停机时产生的问题,同时最近又看了一下 Dubbo 的源码,想重新写一下 Dubbo 相关的文章. 优雅停机原理 对于一个 java 应用,如果想在关闭应用时,执行一些释放资源的操作一般是通过注册一个 ShutDownHook ,当关闭应用时,不是调用 kill -9 命令来直接终止应用,而是通过调用 kill -15 命令来触发这个 ShutDownHook 进行停机前的释放资源操作.

Dubbo 优雅停机演进之路

一.前言 在 『ShutdownHook- Java 优雅停机解决方案』 一文中我们聊到了 Java 实现优雅停机原理.接下来我们就跟根据上面知识点,深入 Dubbo 内部,去了解一下 Dubbo 如何实现优雅停机. 二.Dubbo 优雅停机待解决的问题 为了实现优雅停机,Dubbo 需要解决一些问题: 新的请求不能再发往正在停机的 Dubbo 服务提供者. 若关闭服务提供者,已经接收到服务请求,需要处理完毕才能下线服务. 若关闭服务消费者,已经发出的服务请求,需要等待响应返回. 解决以上三个问

docker容器网络通信原理分析

概述 自从docker容器出现以来,容器的网络通信就一直是大家关注的焦点,也是生产环境的迫切需求.而容器的网络通信又可以分为两大方面:单主机容器上的相互通信和跨主机的容器相互通信.而本文将分别针对这两方面,对容器的通信原理进行简单的分析,帮助大家更好地使用docker. docker单主机容器通信 基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,容器具有完全独立的网络栈,与宿主机隔离,也可以使容器共享主机或者其他容器的网络命名空间,基本可以

Docker入门实战-SSH连接docker容器

简介 什么是Docker Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目.它基于 Google 公司推出的 Go 语言实现. 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护. Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc.Redhat 已经在其 RHEL6.5 中集中支持 Docker:Google 也在其 PaaS

日志系统之基于flume收集docker容器日志

最近我在日志收集的功能中加入了对docker容器日志的支持.这篇文章简单谈谈策略选择和处理方式. 关于docker的容器日志 docker 我就不多说了,这两年火得发烫.最近我也正在把日志系统的一些组件往docker里部署.很显然,组件跑在容器里之后很多东西都会受到容器的制约,比如日志文件就是其中之一. 当一个组件部署到docker中时,你可以通过如下命令在标准输出流(命令行)中查看这个组件的日志: docker logs ${containerName} 日志形如: 但这种方式并不能让你实时获

Docker容器是否可以改变世界?

Docker容器是否可以改变世界? 2016-01-15 杜亦舒 2016年了,很多大牛开始预测技术趋势,其中一个普遍的观点我也很认同: Docker会更加流行,会改变程序世界 2015年的上半年我接触了Docker,熟悉之后,真有一点震惊的感觉,太方便了,可以解决很多问题 Container 通常翻译为容器,但还有另一个意思,就是"集装箱" 集装箱是21世纪最伟大的发明之一,它改变了世界货物运输体系,造就了一个高度自动化.标准化.低成本的物流体系,促进了经济的全球化发展 程序界也出现

docker容器从入门到实战0826

##docker容器安装和配置### #docker的git-hub网站(账号rshare,密rshare520):https://github.com/login #docker官网hub仓库(账号flyer520,密码rhsare520):https://hub.docker.com #docker官网文档和镜像:https://docs.docker.com/samples/centos/ #docker官网的容器网络配置:https://docs.docker.com/engine/us