运维 使用 Upstart + Inspeqtor 管理你的 Sidekiq (监控、崩溃自动重启、邮件通知)

lokyoung · 发布于 2016年4月17日 · 最后由 jarorwar 回复于 2016年8月19日 · 4928 次阅读
20875
本帖已被设为精华帖!

前言

最近在工作中碰到一个问题,服务器上的Sidekiq崩溃之后,由于我们在服务器端并没有对Sidekiq进行监控和管理,当察觉到Sidekiq进程崩溃时已经有大量的background job停留在队列中无法执行。 这无疑是一件相当痛苦的事,所以我开始找寻办法去解决这一问题。 而实际上,Sidekiq的作者就已经给出了最好的解决方案(可以参考他博客的文章Sidekiq and Upstart)——用Ubuntu自带的Upstart去保证Sidekiq不会因为Ruby虚拟机崩溃等原因停止工作,用Inspeqtor结合Upstart去监控你的Sidekiq(Sidekiq进程失败时发送邮件通知)。

Upstart

简介

Upstart是Ubuntu系统自带的基于事件的初始化常驻程序,可以在系统开机和关机时启动和关闭服务,在系统运行时对服务进行监督。 Upstart可以让被监督的进程在非正常关闭时,自动重启该进程,保证其在系统中正常稳定地运行。 可以使用系统自带的工具去解决问题,相比较使用第三方工具而言,无疑是更好的方式。所以我选择了Upstart来管理服务器上的Sidekiq进程。
PS: Upstart除了可以在Ubuntu系统上使用外,在Debian、Fedora、openSUSE、Chrome OS等发行版上也有相关支持。而在最近两年一些Linux发行版的新版本中(Ubuntu 15.04, CentOS 7等),可以使用更先进的Systemd实现Upstart的功能。Upstart的详细信息,可以参考Ubuntu官方的Upstart Cookbook

Upstart监督Sidekiq配置

在服务器的/etc/init目录下新建一个*.conf文件,在这里我新建了一个名为sidekiq.conf的配置文件。

# /etc/init/sidekiq.conf - Sidekiq config

description "Sidekiq Background Worker"

# 在系统开机时启动服务,关机时关闭服务
start on runlevel [2345]
stop on runlevel [06]

# 在进程崩溃时自动重启进程
respawn
# 30秒之内尝试3次重启,如果失败,则放弃重启
respawn limit 3 30

# 正常退出所接收到的信号,0(Linux程序正常退出码)
# TERM是通过sidekiqctl停止sidekiq时发送的信号
# 除了这两种信号之外,其余任何终止sidekiq的方式都会触发respawn
normal exit 0 TERM

# 通过reload指令向正在运行的进程发送USR1信号(对于Sidekiq来说,USR1意味着停止接收新的background job)
reload signal USR1

# 通过upstart启动的sidekiq实例的序号
instance $index

script
# this script runs in /bin/sh by default
# respawn as bash so we can source in rbenv
exec /bin/bash <<'EOT'
  # Pick your poison :) Or none if you're using a system wide installed Ruby.
  # rbenv
  # source /home/apps/.bash_profile
  # OR
  # source /home/apps/.profile
  # OR system:
  # source /etc/profile.d/rbenv.sh
  #
  # rvm
  # source /home/apps/.rvm/scripts/rvm

  # Logs out to /var/log/upstart/sidekiq.log by default

  cd /var/www/app
  # 注:这里必须在bundle exec前加上exec,否则会在另外一个进程(不受Upstart监控)中开启sidekiq
  # sidekiq -i 的参数和之前传入是实例序号index一致
  exec bundle exec sidekiq -i ${index} -e production
EOT
end script

只需要上面这个简单的配置文件,就完成了Upstart中sidekiq的配置。接下来,我们需要通过Upstart来启动sidekiq,这样才可以让sidekiq进程在Upstart的监督下运行。

# 由于在系统中可以开启多个sidekiq进程,所以你可以通过指定sidekiq进程的编号方便你对某一个sidekiq进程进行管理
# 下列启动序号为0的sidekiq实例(在我们我应用中,只需要一个sidekiq进程)
# 启动sidekiq
$ sudo service sidekiq start index=0

