博客链接:http://www.cnblogs.com/zhenghongxin/p/8676565.html

消息队列处理后台任务带来的问题

在系统稍微大些的时候,我们经常会用到消息队列(实现的方式很多种,在后续会讲到),比如发邮件,将邮件消息放入队列待执行,比如发送奖励等。可以说,我们是构造一个最简单的先进先出队列,队列的一个成员就是一段文本。入消息队列lpop比较容易,但在取消息队列rpop的时候,我们可能遇到这样的问题:

我们无法预知消息队列何时会有数据产生,所以我们的任务执行程序还需要具备监控消息队列的能力,也就是一个常驻后台的守护进程。

而PHP在一般情况下是无法常驻内存的,当然有了swoole后,PHP可以常驻内存(可以学习:MixPHP:基于 Swoole 的常驻内存型 PHP 框架),或其他方式来实现常驻内存(workman等),而接下来面对的问题是:

1)当守护进程运行时,Web应用能否与后台守护进程交互,实现开启/杀死进程的功能以及获得进程的运行状态?

2)当我们更改配置时,守护进程能否实时读取配置而不需要整个重启?

3)守护进程如果重启,能否进行平滑的重启,而不会丢失正在执行的消息队列?

4)消息队列的如何取出与意外还原保证消息的完整性?

简单的php定时任务拉起消费队列

我们可以写一个php消费队列的脚本,利用定时任务,每隔几分钟读取一下消息队列,执行成功的队列清除,每隔五分钟拉起任务。这样子做的优点:代码简单易理解,定时任务容易配置

这样子做的缺点:

1) 最慢情况下,消息队列要等5分钟才会被消费,在某些场景下,这是无法忍受的。

2) 消息队列很多的情况下,每隔五分钟,任务被重复拉起,要考虑多种并发,堵塞的情况。当出了问题,如何回滚?突然间进程异常退出,队列没有被消费等情况

后台进程与定时任务双配合

我们可以写一个php消费队列的脚本,让其以后台进程的方式运行,一直在后台默默运行。不断地等待消息队列的产生,为了保证这个进程发生意外断掉,我们需要一个守护进程来守护这个后台进程。

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。顾名思义,它的作用用来守护我们的消息队列消费进程,它将后台程序变成一种服务,让服务一直处于运行状态。当后台程序被kill掉,守护进程会将它重新拉起。

1)守护进程最重要的特性是后台运行。
2)守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。
3)守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端(shell)执行。

简单的实现来说,用定时任务cron,每五分钟检测一下后台进程是否正常运行,如果正常运行,那不作处理,如果后

台进程挂掉,那将它重新拉起。

这是简单的用cron来做守护任务的例子,很多人也提出了让php做守护进程的方法:

1)将文件模式的屏蔽字设置为0;
2)fork出子进程,终止父进程(保证创建守护进程的进程不是进程组的组长);
3)调用setsid创建一个新的会话;
4)将当前工作目录改为根目录;
5)关闭不需要的文件描述符;
6)忽略SIGCHLD信号。

具体可以看:

如何写php守护进程(Daemon)http://www.jb51.net/article/77205.htm

此方法步骤繁琐麻烦,且不易维护,并不推荐这么做

swoole来做守护进程

有朋友的公司用的是swoole来做守护进程,这方面刚开始我们有考虑,最后决定用更加简单的Supervisor来做

Supervisor

Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。

安装

Supervisor是使用python开发的一个进程管工具,安装和使用都非常简单。使用 pip 或者 easy_install 安装会非常方便,自动解决依赖关系。

– sudo pip install supervisor
– sudo easy_install supervisor

supervisor安装完成后会生成三个执行程序:supervisortd、supervisorctl、echo_supervisord_conf,分别是supervisor的守护进程服务(用于接收进程管理命令)、客户端(用于和守护进程通信,发送管理进程的指令)、生成初始配置文件程序。

新建个保存配置的目录:

mkdir /etc/supervisor

用生成配置的命令生成配置查看:

echo_supervisord_conf > /etc/supervisor/supervisord.conf

可以查看 /etc/supervisor/supervisord.conf 下的配置文件

某些配置参数说明:

[unix_http_server]
file=/tmp/supervisor.sock   ;UNIX socket 文件,supervisorctl 会使用
;chmod=0700                 ;socket文件的mode,默认是0700
;chown=nobody:nogroup       ;socket文件的owner,格式:uid:gid

;[inet_http_server]         ;HTTP服务器,提供web管理界面
;port=127.0.0.1:9001        ;Web管理后台运行的IP和端口,如果开放到公网,需要注意安全性
;username=user              ;登录管理后台的用户名
;password=123               ;登录管理后台的密码

[supervisord]
logfile=/tmp/supervisord.log ;日志文件,默认是 $CWD/supervisord.log
logfile_maxbytes=50MB        ;日志文件大小,超出会rotate,默认 50MB,如果设成0,表示不限制大小
logfile_backups=10           ;日志文件保留备份数量默认10,设为0表示不备份
loglevel=info                ;日志级别,默认info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ;pid 文件
nodaemon=false               ;是否在前台启动,默认是false,即以 daemon 的方式启动
minfds=1024                  ;可以打开的文件描述符的最小值,默认 1024
minprocs=200                 ;可以打开的进程数的最小值,默认 200

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ;通过UNIX socket连接supervisord,路径与unix_http_server部分的file一致
;serverurl=http://127.0.0.1:9001 ; 通过HTTP的方式连接supervisord

; [program:xx]是被管理的进程配置参数,xx是进程的名称
[program:xx]
command=/opt/apache-tomcat-8.0.35/bin/catalina.sh run  ; 程序启动命令
autostart=true       ; 在supervisord启动的时候也自动启动
startsecs=10         ; 启动10秒后没有异常退出,就表示进程正常启动了,默认为1秒
autorestart=true     ; 程序退出后自动重启,可选值:[unexpected,true,false],默认为unexpected,表示进程意外杀死后才重启
startretries=3       ; 启动失败自动重试次数,默认是3
user=tomcat          ; 用哪个用户启动进程,默认是root
priority=999         ; 进程启动优先级,默认999,值小的优先启动
redirect_stderr=true ; 把stderr重定向到stdout,默认false
stdout_logfile_maxbytes=20MB  ; stdout 日志文件大小,默认50MB
stdout_logfile_backups = 20   ; stdout 日志文件备份数,默认是10
; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out
stopasgroup=false     ;默认为false,进程被杀死时,是否向这个进程组发送stop信号,包括子进程
killasgroup=false     ;默认为false,向进程组发送kill信号,包括子进程

