1 起因

事件的起因是这样的,我们在微服务改造的过程中,选择将服务注册到eureka中,开发的时候还好,使用场景是这样的:

  • 在idea中启动服务,成功注册到eureka,关闭服务,eureka成功注销该服务实例
  • java -jar方式启动服务,成功注册到eureka中,ctrl-c停止服务,eureka成功注销该服务实例

有一天,在服务器上部署服务的时候,我们选择了docker启所有的服务,预料之外的事情发生了:

docker run 服务成功注册到eureka,docker stop之后,eureka却没有将该服务实例注销, 那就docker rm 将容器删除,eureka中这个服务实例还是存在,这样每docker run一下,eureka中就会多注册一个实例,就多了好多僵尸实例。

eureka有问题?还是docker启服务有问题?

我docker容器都干掉了,eureka中还存在这有点儿说不过去吧

2 手动下线

eureka不能自动给下线我就手动delete一下吧

DELETE http://{ip}:{port}/eureka/apps/{appName}/{inatanceId}

3 改实例ID

但是这样就是你每重启一下就得删一下,很麻烦。发现容器启的实例id都有个特点,containerId:服务名称:服务端口号,物理机上启的主机ip:服务名称:服务端口号

那就eureka.instance.instance-id=${spring.application.name}:${server.port}定制一下实例id,这样docker run的服务端口相同的话,实例id就会相同,比如都是rms:8080,这样docker run多少次也不会有那么多僵尸实例了,后起的会把前边儿启的同id实例挤掉。

但是这也并没有从实质上解决自动下线问题,到底是为什么呢?

4 优雅的停止容器

直到看到一个知识点儿你真的优雅的停止容器了吗?不就是docker stop吗,其实:

当你发出Docker stop命令时,Docker会很好地要求进程停止,如果进程在10秒内没有关闭,它将强制终止进程。

docker stop命令首先尝试通过向容器中的根进程(pid 1)发送sigterm信号来停止正在运行的容器。如果进程在超时期间没有退出,则发送SIGKID信号。

虽然进程可以选择忽略sigterm,但sigkill直接进入内核,内核将终止进程。这个过程根本看不到信号。

使用Docker Stop时,唯一可以控制的是Docker守护进程在发送sigkill之前等待的秒数:docker stop --time=30 foo

这才慌然大悟,启容器,进入容器,杀进程:

这里如果kill -9 同样不能正常下线,原因看图,-9 也是发送的SIGKILL

忽然想到java -jar 方式起的服务可以正常注册到eureka,ctrl-c可以正常停止进程使eureka成功注销该实例,如果我nohup java -jar启的服务,就不能ctrl-c了

只能kill掉进程了,贯用的kill -9 pid,发现这样杀死的服务实例,确实eureka中也没有下线。这样就与docker stop服务实例不能正常注销的原因一致了。

看来不能高兴的太早,发现docker stop指定时间不好使:

docker stop --time=80 rms-consul

等呀等,真的等了80s强制退出,eureka并没有注销该实例,感觉这种方式不太好把握进程停止真正需要的时间,也可能这种方式就是无效。

到底应该如何优雅的停止容器?https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/

试了一圈还是这好使:

5 docker 不能正常停止服务是因为没有正确的开始

说好的优雅停止容器,为啥还是不能优雅的解决问题呢?到目前为止其实就是正常的kill解决了问题,继续找原因。找到dockerfile

ENTRYPOINT [ "sh", "-c", "/start.sh"]
$ cat start.sh
java -jar /apps/rms.jar

这个问题是shell script接收SIGTERM信号,而没有发送给通过shell脚本生成的java进程,因此spring boot无法正常退出。

解决办法:

通过运行exec命令,它将代替shell进程把SIGTERM传播到spring boot。

ENTRYPOINT [ "sh", "-c", "exec java -jar /apps/rms.jar"]

再次

docker build...
docker run...
docker stop rms

居然成功了,eureka也能成功注销该容器实例了

再试一下上边儿不生效的优雅停止容器方式也成功了,如:

docker kill -s SIGTERM rms

还是蛮优雅的嘛。

其实说来说去,就是只要能让spring boot优雅退出,eureka就能让该实例优雅注销。

另外spring cloud consul也是如此。