# 终止sidekiq
$ sudo service sidekiq stop index=0

# 重启sidekiq
$ sudo service sidekiq restart index=0

在通过Upstart的方式启动sidekiq之后,sidekiq进程如果遇到异常情况造成崩溃,之后立刻重生(重新启动一个sidekiq进程)。你可以尝试使用kill的方式强制关闭sidekiq,会发现sidekiq不会在你的进程列表中消失(pid会改变)。现在你只能通过以上命令中的stop来关闭sidekiq。

部署

sidekiq部署的最佳实践,是尽可能早的让sidekiq处于quiet状态(停止接受新的job,只处理当前在队列中的job),并且尽可能晚的重启sidekiq。 在/etc/init/sidekiq.conf中我们曾指定过reload signal USR1,这表示向当前Upstart进程发送reload命令时,传送一个名为USR1的信号过去。USR1是sidekiq系统内置的一个信号量,当sidekiq接收到这个信号时,便会进入quiet状态。
在你的部署脚本的早期阶段执行以下命令:

$ sudo service sidekiq reload index=0

重启sidekiq也十分地方便,使用Upstart自带的restart即可,restart命令会停止当前任务,之后再次启动。不过restart命令和单纯地先执行stop然后执行start不一样,restart命令会保留当前任务停止时的各项配置,在重新启动时从硬盘中读取这些信息。这样就不会造成如果在重启时,如果正好有任务还在队列中执行,却因为重启而停止导致没有执行完的情况了。 在你的部署脚本中尽量靠后的位置运行重启命令:

$ sudo service sidekiq restart index=0

PS: 由于sudo需要输入密码,而在自动化部署时无法输入密码。而我们启动Upstart是通过service的方式,所以可以让部署用户在执行service命令时不需要输入密码。 打开sudo配置文件:

$ sudo visudo

在打开的配置文件中加上一行(用你的系统用户名替换current_user)

current_user ALL=NOPASSWD:/usr/sbin/service

Inspeqtor

简介

Inspeqtor是Sidekiq作者自己写的一个监控工具,可以对系统中的开启的服务(通过init.d, systemd或者upstart启动的进程)进行监控。 同时也可以监控进程的内存占用量和CPU使用量。你可以针对不同的进程配置相应的监控规则,在违反这些规则时重启进程或者向你发送邮件告知。 在之前我们通过配置Upstart启动Sidekiq,所以可以使用Inspeqtor对Sidekiq进程进行监控(这里主要想实现的目标,是在Sidekiq崩溃重启时可以收到邮件通知)。

PS:Inspeqtor和God, bluepill等基于Ruby的监控工具不同,Inspeqtor不需要依赖于Ruby,所以安装也更加方便。

环境搭建和通知邮箱配置

安装

Inspeqtor的安装教程可以在官方wiki中找到,在这里我只列出Ubuntu系统中的安装方式。

$ curl -L https://bit.ly/InspeqtorDEB | sudo bash
$ sudo apt-get install inspeqtor

命令行基本操作

这里同样参考自wiki,有兴趣的朋友可以好好研读。 CentOS 6.5 / Ubuntu with Upstart

$ initctl start inspeqtor
$ initctl stop inspeqtor
$ initctl restart inspeqtor

inspeqtor的log会在/var/log/upstart/inspeqtor.log中输出。

邮箱配置

对发送email的配置在inspeqtor的全局配置文件/etc/inspeqtor/inspeqtor.conf中。 可以通过配置gmail,普通的smtp邮箱和服务器本机的smtp邮件服务三种方式发送邮件。 这里我列出普通smtp邮箱的配置

# /etc/inspeqtor/inspeqtor.conf

send alerts via email with
  username bubba,
  password "correct horse battery staple",
  smtp_server smtp.example.com,
  to_email accounting@example.com,
  tls_port 587

更多的配置可以查看官方wiki中的Global Configuration

PS: inspeqtor标准版只能指定一个收件邮箱,如果你想让多个邮箱接收inspeqtor邮件,可以使用邮件组。

监控sidekiq

