50

PHP 的多进程并发

 5 years ago
source link: https://mp.weixin.qq.com/s/uww4s7GBicBJ-XSwrYSS_A?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

介绍

php工程师在开发过程中,往往以只需要串行编写业务逻辑即可,完全不用考虑并发。通常部署时配置好nginx, fpm就行。就这样接口便并发的提供web服务了。那到底是怎么实现的呢?一个来自客户端的请求,首先会到达nginx这样的web服务器,然后通过fastcgi协议将请求传递到php这样的处理程序,php执行后返回结果给nginx,nginx最终返回客户端。nginx是高并发服务器,这里我们不细说。主要看看php是怎么实现并发的。

fpm(Fastcgi Process Manager),支持fastcgi外,主要功能是进程管理。以多进程方式工作,由一个master进程与多个worker进程组成,master进程主要功能是管理worker进程,例如维持worker数量在一定范围内。而worker进程则是真正处理请求的,对于单个worker进程,是串行执行接收到的每个请求。这种简单的实现就导致有多少个worker最多同时处理的请求数量就有多少。这也是不能高并发的主要原因。

实现

多进程实现是靠fork这个系统调用完成。

  1. master初始化后,按配置要求fork出worker进程,自身进入事件循环处理中。 worker退出执行请求处理逻辑

MRFbEvy.jpg!web

2. worker正常执行max_requests个请求正常退出

ZfE7zia.jpg!web

细节

1. master如何获取worker的运行信息?

这里是通过共享内存来通信的。在master初始化过中,会进行scoreboard结构的分配(每个worker pool分配一个)。每个worker在处理请求的过程中,会先后将

fpm_request_accepting,

fpm_request_reading_headers,

fpm_request_info,

fpm_request_executing,

fpm_request_end,

fpm_request_finished置位到request_stage, master就可以直接在获取worker状态,例如在多个worker都在等待请求时,减少worker数到最小空闲数。

2. master进入事件循环有哪些处理?

信号处理 : master对接收到的信息进行处理,比如收到关闭信息,则发送信号给worker进程(master与worker进程通信的主要方式是信号)

进程检查定时器 : 每隔一段时间,根据不同策略将worker数量维持在要求的范围内。

超时检查定时器 : 若一个请求处理时长超过request_terminate_timeout, 那master便会发送term信号杀掉worker.

3. 若多个worker同时获取一个请求?

若多个worker都阻塞在fcgi_accept_request, 突然有一个请求到达,为了防止多个进程对accept进行抢占,php在这里加入了锁机制。FCGI_LOCK, FCGI_UNLOCK, 在linux中没实现。因为在linux2.6内核中, accept系统调用已不存在惊群了。

存在的问题

1. fpm是通过多进程实现并发的。并发主要受限于进程的数量,进程的数量又受限于系统的内存,cpu。一般服务器开500+ worker就可以了。但是这些worker又不能充分利用系统资源,主要是大多处理要集中在操作mysql, redis这样的远程资源上了,发起请求后,worker本身就阻塞等待中。真是受限于资源,不能太多进程,而在手的进程又不能完全发送作用。

2. worker串行化处理max_requests个请求,不能高并发。fastcgi_finish_request这些也只是优先返回客户端响应,还是阻塞处理后续逻辑。

3. 基于上面1,2两点,我们知道了php处理能力有限。在特殊情况下,会导致后果呢? 1. 依赖的redis,mysql被慢查询拖住时,多个worker会同时请求超时,到时后续请求得不到处理,直接导致一段时间内请求雪崩。这时应该重启fpm还是解决后端数据资源?  2. 若你的php接口中还代理了其他服务,请合理设置超时,原因同上。

4. max_requests的初衷是为了避免第三方扩展引起的内存泄漏问题。但是,在请求均匀的情况下,多个 worker同时结束,master为了维持worker平衡,会瞬间大量fork,从监控来看会发生锯齿状。百度技术人员通过对max_requests进行随机,优化了这种情况,可以参考: 

http://www.sohu.com/a/163046759_487482

总结

通过fpm这个进程管理器,php实现了让开发者不考虑并发,专注于业务开发,保证了较快的开发效率,但是又是这种简单的多进程实现的并发,不能承载高并发的业务。在技术选型上,开发者要牢记这一点!

iQV3euV.gif

FBJbayv.jpg!web

微信公众号

溜溜技术

简介: 

来自各大移动互联网服务端程序员的思想碰撞平台 。技术、逻辑、思辩、进步、创新。有没有干货,拉出来溜溜!

投稿联系

oscersong007

长按二维码, 发现惊喜


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK