我在github中提交了不少大大小小的项目,很多时候因为在公司场景中用到的项目,就想当然的以为别的公司肯定也有用到。但是到头来,会发现我开源的那些项目反映其实不怎么热烈,换个意思来表达就是很是冷淡,每次的一时兴起把所写东西提交到github、pypi,但换回来的总是无趣… 我自己细想了下导致这样情况的原因.
其一,代码很多是囫囵吞枣,不优质.
其二,那些项目很多时候,别人遇不到那么偏门的场景.
那我这次就分享一个自认为有些价值的项目. 前段时间朋友在csdn转了我的文章,是关于python多进程管理模型( Master Worker ),有兴趣的朋友,可以去看看这篇文章. 《python使用master worker管理模型开发服务端》. 借着csdn拿到了不少的pv. 文章里面有说过要开源这个模块,但因为年纪大的原因,把这样的事情给忘了. 正好上周有个陌生人给我发邮件,再问是否有开源这项目的想法. 不能再拖了,搞吧….
情况特殊,文章总是被转走,导致我后续的更新大家无法及时看到。这里特意标注下原文链接!
项目名:
ProcessHandler
github地址,https://github.com/rfyiamcool/ProcessHandler
为避免被喷,这里提前申明下ProcessHandle的设计思想跟代码实现极其认真的参考并抄袭 开源gunicorn框架 gunicorn官方 . 换句话说ProcessHandle是基于gunicorn开发的.
更多的内幕及后续的文档更新, 我会放在我博客里面, 有兴趣的朋友可以瞅瞅 ! http://xiaorui.cc/?p=2219
用途:
简单理解为这是一个Master Worker框架. 可以说跟nginx的进程管理模式相似的.
工作原理:
当ProcessHandle启动后,会有一个master进程和多个worker进程.master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程.
对于每个worker进程来说,独立的进程,不需要加锁,所以省掉了锁带来的开销,同时在编程以及问题查找时,也会方便很多。其次,采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快启动新的worker进程。当然,worker进程的异常退出,肯定是程序有bug了,异常退出,会导致当前worker上的所有请求失败,不过不会影响到所有请求,所以降低了风险。当然,好处还有很多,大家可以慢慢体会。
另外说下prefork工作模型,每个worker进程都是从master进程fork过来.在master进程里面,先建立好需要listen的socket之后,然后再fork出多个worker进程,这样每个worker进程都可以去accept这个socket( fork的进程空间是copy on write产生的,多个子进程会继承该文件描述符).
我们模拟用户请求过来的场景, 当一个连接进来后,所有在accept在这个socket上面的进程,都会收到通知,而只有一个进程可以accept这个连接,其它的则accept失败.多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的.一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求. worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致.
闲扯:
设计思想跟代码实现(包括代码片段) 极其认真的参考了gunicorn框架 详细介绍 . 可能有些朋友在纳闷、疑惑. 怀疑我为毛又在造轮子,但我想说的是gunicorn代码理解起来不简单,里面还真有不少UNIX设计艺术在里面. 再提一句, gunicorn的代码质量很高,实现的prefork也很是优雅,但是他更多是为web framework打造的.当用gunicorn启动web应用的时候,其实gunicorn为后面的几个web做了各方面的适配. 那我如果只是想做个Master Worker这样的进程管理,那么gunicorn是做不到的,除非是你改gunicorn代码,如果又想基于刚才说的进程框架之上封装一个RPC或Restful Api服务,那么又咋办? 我的回答是,直接重写一个适合自己的. 我曾经视图改过gunicorn和uwsgi的代码,好融合我以前写过的RPC服务,但世事难料… …
不管是gunicorn or uwsgi的Master Worker ,Prefork 跟wsgi耦合的太紧密… 结果呢? 这项目就是结果! 更多的内幕及后续的文档更新,我会放在我博客里面,有兴趣的朋友可以瞅瞅 xiaorui.cc
要做的事情:
- 文档的更新,现在的项目说明是在是太过简陋.
- 要在ProcessHandler上开发一个高性能的RPC示例代码.
现在还存在的BUG:
- pid文件写入有问题
- 多实例控制问题
文档说明
配置文件说明 config.py:
[DEFAULT] #当收到kill信号后,几秒后干掉worker graceful_timeout = 3 #应用的环境变量 base_path = . #日志根目录 log_path = . #是否支持多实例 single_instance = false [jobexecute] #是否需要扔到后端 daemonize = true #进程名字 proc_name = jobexecute #Master主进程PID pidfile = %(base_path)s/master.pid #日志位置 log_file = %(log_path)s/master.log #最大的请求数,也可以理解为是调用测试 max_requests = 10000 #启动的进程数目,每个进程都是一个实例 number_workers = 2使用方法:
首先需要安装ProcessHandler所需要的关联模块,尽量使用标准库来实现.
pip install requirement.txt下面是主要处理任务模块. 根据自己的场景,直接copy代码就可以了.
#blog: http://xiaorui.cc import time import logging import traceback from ProcessHandler.lib.log import setup_file_logging from ProcessHandler.lib.workers.sync import SyncWorker class JobExecute(SyncWorker): LOGGER_NAME = "jobexecute" def __init__(self, cfg, file_logger=None, ppid=None, sockets=None): SyncWorker.__init__(self, cfg, file_logger, ppid) setup_file_logging(self.LOGGER_NAME, self.cfg.log_file) self.logger = logging.getLogger(self.LOGGER_NAME) def setup(self): super(JobExecute, self).setup() def init_process(self): super(JobExecute, self).init_process() def stop(self): super(JobExecute, self).stop() def handle_request(self): while 1: print 'go....' logger.info('go...') time.sleep(1.5) if __name__ == '__main__': pass有问题提Issue !另外强烈推荐看gunicorn的代码,能学到不少东西…
这个厉害呀
尽快加入rpc功能吧
现在支持rpc了?
楼主rss 地址一直没有公开呀.
我也不知道自己的rss是多少… 这篇文章下午更新.