我们之前通过使用Upstart实现了让sidekiq意外崩溃时的自动重生,在这里我们需要的只是在sidekiq崩溃重启时发生邮件通知我们。 由于inspeqtor默认会在其监控下进程的pid改变时发送邮件通知,所以监控sidekiq的配置文件非常简单。 新建配置文件/etc/inspeqtor/services.d/sidekiq.inq。

PS: 按道理说,在这里我们只需要添加一个配置文件即可,不需要添加监控规则(因为pid改变时会自动发送邮件),但是我尝试过,如果不添加一条监控规则,inspeqtor是不会对sidekiq进行监控的。所以我随意添加了一条CPU占用率2次大于95%时发送邮件通知的规则。

# /etc/inspeqtor/services.d/sidekiq.inq

check service sidekiq
  if cpu:user > 95% for 2 cycles then alert

配置完成后,执行restart指令重新启动inspeqtor便可以在sidekiq进程崩溃时收到邮件。

inspeqtor部署集成

之前曾经提到过,inspeqtor在进程的pid变化时会触发alert(发送邮件)。而我们在部署时是会对sidekiq进行重启的(pid会改变),那么在默认情况下,部署时会收到inspeqtor发来的通知邮件。很显然,这样的邮件是没有必要的。所以inspeqtor提供了针对部署时的指令,可以在应用部署期间暂停对进程的监控,这样就不会收到不必要的通知了。

# 在部署开始时运行这条指令(建议在部署脚本的第一步运行)
$ inspeqtorctl start deploy

# 在部署结束时运行(建议在部署脚本的最后执行)
$ inspeqtorctl finish deploy

PS: inspeqtorctl默认情况下需要sudo才可以执行,可以通过修改inspeqtor的Upstart配置文件(/etc/init/inspeqtor.conf)指定当前用户所在group,group中的用户执行inspeqtorctl就不需要输入sudo了。

# /etc/init/inspeqtor.conf

setgid current_user_group

参考资料

Sidekiq and Upstart Upstart Cookbook

共收到 44 条回复
96

顶一个!越来越棒了!

20875

#3楼 @yangbodotnet 哈哈,谢谢支持。你和David帮我消除了零回复哈哈。

15999

很有用

20875

#5楼 @embbnux 嗯,而且配置和使用都还挺方便的。

8

很好!

8楼 已删除
1638

nice article.

20875

#7楼 @hooooopo 谢谢!对大家有帮助就好!

20875

#9楼 @xiaoronglv 谢谢,得到认可很开心,个人感觉Upstart和Inspeqtor(二者都不仅仅局限于Sidekiq)还是挺实用的~

96

 👍

14062

:plus1:

2329

大写的赞

20103

顶一个 ~

3

两天后 Ubuntu 16.04 (2016年4月21日) 就会发布,届时 Ubuntu 的 init 会升级为 Systemd,这篇文章可能需要修订一下,或者根据不同的 Ubuntu 版本提供不同的配置建议。

4120

https://github.com/seuros/capistrano-sidekiq#usage 我感觉使用monit更方便点。 用monit令人比较烦的一点是:在系统里装monit默认要sudo权限,我手动将monit相关的权限全部改成deploy,然后设置:sidekiq_monit_use_sudo => false, 部署时就不用烦恼了。

3469

很肉麻的说一句,『感谢分享』,最近正要处理相关环节,没想到现在能看到这么及时的经验贴。攒到内存溢出系统崩溃啊!!!!

3

#18楼 @kungs 系统自带的进程管理工具已经足够标准且强大了,monit 成了非必需的第三方依赖,而 inspeqtor 做的事情跟系统进程管理工具各负其责,刚刚好不冲突。

20875

#17楼 @lgn21st 谢谢建议!对于最新Ubuntu系统(16.04)的确要不适用了,本文的适用群体应当是Ubuntu 16.04之前的系统。是的,Systemd会是趋势,配置也更加方便。不过现在大部分服务器使用的是旧版本的系统,而服务器系统升级需要很大的成本,所以可能在很长一段时间里,旧版本系统的占有率还是会很高吧~

20875

#15楼 @mingyuan0715 Thank you very much!

20875

#19楼 @liwei78 也谢谢你的支持!看到对大家有帮助,我也非常非常开心!我还是一个新手,如果有哪里疏漏的,也欢迎并且谢谢指正!

