Server中对象的4层生命周期

开发Server程序与普通LAMPWeb编程有本质区别。在传统的Web编程中,PHP程序员只需要关注request到达,request结束即可。而在Server程序中程序员可以操控更大范围,变量/对象可以有四种生存周期。

变量、对象、资源、require/include的文件等下面统称为对象

程序全局期

Server->start之前就创建好的对象,我们称之为程序全局生命周期。这些变量在程序启动后就会一直存在,直到整个程序结束运行才会销毁。

有一些服务器程序可能会连续运行数月甚至数年才会关闭/重启,那么程序全局期的对象在这段时间持续驻留在内存中的。程序全局对象所占用的内存是Worker进程间共享的,不会额外占用内存。

这部分内存会在写时分离(COW),在Worker进程内对这些对象进行写操作时,会自动从共享内存中分离,变为进程全局对象。

程序全局期include/require的代码,必须在整个程序shutdown时才会释放,reload无效

进程全局期

Server启动后会创建多个进程,每个Worker子进程处理的请求数超过max_request配置后,就会自动销毁。Worker进程启动后创建的对象(onWorkerStart中创建的对象),在这个子进程存活周期之内,是常驻内存的。onConnect/onReceive/onClose 中都可以去访问它。

进程全局对象所占用的内存是在当前子进程内存堆的,并非共享内存。对此对象的修改仅在当前Worker进程中有效
进程期include/require的文件,在reload后就会重新加载

会话期

会话期是在onConnect后创建,或者在第一次onReceive时创建,onClose时销毁。一个客户端连接进入后,创建的对象会常驻内存,直到此客户端离开才会销毁。

LAMP中,一个客户端浏览器访问多次网站,就可以理解为会话期。但传统PHP程序,并不能感知到。只有单次访问时使用session_start,访问$_SESSION全局变量才能得到会话期的一些信息。

Server中会话期的对象直接是常驻内存,不需要session_start之类操作。可以直接访问对象,并执行对象的方法。

请求期

请求期就是指一个完整的请求发来,也就是onReceive收到请求开始处理,直到返回结果发送response。这个周期所创建的对象,会在请求完成后销毁。

请求期对象与普通PHP程序中的对象就是一样的。请求到来时创建,请求结束后销毁。



  • 匿名

    onWorkerStart 回调函数创建的对象,应该位于onWorkerStart回调函数的作用域啊, 怎么从onConnect/onReceive/onClose回调函数中访问?

  • ibrahim

    在swoole_server->start中创建的对象属于“程序全局期”吗?

  • 陆卫军

    在swoole_server中,请求处理过程中,再用异步的swoole_client访问外部资源时:访问完毕后不会进行内存回收。比如swoole_server接受到一个请求,处理过程通过swoole_client去抓取jd首页,输出给客户端。这种场景下,资源和类不会被回收。内存一直暴涨。相反,如果用的是 阻塞的swoole_client,所有资源能被回收。

  • 陆卫军

    现象是:异步回调的server中,启用异步client获取第三方资源的时候,server的回调已经执行完毕,相关资源还在被获取第三方资源的client占用,因此不能被回收。而这个异步的client执行完毕后,因为这个异步的client是其它未被回收的资源的一小部分,它仅仅回收了自己。所以内存暴涨。。。。。

  • 陆卫军

    这部分内存泄漏的资源不属于任何一个周期的感觉。

  • 陆卫军

    https://github.com/swoole/redis-async 用作者的redis连接池测试,也存在内存泄漏的问题。 通过 debug_zval_dump()看对象的refcount大于0不能被回收. 基本上这类问题只能靠一个适合大小的 max_request 重新拉起一个进程来解决. 贴数据如下

  • 我梦江南好

    同问。

  • 鸟人

    两个回调里面使用global

  • 2014MyDream

    调用tsrat之前创建的对象在程序全局期,这个对象用的是共享内存? 在worker进程可以调用到程序全局期的对象吗 对于这点非常不理解

  • rtsg

    协程的生命周期呢??