Openresty 性能调优案例

对 gateway (commit id = 8ef7a8f2185c41777) 压测时采集火焰图,压测前需配置 lua_code_cache=on,使用网关默认路由,不配置插件,

qps 如下:

image.png

采集得到的火焰图如下:

image.png

一、找出火焰图的平顶

火焰图就是看顶层的哪个函数占据的宽度最大。只要有平顶,就表示该函数可能存在性能问题

从火焰图中可以看出,apirouter.lua存在比较耗时的调用 lj_str_new, 这一般是由于字符串操作导致的

image.png

逐步注释字符串相关代码进行火焰图分析,发现是由红框标识代码导致,而ngx.re.match函数本身可以被jit,没有更优的替代方法,

image.png

从另一方面考虑,可能是由于ngx.re.match调用次数过多导致,通过代码统计,因为匹配的是默认路由,这段函数总计调用了270次,

修改代码直接路由到默认路由,得到了如下数据:

image.png
image.png

从图中可以看出,相关耗时调用已经消失,qps有所增加,但实际代码中显然不能如此修改。

项目使用遍历所有路由进行转发的算法,算法复杂度为O(n),比较耗时,关于路由算法,后面专门进行分析。

二、观测每个业务函数的宽度( 基于on-cpu-flame(2) )

从火焰图中可以看出,耗时比较长的调用有

1、content_by_lua 阶段

(1)网关返回的response

image.png

从中可以看出,存在字符串操作 lj_str_new,由于.. 操作符每次都会新申请临时空间来拼接字符串,利用table.concat去掉所有临时空间的申请和GC

image.png
image.png

(2) 网关转发至上游的 request 和 response

从图中可以看出转发耗时主要是在发送和接收中,这也是整个请求生命周期中最耗时的操作

image.png

其中每个请求都对请求体进行json解析比较耗时,这个后期可以考虑优化

image.png

2、log_by_lua 阶段

记录metrics最为耗时,暂没发现优化空间

记录log,由于现在是每个请求的日志都立即记录,操作过于频繁,可以累积一定日志后再进行记录

image.png

优化后qps明显提高

image.png

3、rewrite_by_lua 阶段

没有发现优化空间

image.png

4、uuid

生成uuid比较耗时,暂无优化

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容