;包含其它配置文件
[include]
files = relative/directory/*.ini    ;可以指定一个或多个以.ini结束的配置文件

更为具体的配置,我们可以查看:

https://blog.csdn.net/xyang81/article/details/51555473

上面有更为详细的开机启动,web管理等各项说明,在此我不列举了

我本地的简略配置为:

command=php /phpstudy/www/index.php
stdout_logfile=/tmp/catalina.out
autostart=true
user=root
autorestart=true
startsecs=5
priority=1
stopasgroup=true
killasgroup=true

启动后,可以尝试kill掉index.php进程,几秒内进程都会重新被拉起

*** 值得注意的是:如果你在代码中,刻意的去退出进程,那supervisor依旧会帮你重新拉起。

守护进程与Supervisor的更多相关文章

  1. centos安装守护进程工具supervisor

    安装命令 yum install supervisor 启动守护进程 supervisord -c /etc/supervisord.conf 切换至/etc/supervisord.d目录下 写一个 ...

  2. centos 下Supervisor 守护进程基本配置

    supervisor:C/S架构的进程控制系统,可使用户在类UNIX系统中监控.管理进程.常用于管理与某个用户或项目相关的进程. 组成部分supervisord:服务守护进程supervisorctl ...

  3. 【Centos7】 中使用Supervisor守护进程

    原文出处: Centos7 中使用Supervisor守护进程 配置supervisor实现进程守护 1.安装supervisor yum install Supervisor   2.启动服务 su ...

  4. Linux Supervisor 守护进程基本配置

    supervisor:C/S架构的进程控制系统,可使用户在类UNIX系统中监控.管理进程.常用于管理与某个用户或项目相关的进程. 组成部分supervisord:服务守护进程supervisorctl ...

  5. supervisor运行golang守护进程

    最近在鼓捣golang守护进程的实现,无意发现了supervisor这个有意思的东西.supervisor是一个unix的系统进程管理软件,可以用它来管理apache.nginx等服务,若服务挂了可以 ...

  6. Supervisor 管理后台守护进程

    Supervisor 管理后台守护进程 参考原文如下: http://codinn.com/people/brant/notes/110948/ 做了一些注释 +++++++++++引用开始+++++ ...

  7. [Linux] PHP程序员玩转Linux系列-使用supervisor实现守护进程

    1.PHP程序员玩转Linux系列-怎么安装使用CentOS 2.PHP程序员玩转Linux系列-lnmp环境的搭建 3.PHP程序员玩转Linux系列-搭建FTP代码开发环境 4.PHP程序员玩转L ...

  8. 【转载】Centos7 中使用Supervisor守护进程

    配置supervisor实现进程守护 1.安装supervisor yum install Supervisor   2.启动服务 supervisord -c /etc/supervisord.co ...

  9. supervisor使用,配置和安装(包括监控守护进程httpd,keepalived)

    yum -y install supervisor(如果安装不成功,需要更新源,yum -y install epel) 或者: wget --no-check-certificate https:/ ...

随机推荐

  1. mysql优化概述2

    一.索引的概念 利用关键字,就是记录的部分数据(某个字段,某些字段,某个字段的一部份),建立与记录位置的对应关系,就是索引.索引的关键字一定是排序的. 二.索引的类型 mysql支持四种索引: 1.主 ...

  2. struts框架值栈问题二之值栈的内部结构

    2. 问题二 : 值栈的内部结构 ? * 值栈由两部分组成 > root -- Struts把动作和相关对象压入 ObjectStack 中--List > context -- Stru ...

  3. centos6.5 设置ssh无密码登录

    :关闭防火墙 vim /etc/selinux/config 把SELINUX=enforcing修改为SELINUX=disabled   A机器root连接B机器root用户 (root用户登录) ...

  4. linux信号量初识

    以下程序使用信号量控制程序运行 "信号"量 "变"量 /*信号量(semaphore)是变量,是一种特殊的变量.它仅取正值. 对信息号量的操作只有2种:等待(w ...

  5. IIS 6 备忘

    用IIS7久了, 回到IIS6 总被搞混,所以记录下,以备忘记. 以下是转载和整合了他人的资源,原出处不详.   IIS Web 服务器的权限设置有两个地方,一个是 NTFS 文件系统本身的权限设置, ...

  6. 二进制搭建kubernetes多master集群【二、配置flannel网络】

    上一篇我们已经搭建etcd高可用集群,参考:二进制搭建kubernetes多master集群[一.使用TLS证书搭建etcd集群] 此文将搭建flannel网络,目的使跨主机的docker能够互相通信 ...

  7. linux配置ip 网关 和dns(转)

    原文地址:http://blog.csdn.net/ztz0223/article/details/5800665 Linux下面配置ip很容易的,并没有网上说的那么复杂,我的linux系统是rhel ...

  8. Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.liuyang.JDbCTemplate.PersonDao]: No default constructor fo

    错误是说我的配置文件中没有对构造函数进行配置,所以找不到构造函数,在配置文件application.xml中加入如下句子: <bean id="personDao" clas ...

  9. POJ 1061 青蛙的约会(扩展欧几里德算法)

    题意:两只青蛙在同一个纬度上跳跃,给定每个青蛙的开始坐标和每秒跳几个单位,纬度长为L,求它们相遇的最短时间. 析:开始,一看只有一组数据,就想模拟一下,觉得应该不会超时,但是不幸的是TLE了,我知道这 ...

  10. HDU 1061 Rightmost Digit (快速幂取模)

    题意:给定一个数,求n^n的个位数. 析:很简单么,不就是快速幂么,取余10,所以不用说了,如果不会快速幂,这个题肯定是周期的, 找一下就OK了. 代码如下: #include <iostrea ...