20875

#17楼 @lgn21st 其实当初碰到这个问题不知道怎么解决,还是在社区里搜索sidekiq相关问题,然后发现你在一个回答中推荐使用Upstart/Systemd并且给出了Sidekiq作者的那篇文章,我才去了解然后发现这对我而言几乎是最好的解决方案了。所以感谢!

3

#24楼 @lokyoung 目测从下个月开始,Ubuntu 16.04 将会是新开服务器的默认选择,而且会流行至少两年,直到 18.04 发布。

我自己也做了同样的事情,包括研究过 upstart,systemd,以及 Inspeqtor (包括源码),以及小米运营团队开源出来的 open-falcon,但是我比较懒,没有像你一样把这些都写出来 :D

15

好像 supervisor 来做更简单些

20875

#25楼 @lgn21st 那看来是要与时俱进了。 啊哈,其实写出来也是让我自己把这些知识巩固下。看到这么多人支持,真心感觉到社区的好!

20875

#26楼 @huobazi 当时supervisor也是备选之一,由于后来使用了Upstart就没有去仔细了解了。不过supervisor应该仅仅是监控进程并且也需要安装相应的包。而Upstart是系统自带的,我们系统中的Sidekiq进程直接通过Upstart启动,进程本身也算是一个Upstart进程,这样解决我觉得更加彻底并且没有依赖。

19199

:plus1:

11314

Cool! 之前也有遇到过这个问题,我们是自己写脚本10s去检测一下sidekiq.pid是否存在,如果不存在就重启。

#!/bin/bash

file="/path/to/project/tmp/pids/sidekiq.pid"

while : ;do
    if ps -p `cat $file` >/dev/null; then
        echo "Sidekiq Started"
    else
        echo "Sidekiq Stopped"
        cd /path/to/project
        echo `pwd`
        nohup bundle exec rake sidekiq:restart RAILS_ENV=production >> /path/to/check_sidekiq_log &
    fi
    sleep 10
done

最近也有想把sidekiq的运行状态加到zabbix中去监控。 但是sidekiq为什么会crash掉,这个问题还在跟进。

4113

:plus1:

respawn 3 30 处的语法有问题,可以用 init-checkconf /etc/init/sidekiq.conf 检查。有时间更新下:respawn limit 3 30

感谢分享~

20875

#31楼 @cod7ce 谢谢指正!

20875

#30楼 @zoker 用Upstart吧,用脚本去检测感觉并不是种好的方式。

3

#30楼 @zoker 推荐用 Upstart,用了你会发现你根本不需要 PID 文件。

3

我找出了之前项目中用 upstart 管理 sidekiq 的部署文档,贴到了我的 blog 上,跟 @lokyoung 的版本大同小异。

http://lvguoning.com/2016/04/20/using-upstart-to-manage-sidekiq/

26044

监控方案就跟前端开发一样, 框架多, 总不够用

20875

#37楼 @unbug 至少对于Sidekiq来说,Upstart算是最佳实践了。

96

用 monit 就够了,而且 https://github.com/seuros/capistrano-sidekiq#usage 本身就提供了支持

systemd 是王道,upstart 是要被淘汰的东西。

20875

#39楼 @vkill kill you dependency....此外现在投入生产环境的Linux服务器有很大一部分还不支持Systemd,所以对现有服务器来说Upstart还是一种很好的解决方式。当然,Systemd是趋势这毋庸置疑。

11314

#34楼 @lgn21st #40楼 @lokyoung 😄 感谢建议,看完这篇文章就已经准备改用Upstart

10919

不是有god吗?

20875

#42楼 @tq0fqeu 可以用Upstart/Systemd这种系统自带的方式,从进程本身角度解决监控和崩溃重启这些事。相比之下,god就是不必要的依赖了。

910

使用了楼主的方式,测试环境一切正常,生产环境报如下异常,不知道各位是否遇到过~

DEBUG [57133839]    start: Unknown job: sidekiq
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as deployer@121.41.40.7: sudo exit status: 1
sudo stdout: Nothing written
sudo stderr: start: Unknown job: sidekiq
5610

感觉monit就挺好的。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册