微信搜索superit|邀请体验:大数据, 数据管理、OLAP分析与可视化平台 | 赞助作者:赞助作者

PHP高并发处理心得

架构 aide_941 2℃ 0评论

服务器配置

  1. Web: 4C8G 120GSSD
  2. MySQL:2C4G

服务器组件

  1. Nginx
  2. PHP
  3. MySQL
  4. Redis

高并发处理心得

  1. 配置nginx status,php-fpm status,nginx/php-fpm日志上传
  2. php-fpm的进程数能准确反映当前的并发数,包括CC攻击
  3. nginx进程数足够用
  4. php-fpm的子进程不要频繁终结和新建,这样会造成额外的开销和连接丢失,,静态子进程
  5. start_server,min_spare_server,max_spare_server都要大,避免突如其来的连接导致php-fpm进程的增加赶不上连接的增多
  6. 单个php-fpm占用的内存不是网上说的30M,平时是6M左右,这点可以从top和free命令查出。最大时估计能达到15M,所以8G内存服务器的最大php进程估计能达到400~500左右,此时MySQL的配置应至少提升到4C8G
  7. MySQL的压力主要在读R,而UCD的操作相比之下非常少,所以读写分离的作用非常明显,只读实例的配置应大于主实例。
  8. 目前Web服务器所用120SSD的最大IOPS是4800,当并发约为20时,session/缓存的请求操作约为2400/S,仅此一项已逼近硬盘的最大IOPS!这也是为什么会偶尔出现session_start超时。Redis的KV结构每秒读写可轻松上10万,完美应对高并发请求,所以,Session和缓存都应该使用效率更高的Redis,而不是File或Memcached!根据实测,切到Redis后,php-fpm进程的阻塞大大减少,slowlog大幅降低。
  9. 组件使用最新的版本,如PHP/Nginx/MySQL/Redis/CentOS

 

 


 

  1. 千万不要被网上的言论带歪了,辟谣:

    单纯凭经验断定一个 PHP-FPM workers 进程占用多少内存是没用的,单个 worker 进程的最高内存占用至少是「在 max_requests 内,内存占用最高的那次 request 所申请的内存」。

    启动大量的 PHP-FPM workers 进程并不能提升高并发的承载能力,反而会导致大量 CPU 上下文切换,尤其是如果你的业务偏向于计算、单次请求所消耗的时间很长,增加 PHP-FPM 进程数量反而会导致平均请求处理时长飙升。

    Swoole / 容器 / Kubernetes 之类的东西并不是银弹,你需要深入学习才能了解它(们)适不适合你的场景和需求。如果你没有投入大量精力改造的准备,我不建议你考虑这些方案。并且,使用所谓的「容器」的确能够将单个容器的 CPU 和内存压到很低,但容器还是要运行在实际的物理机器上的,这对提升并发量并没有什么帮助,反而将一部分计算资源划分给了容器调度进程。

    我的建议是:

    在新业务上线前,要得出你需要多大机器,你需要:(QPS*ART)/NOW=1。
    QPS = Queries per Second. 每秒请求数量,也就是所谓的「并发量」。
    ART = Average Response Time. 平均响应时间,单位秒。
    NOW = Number of Workers. PHP-FPM Worker 的数量。
    根据单位推算,这个公式可以写为 (N/s*s)/N = 1,因此成立。
    假设 QPS = 1000,ART = 0.1s,那么 NOW 为 100 才能够在理想状态下,刚好满足你的业务需求(也就是所有请求都可以在不排队的情况下完成处理)。
    那么为了推算 NOW,你就需要知道 ART。你可以在一台 1 核心 CPU 的机器上跑一下你的业务,PHP-FPM max_children 保持为 1 即可。随后用压测工具跑单并发,即可计算大概的平均响应时间。务必单线程,否则没有参考价值。

    得到 NOW,也就是所需的 Worker 数量之后,你就可以开始推算需要多大机器了。

    一般来说,Worker 进程不建议超过 CPU 核心数的 2~4 倍。因此你可以使用 NOW / 2 甚至 NOW / 4 得到你所需要的 CPU 核心数。

    至于内存,你同样可以在一台内存足够的机器上跑一跑你的业务,max_children 调大些,通过 systemctl 之类的工具观察 FPM Worker 进程的内存占用,得出一个大概内存占用量的大概数值,随后将平均内存占用量 * NOW 即可。

    最后,在生产环境中,建议你:

    先按照推算数量向上提高一个档位,部署一台机器。

    随后通过 htop 等工具观察实际的 CPU 和内存使用率,尤其是 Load Average 的值。

    如果比较稳定或者偏低,可以再降低一个档位部署一台机器(先不要销毁老机器)。

    随后在业务低峰将 DNS 记录指向新机器,注意 DNS 记录的 TTL 不要太高。

    观察新机器的 Load Average,如果偏高或者雪崩可以立即将 DNS Record 回滚到老机器,恭喜你找到了适合你的机型。如果仍然偏低,可以继续循环第 3 – 5 步,最终实践出最适合你的 Instance Type。

转载请注明:SuperIT » PHP高并发处理心得

喜欢 (0)or分享 (0)

您必须 登录 才能发表评论!