论consul正确的关闭姿势
最近在工作中发现一个有意思的现象,我用 ctrl+c 关闭本地 consul 的时候,报警系统并没有发出告警,说我的 node 异常,自己看了一下代码,发现 consul 的关闭还是有点猫腻的,仔细来讲讲
consul agent 在正常关闭的时候会向集群发送 leave 信令,宣告自己离开集群,那么什么才叫正常关闭呢?
还是上代码:
摘自command.go handleSignals方法
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | func (c *Command) handleSignals(config *Config, retryJoin <-chan struct{}, retryJoinWan <-chan struct{}) int { 	signalCh := make(chan os.Signal, 4) 	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP) 	// Wait for a signal WAIT: 	var sig os.Signal 	select { 	case s := <-signalCh: 		sig = s 	case <-c.rpcServer.ReloadCh(): 		sig = syscall.SIGHUP 	case <-c.ShutdownCh: 		sig = os.Interrupt 	case <-retryJoin: 		return 1 	case <-retryJoinWan: 		return 1 	case <-c.agent.ShutdownCh(): 		// Agent is already shutdown! 		return 0 	} 	c.Ui.Output(fmt.Sprintf("Caught signal: %v", sig)) 	// Check if this is a SIGHUP 	if sig == syscall.SIGHUP { 		if conf := c.handleReload(config); conf != nil { 			config = conf 		} 		goto WAIT 	} 	// Check if we should do a graceful leave 	graceful := false 	if sig == os.Interrupt && !(*config.SkipLeaveOnInt) { 		graceful = true 	} else if sig == syscall.SIGTERM && config.LeaveOnTerm { 		graceful = true 	} 	// Bail fast if not doing a graceful leave 	if !graceful { 		return 1 	} 	// Attempt a graceful leave 	gracefulCh := make(chan struct{}) 	c.Ui.Output("Gracefully shutting down agent...") 	go func() { 		if err := c.agent.Leave(); err != nil { 			c.Ui.Error(fmt.Sprintf("Error: %s", err)) 			return 		} 		close(gracefulCh) 	}() 	// Wait for leave or another signal 	select { 	case <-signalCh: 		return 1 	case <-time.After(gracefulTimeout): 		return 1 	case <-gracefulCh: 		return 0 	} } | 
首先 agent 监听了三个系统信令,os.Interrupt, syscall.SIGTERM, syscall.SIGHUP
看26行,syscall.SIGHUP,用于 reloadconfig, 这个忽略掉
接下来才是进入正题,如何正确的关闭 consul
首先我们要知道 consul agent 关闭后 consul server 一般是什么体现.
- consul ui 显示 Node 异常, check 显示是 fialling
- consul ui 中搜索不到这个 node
是什么造成这个差别呢,答案在上面代码里面的第49行到55行,正常关闭后, node 会向 server 发送一条 leave 的信令,告诉 server 我离开了,你不用管我了,但是如果是宕机的话,又不能发送这个 leave 信令,让 server 知道我falling 了,这里通过34行定义的graceful来处理,如果配置里面说需要发送 leave 信令,那么就发送一个.
这里说一下, consul 的 service 或者 node 状态监控可以通过consul_alert这个项目来做(这里吐个槽,虽然我在用这个程序做报警,但是真心觉得这个代码写得不敢恭维,不停的 exet 子进程,不停的初始化,想要写alert 扩展的,一定要考虑重复初始化到知道内存泄漏)
原理说完,槽吐完,接下来说点好的,这也是我觉得 consul 开发者很贴心的一个地方.
作者把os.Interrupt, syscall.SIGTERM两个信令分开处理,
os.Interrupt
这个信令对应的其实就是 ctrl+c, 这一般是我们在开发时才会用到,那么和这个信令配合的配置是config.SkipLeaveOnInt ,这个配置项不配置,默认就是 false, 那么`sig == os.Interrupt && !(config.SkipLeaveOnInt)` 就为 true, 接着就会执行 leave信令,这完全适用于我们在开发环境中,使用自己开发电脑上的 consul agent, 退出就自动注销,不用怕收到报警.
syscall.SIGTERM
这个信令一般我们执行
kill -15 ${pid}就会发送,当然kill ${pid}默认就是发送15号信令,这个信令配合config.LeaveOnTerm配置项来处理是否发送 leave 信令,这种一般是 agent 在后台运行时才会用到的,这种情况大家都知道主要场景是在生产环境,如果配置config.LeaveOnTerm= true 的话,那么停机维护的时候,也收不到烦人的报警.贴心吧
有人说,宕机怎么办,我很遗憾的告诉你 os.KILL 信令,程序接收到也没有时间执行下面的操作,直接被杀掉了,在服务器宕机的时候也许都没机会发出 kill 命令,在程序被 kernel 杀掉也就是 kill -9,当然程序也没办法执行下面的操作,当然在 server 端看到的状态就是 falling,接收收到报警,找运维人员处理就好了.
最后总结一下,关闭 consul 的正确姿势:
在前台运行的情况下:
ctrl+c +最简化配置即可正常关闭,
在后台运行的情况下:
配置中指定
LeaveOnTerm: true,维护时,使用kill -15 ${pid}来关闭进程,即可正常关闭掉 node, 并注销成功.
补充说明:
leave 的信令发送时异步发送的,所以如果网络不太好的情况下,也许会 leave 还没完全发出去程序就关闭掉了.代码见上面49行,我没想明白为什么要一步处理,同步处理,就算发送失败重试三次再管也好的….
论consul正确的关闭姿势的更多相关文章
- Hibernate中,将session绑定到线程时,在保存和查询数据的代码里,要正确的关闭session
		比如有个保存的方法 // 保存 public void save(){ Transaction t = XXX Session s = getSession.beginTransaction(); X ... 
- HTTP协议学习笔记---HTTP持久连接和如何正确地关闭HTTP连接
		一,持久连接 什么是持久连接?对于HTTP协议而言,它是基于请求响应模型,Client向Server发请求时,先建立一条HTTP连接,Server给Client响应数据后,连接关闭. 当Client发 ... 
- 如约而至,Java 10 正式发布!   Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十四)Redis缓存正确的使用姿势  努力的孩子运气不会太差,跌宕的人生定当更加精彩  优先队列详解(转载)
		如约而至,Java 10 正式发布! 3 月 20 日,Oracle 宣布 Java 10 正式发布. 官方已提供下载:http://www.oracle.com/technetwork/java ... 
- java并发系列(五)-----如何正确的关闭一个线程
		正确的关闭一个线程可不是简单的事情,由于线程调度的复杂性以及不可控性(毕竟运行都由操作系统做主),先来了解一下interrupt() 1.interrupt() 根据jdk文档的介绍,如下: inte ... 
- Fragment全解析系列(二):正确的使用姿势
		作为一个稳定的app,从后台且回到前台,一定会在任何情况都能恢复到离开前的页面,并且保证数据的完整性. 如果你没看过本系列的第一篇,为了方便后面文章的介绍,先规定一个"术语",安卓 ... 
- Servlet3.0+springmvc5+log4j2正确的开启姿势(WebLookUp)
		前言 java社区占据市场份额比较大的日志组件由log4j 1.×,到logback,再到整合后的升级版 log4j 2.×,有网友测试后据说log4j2的性能最NB.于是开始往自己的springmv ... 
- linux 如何正确的关闭mongodb
		有的朋友说可以通过下面的命令关闭mongodb: killall mongodb #or kill -9 mongo-pid 上面的方法确实可以关闭mongodb,但是正确的做法不是这样子的,mong ... 
- How Javascript works (Javascript工作原理) (五) 深入理解 WebSockets 和带有 SSE 机制的HTTP/2 以及正确的使用姿势
		个人总结: 1.长连接机制——分清Websocket,http2,SSE: 1)HTTP/2 引进了 Server Push 技术用来让服务器主动向客户端缓存发送数据.然而,它并不允许直接向客户端程序 ... 
- springboot  actuator shutdown正确的关闭操作
		今天整合ehcache时发现一个很重要的问题,就是程序关闭(硬关闭)之后,持久化到磁盘的缓存数据没能正确写入加载,问题还是硬关闭的问题,所以就使用actuator 进行监听 <dependenc ... 
随机推荐
- js插件---WebUploader 如何接收服务端返回的数据
			js插件---WebUploader 如何接收服务端返回的数据 一.总结 一句话总结: uploadSuccess有两个参数,一个是file(上传的文件信息),一个是response(服务器返回的信息 ... 
- C# 退出应用程序的几种方法
			Application.Exit();//好像只在主线程可以起作用,而且当有线程,或是阻塞方法的情况下,很容易失灵 this.Close();//只是关闭当前窗体. Application.ExitT ... 
- Alpha冲刺(8/10)——2019.5.1
			所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(8/10)--2019.5.1 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪万 ... 
- render函数之jsx应用
			一.模板缺陷(模板的最大特点是扩展难度大,不易扩展.可能会造成逻辑冗余) <level :type="1">哈哈</level> <level :ty ... 
- include指令 include动作
- gcc分步骤编译的记录
- 使用terraform 生成自签名证书
			terraform 是一个很不错的基础设施工具,我们可以用来做关于基础设施部署的事情,可以实现基础设施即代码 以下演示一个简单的自签名证书的生成(使用tls provider) main.tf 文件 ... 
- 微信小程序知识云开发
			一个小程序最多5个服务类目,一个月可以修改3次类目 小程序侵权投诉的发起与应对 软件著作权作品登记证书 实现小程序支付功能 如何借助官方支付api简单.高效率地实现小程序支付功能 借助小程序云开发实现 ... 
- Django自带后台admin的使用配置
			Django自带后台使用配置参考官网地址:https://docs.djangoproject.com/en/1.11/ref/contrib/admin/ ,本文章值是介绍简单配置,如果需要详细内容 ... 
- 缺陷描述(Description)
			[tips1] 缺陷报告的用途在于: 记录bug 对bug进行分类(发现者.日期.版本.模块.严重程度.优先级) 跟踪bug(new-open-fixed-closed) 对bug进行统计分析.总结 ... 