spring cloud之Eureka不能注销docker部署的实例的更多相关文章

  1. Spring Cloud与Eureka

    Spring Cloud与Eureka 一.使用SpringCloud注册中心Eureka 1.1 Eureka和Zookeeper对比 1.1.1 Zookeeper保证CP 1.1.2 Eurek ...

  2. Spring Boot 2 (六):使用 Docker 部署 Spring Boot 开源软件云收藏

    Spring Boot 2 (六):使用 Docker 部署 Spring Boot 开源软件云收藏 云收藏项目已经开源3年多了,作为当初刚开始学习 Spring Boot 的练手项目,使用了很多当时 ...

  3. Spring Boot 2 (四):使用 Docker 部署 Spring Boot

    Spring Boot 2 (四):使用 Docker 部署 Spring Boot Docker 技术发展为微服务落地提供了更加便利的环境,使用 Docker 部署 Spring Boot 其实非常 ...

  4. spring cloud之eureka简介

    最近线上的接口出了一些问题,有一些可能不是代码的问题,但是由于是测试和其他方面的同事爆出来的,所以感觉对接口的监控应该提上日程. 经过搜索发现,spring cloud的eureka就是专门做这方面工 ...

  5. Spring Cloud Security&Eureka安全认证(Greenwich版本)

    Spring Cloud Security&Eureka安全认证(Greenwich版本) 一·安全 Spring Cloud支持多种安全认证方式,比如OAuth等.而默认是可以直接添加spr ...

  6. Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇

    Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...

  7. Spring Boot,Spring Cloud,Eureka,Actuator,Spring Boot Admin,Stream,Hystrix

    Spring Boot,Spring Cloud,Eureka,Actuator,Spring Boot Admin,Stream,Hystrix 一.Spring Cloud 之 Eureka. 1 ...

  8. Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)

    一.背景 在我上一篇文章<Spring Cloud开发人员如何解决服务冲突和实例乱窜?>中提到使用服务的元数据来实现隔离和路由,有朋友问到能不能直接通过IP来实现?本文就和大家一起来讨论一 ...

  9. Spring Cloud之Eureka服务注册与发现

    解决什么问题 ➟阐述微服务以及服务注册发现的部分概念 ➟阐述Eureka服务注册与发现的部分原理及细节 为什么需要服务中心 过去,每个应用都是一个CPU,一个主机上的单一系统.然而今天,随着大数据和云 ...

随机推荐

  1. sed原理及sed命令格式 ,缓存区,模式空间

    4.1            Sed工作原理 sed是一个非交互式的流编辑器.所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出:而所谓流编辑器,是指sed每次只从 ...

  2. redis—django-redis

    自定义连接池 这种方式跟普通py文件操作redis一样,代码如下: views.py import redis from django.shortcuts import render,HttpResp ...

  3. Python单例模式(Singleton)的N种实现

    很多初学者喜欢用全局变量,因为这比函数的参数传来传去更容易让人理解.确实在很多场景下用全局变量很方便.不过如果代码规模增大,并且有多个文件的时候,全局变量就会变得比较混乱.你可能不知道在哪个文件中定义 ...

  4. Ubuntu安装截图软件shutter

    参考链接: Ubuntu 安装和配置shutter截图软件 解决shutter不能编辑的问题:https://itsfoss.com/shutter-edit-button-disabled/ 安装前 ...

  5. LNMP原理

    在linux系统中,LNMP是目前网站主流架构之一,LNMP中L指linux系统平台,N是nginx指网站的前端程序,发布静态页面和调用外部程序解析动态页面,M是mysql指网站的后台数据库,P是PH ...

  6. Raid0、Raid0+1、Raid1、Raid5四者的区别

    RAID,可以把硬盘整合成一个大磁盘,还可以在大磁盘上再分区,放数据还有一个大功能,多块盘放在一起可以有冗余(备份)RAID整合方式有很多,常用的:0 1 5 10 Raid0Raid0是所有raid ...

  7. Java笔记(基础第三篇)

    面向对象的特点: 封装 继承 多态 类的构造方法 如果在类中定义的构造方法都不是无参的构造方法,则编译器不会为类设置一个默认的无参构造方法,当视图调用无参构造方法实例化一个对象时,编译器会报错,所以只 ...

  8. Navicat Premium 12 安装 与 激活

    官方简体中文下载网址:https://www.navicat.com.cn/download/navicat-premium 安装的过程....(都是中文)所以略过. 开始破解....( ...... ...

  9. RHEL6 学习:使用 cryptsetup 给分区加密

    RHEL6 学习:使用 cryptsetup 给分区加密 今天学习了 RHEL 对硬盘分区加密的知识,在 RHEL 系统里可以通过使用 cryptsetup 工具对硬盘分区进行加密,加密后的分区需要输 ...

  10. python3 scrapy爬虫项目的诞生

    前提安装好scrapy模块最好 requests和bs4模块都安装好 可以概括为五个步骤 步骤一:新建一个项目 无论你用windows也好,linux也罢,在cmd或者终端 切换到目标文件夹,然后输入 ...