您现在的位置是:首页 > 学无止境
swoole http server 性能优化
转载自:https://mp.weixin.qq.com/s?__biz=MzU5MDY4MzY5Mw==&mid=2247483719&idx=1&sn=2802d81c940086ba48205f6def64a3f4&chksm=fe3bca05c94c43133df997e8c295e9280e163ce4e85d5c5adc7c78db257a08b02b9e15c616a0&mpshare=1&scene=1&srcid=0822nFt0G70Zl2EfeeaAGyZr#rd
上线了一个基于 swoole http server 的服务以后,发现这个服务的请求耗时监控毛刺十分严重,接口耗时波动比较大,经过一段时间的分析,发现这个服务 response 包十分大,有些 response 包高达1 ~ 2M,甚至更大,这样就很清楚了,因为包太多,导致服务相应波动比较大。
这里稍微解释下,为什么 response 包会导致相应时间波动,这里主要有两个方面的影响,第一是包大会导致 swoole 之间进程通信更加耗时,并占用更多资源,第二是包大会导致 swoole 的 reactor 线程发包更加耗时,关于 reactor 的解释,摘自
Swoole的主进程是一个多线程的程序。其中有一组很重要的线程,称之为Reactor线程。它就是真正处理TCP连接,收发数据的线程。 Swoole的主线程在Accept新的连接后,会将这个连接分配给一个固定的Reactor线程,并由这个线程负责监听此socket。在socket可读时读取数据,并进行协议解析,将请求投递到Worker进程。在socket可写时将数据发送给TCP客户端。
那么怎么优化呢?
其实很简单,那就是直接在 swoole 里开启 gzip,这里摘自 swoole 文档
启用Http GZIP压缩。压缩可以减小HTML内容的尺寸,有效节省网络带宽,提高响应时间。必须在write/end发送内容之前执行gzip,否则会抛出错误。swoole_http_response->gzip(int level=1);level 压缩等级,范围是1-9,等级越高压缩后的尺寸越小,但CPU消耗更多。默认为1,调用gzip方法后,底层会自动添加Http编码头,PHP代码中不应当再行设置相关Http头
刚开始我是采用这个方式,确实有些效果,但是效果还不是很明显,然后我想到了一个新的方案,就是 http chunk + gzip,这个 swoole 本身是仅提供了chunk的支持,chunk+gzip需要自己实现,实现也很简单
swoole_http_response->header('Content-Encoding', "gzip"); $content = gzencode($content, 6); $arr = str_split($content, 1024); foreach ($arr as $v) { swoole_http_response->write($v); } swoole_http_response->end();
使用php压缩相应内容,然后使用 swoole_http_response->write 分段发送,上线之后效果很明显,耗时监控毛刺少了很多。
有些机智的同学或许会有这个疑问,swoole http server 一般情况下,会被 nginx 反向代理,nginx 普遍会打开 gzip,那么问题来了,swoole 把数据 gzip 了,nginx 会不会把数据二次压缩。
当然不会了,这可是nginx,来,虽然nginx的文档里并没有说明gzip不会被二次压缩,但是我在源码里找到了相关逻辑
src/http/modules/ngx_http_gzip_filter_module.c,略去无关代码,下面函数调用ngx_http_gzip_ok检测是否是gzip
static ngx_int_tngx_http_gunzip_header_filter(ngx_http_request_t *r){ …… if (!r->gzip_tested) { if (ngx_http_gzip_ok(r) == NGX_OK) { return ngx_http_next_header_filter(r); } } else if (r->gzip_ok) { return ngx_http_next_header_filter(r); } ……}
src/http/ngx_http_core_module.c,略去无关代码,ngx_http_gzip_ok根据http header检测是否是gzip
ngx_int_t
ngx_http_gzip_ok(ngx_http_request_t *r)
{
……
if (ae->value.len < sizeof("gzip") - 1) {
return NGX_DECLINED;
}
……
}
从上述两块代码可以看出,nginx 并不会对 gzip 的包二次压缩。
所以,放心大胆的使用吧。
最后,虽然这篇文章,讲的是针对swoole http server 做的一个优化,但是这个思路,对于其他http server 也同样适用。
下一篇:电商系统之订单系统
文章评论
- 登录后评论
点击排行
-
php-fpm安装、配置与优化
转载自:https://www.zybuluo.com/phper/note/89081 1、php中...
-
centos下postgresql的安装与配置
一、安装(以root身份进行)1、检出最新的postgresql的yum配置从ht...
-
Mysql的大小写敏感性
MYSQL在默认的情况下查询是不区分大小写的,例如:CREATE TABLE...
-
关于URL编码
转载自:http://www.ruanyifeng.com/blog/2010/02/url_encoding....
-
header中的Cache-control
网页的缓存是由HTTP消息头中的“Cache-control”来控制的,常见的...