unix进程间通信信号的有效实践

背景

最近优化了一版程序:用到了golang的优雅退出机制。

程序使用leader/follower分布式高可用模型,所有的请求都会命中leader;

使用etcd的election sdk做选主,需要在节点意外下线的时候,主动去etcd卸任(删除10s租约), 否则已经下线的节点还会被etcd认为是leader。

所以在这里,优雅退出是技术刚需。

另外根据[云原生十二要素方法论] 第9条: 快速启动和优雅终止可最大化健壮性 , 也推荐各位遵守实践。
Fast startup and shutdown are advocated for a more robust and resilient system.


粗浅的认知方案:捕获程序的终止信号, 主动去卸任。

1. 进程间通信信号

进程间通信信号是操作系统提供的信号机制的内容, 它不是我们开发者长陷入其中的网络或者Socket通信。

kill -l 命令可以列出系统支持的所有进程间通信信号, 下面粗体是常见的、可能用到的通信信号

  • SIGHUP (1) : 挂起信号,通常用于在终端断开时通知进程,也用于通知进程重新加载配置文件。

  • SIGINT (2) : 中断信号,通常由用户通过 Ctrl+C 组合键发送,用于中断一个进程。

  • SIGQUIT (3) : 退出信号,通常由用户通过 Ctrl+\ 组合键发送,用于退出一个进程,并生成核心转储。

  • SIGILL (4) : 非法指令信号,表示进程试图执行非法指令。

  • SIGABRT (6) : 中止信号,通常由调用 abort() 函数产生,用于异常终止一个进程。

  • SIGFPE (8) : 浮点异常信号,表示进程发生算术错误,如除以零。

  • SIGKILL (9) : 杀死信号,强制终止进程,无法被捕获或忽略。

  • SIGSEGV (11) : 段错误信号,表示进程试图访问未分配的内存。

  • SIGPIPE (13) : 管道破裂信号,表示进程写入一个没有读取端的管道。

  • SIGALRM (14) : 定时器信号,由 alarm() 函数产生,用于定时通知进程。

  • SIGTERM (15) : 终止信号,通常用于请求进程优雅地终止。

  • SIGUSR1 (10) 和 SIGUSR2 (12) : 用户自定义信号,供用户和应用程序自行定义用途。

  • SIGCHLD (17) : 子进程状态改变信号,当子进程终止或停止时,父进程会收到此信号。

  • SIGCONT (18) : 继续执行信号,用于恢复暂停的进程。

  • SIGSTOP (19) : 暂停信号,停止进程的执行,无法被捕获或忽略。

  • SIGTSTP (20) : 终端停止信号,通常由用户通过 Ctrl+Z 组合键发送,用于暂停进程。

  • SIGTTIN (21) 和 SIGTTOU (22) : 后台进程试图从终端读取或写入数据时发送的信号。

2. Go应用侦听SIGINT、SIGTERM信号实现优雅退出

有进程终止效果的常用信号有三个:SIGINT、 SIGKILL、SIGTERM, 其中SIGKILL(kill -9) 无法被应用捕获或忽略。

一般应用捕获SIGINT(interrupt中断)、SIGTERM(terminate终止)信号就可在终止之前注入行为。

golang提供signal包来监听收到的进程间通信信号。

针对长时间运行的程序,新开协程,持续监听信号,并插入优雅关闭的代码。

c := make(chan os.Signal)
    signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
    go func() {
      select  {
       case sig:= <-c: {
        log.Infof("Got %s signal. Aborting...\n", sig)
        eCli.Close()    // 利用 etcd election sdk主动卸任
        os.Exit(1)    
       }
      }
     }()

3. 利用SIGSTOP信号模拟进程阻塞

SIGSTOP:暂停进程, 这意味着进程挂起,直到收到SIGCONT信号(continue)才能继续运行。

Q: 进程暂停是什么状态?

1> .收到SIGSTOP信号, 进程会停止运行, 不会执行任何代码,直到被显式恢复;
2>. 不可忽略,这意味着进程收到信号,无法自行决定如何响应,操作系统会直接暂停它;
3>. 资源保持, 虽然被暂停,但依然保留所有系统资源(内存、文件描述符), 这不像进程终止,会释放所有资源。

a130af064d37287828b722562cfbc663.jpeg

client===> A===>B, 模拟进程B阻塞:

1>. 对进程B执行kill -STOP {pid}  暂停进程

2>. time curl  192.168.8.88/test/timeoutAPI 输出:

0.01s user 0.01s system 0% cpu 10.168 total
// 这意味着进程A请求B的超时时间是10s


4. Nginx使用SIGHUP信号实现热更新

上面的STOP信号是纯正的暂停信号,进程无法拒绝;

HangUp信号最初用于终端断开时通知应用进程, 默认行为是终止进程;

由于HUP信号可被应用捕获,在现代应用中,HUP信号常用于通知守护进程重新加载其配置文件。

Nginx master进程重写了HUP信号默认终止进程的逻辑,自定义了处理逻辑,实现了配置的热更新。

6fe2374b07f5187f264b9f1b67d5a66c.jpeg


btw, 在机器与内master进程直接交互, 不是特别便利;

nginx  0.8版本之后,给出了一系列命令行参数, nginx -s reload这个命令会启动一个nginx前台进程,自动定位master进程,向master进程发送HUP信号。

相关资料:https://tengine.taobao.org/book/chapter_02.html#id1

61d30dd2b04c2e7677537b1530e1db8b.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有态度的马甲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值