记一次LNMP优化过程

首先要给大家说明以下几点:

1.篇幅和时间有限,本篇着重讲实战,理论部分交给超链接

2.本人水平有限,希望大家不吝赐教

3.现在是一个CPU过剩的时代,或者说是一个非常强悍的CPU带着它坑逼的队友们(io总线,内存,缓存,硬盘,Linux,多进程模型,脚本语言,网络带宽)去超神

4.默认情况下使用的是2核/4G ECS

开始着手优化之前我就明显感觉到这个问题稍稍的超出了我的能力范围,但是没关系啊,先看看大家是怎么做的。

我要处理的问题有个非常洋气的名字c10k,c10k实际上瓶颈往往出在io和内文切换,参考。epoll很熟悉嘛,nginx已经做好了,咱也甭操心了。协程也甭考虑了,有本事你把fpm的代码用协程给重构了。那问题就简单多了,优化io就成为了。

0.优化前奏

在优化之前务必开启以下日志:

1.nginx access.log error.log

2.php error.log

3.fpm error.log slow.log

开始优化之前用ab压力测试发现rps很低,这时候nginx输出日志提示连接数过多。参考基友的文章(这货钱多、活好、风骚男同志赶紧加他)做了比较基础的优化后nginx处理能力小幅上升。这时候rps依旧不是很乐观:46。敲个top命令看了下cpu才占用64%!!!为啥cpu跑不满就就到瓶颈了???这个问题很诡异啊——那是因为你不懂linux(top命令详解)。刷新了我的三观,us不是used,而是user的意思。是user占用cpu64%的时间片。id是0也就是说cpu已经跑满了。让人感觉不可思议的是si占用了9%左右,sy占用了27%左右。

这让人感觉很不爽啊,就像是辛辛苦苦干了一个月36%的薪水都不属于自己的!

si:软中断占用百分比

sy:内核空间占用CPU百分比

很明显嘛,内文切换。这个要优化fpm模型咱就暂时不讨论了,如果你真想在这方面优化,继续往下看,下面讨论。

1.优化io&将mysql独立出去


很明显嘛,内文切换。这个要优化fpm模型咱就暂时不讨论了,如果你真想在这方面优化,继续往下看,下

实际上我没有做特殊的io优化,没达到那个量级嘛!我们公司现在的并发能达到1k足以。然后我就开了台io优化过的ecs+ssd。然后把mysql独立出去使用RDS+读写分离。然后rps就上升到468左右了,注意哦!还没加负载均衡。给我马哥烧柱香吧。

个人建议如果条件允许不要自己搭mysql读写分离,水很深,你买阿里云RDS的钱远远少于你请一个高级php的钱。下面我着重讲解一下为啥我非要用io优化+ssd。这就要看你对computer science有多深入的了解了。感谢我大学在cs上打下了不错的基础,然后去翻linux内核的书的时候让我可以轻松点进入状态。

2.扯点Linux内核

1.首先你需要了解的是虚存
这是个很扯的问题呀,每个进程都有4G的内存空间去存对象、变量和数据之类的。而且是放在硬盘上。让人感觉更扯是内存不直接参与运算,直接参与运算的只有寄存器。cpu总要把数据拉倒寄存器里把,总待有个桥之类的东西实现这个功能吧——这个东西叫io总线

2.io总线。有限的时间我只查到了IBM PowerPC的cpu一共只有65536个8bit的io总线。现在你终于知道nginx 的worker_rlimit_nofile 为啥要设置65535了吧,我猜测要留一个给系统中断用。这也是为啥linux的最大文件打开数是65535。

千军万马过65536个独木桥。

这也是为啥会有层出不穷的io复用模型的出现。

其实后面兜了不少圈性能提升不明显。由于公司使用的是一个非常蛋疼的框架,微擎(简称we7)。多次给高层建议重构无果,最终只能硬着头皮优化了。在这里顺便提醒大家一句:千万不要不要以为php简单就动不动自己动手写个框架,因为你很难有机会像开源框架一样接受市场的考验,你更难有开源社区那么多有热情的志愿者不断贡献代码去迭代。

我简单拿we7和tp5对比了一下。发现tp5在优化完nginx cgi连接超时以后表现的很稳定ab测试下几乎不会有Failed。但是we7只要超过1000的用户并发就会不断的报以下三个错误:



2017/12/25 09:37:03 [error] 22582#0: *16081 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 10.26.68.75, server: www.medianewvisual.com, request: "GET /h5/index.php?c=insurance_drawtest&d=StarDraw&i=1 HTTP/1.0", upstream: "fastcgi://127.0.0.1:9001", host: "medianewvisual.com"

2017/12/25 09:37:03 [error] 22582#0: *16081 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 10.26.68.75, server: www.medianewvisual.com, request: "GET /h5/index.php?c=insurance_drawtest&d=StarDraw&i=1 HTTP/1.0", upstream: "fastcgi://127.0.0.1:9001", host: "medianewvisual.com"

2017/12/25 09:46:31 [error] 22581#0: *233603 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 10.26.68.75, server: www.medianewvisual.com, request: "GET /h5/index.php?c=insurance_drawtest&d=StarDraw&i=1 HTTP/1.0", upstream: "fastcgi://127.0.0.1:9001", host: "medianewvisual.com"



这个其实是考验一个框架的功力。我简单看了一下we7源码,数据库连接全是胡扯,就一个pdo对象做了单例(php的单例只能做到Java单例的20%)。完全没有连接池的概念。再仔细看看ab的结果


这也就难怪请求越多死的越多了。更可怕的是一个错误溢出消耗的cpu资源是正常的完整请求的三倍。

3.高级优化思路

大致看了tp5的源码,tp5是有数据库连接池。但是对于没有常住内存进程的php来说,然并卵啊。相比较而言Java就做的比较好,参考c3p0数据库连接池原理。假使就想用php复用mysql连接池呢?可以使用swoole来实现。如果你仅仅做到了这一步,我觉得还不够。可以参考redis的pipeline设计一个缓冲池批量给mysql服务器同步数据。如果再配合上swoole的异步io就更好了。


fpm是使用进程模型做计算密集处理的。以前在看python的协程、线程和进程的时候有“io密集型用协程,计算密集型用进程”的说法。线程切换能占用近1/3的cpu确实很可怕。如果fpm能用协程模型实现着实能提高很高的效率。另外一条路子个人认为也是php未来的一个趋势——jit技术。难道只有我一个人觉得既然nginx 都已经做了多worker、io复用、请求排队这些操作了,fpm岂不是很多余吗?未来一定会有人用php实现一个和OpenRest类似的东西。

在很大的请求量下,频繁的写入日志(nginx log)也是一个很头疼的问题。同样的nginx应该提供一种批量写入日志/延迟写入日志的技术。这点我没有验证,不知道nginx或者Tengine有没有实现类似的功能。



©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • 1. Nginx的模块与工作原理 Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单...
    rosekissyou阅读 10,208评论 5 124
  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,664评论 24 1,002
  • 一、MemCache简介 session MemCache是一个自由、源码开放、高性能、分布式的分布式内存对象缓存...
    李伟铭MIng阅读 3,804评论 2 13
  • Nginx简介 解决基于进程模型产生的C10K问题,请求时即使无状态连接如web服务都无法达到并发响应量级一万的现...
    魏镇坪阅读 1,997评论 0 9
  • ——11.30补充—— 分享一些个人简单的理解 “你,痛苦么?” 人的痛苦有两种: 想要发生的事没发生 不想发生的...
    捍道阅读 764评论 0 3