pdf
|<<
<
>
>>|
/
Application of {{#ci|Lua}} in {{#x|Nginx}} Lua 在 Nginx 中的应用 ☺{{#author|agentzh@gmail.com}}☺ {{#author|章亦春 (agentzh)}} {{img src="images/cloudflare2.gif" width="141" height="71"}} {{#date|2015.04}} ---- {{img src="images/lz-shopsummary.png" width="1059" height="723"}} ---- {{img src="images/lz-arch.png" width="1152" height="607"}} ---- {{img src="images/modules-cloud.jpg" width="1186" height="685"}} ---- {{img src="images/chaoscat-big.jpg" width="1100" height="825"}} ---- {{img src="images/nginx-lua-big.png" width="1100" height="398"}} ---- {{img src="images/lua-embed-nginx.png" width="1142" height="662"}} ---- {{#x|☺}} No \"callback hell\". {{#x|☺}} 100% nonblocking IO 没有“回调地狱”。 {{#ci|100%}} 非阻塞I/O. ---- {{img src="images/ngx-lua-cmd-cloud.jpg" width="1186" height="636"}} ---- {{img src="images/cosocket.png" width="1168" height="397"}} ---- {{img src="images/pool.png" width="1133" height="467"}} ---- {{img src="images/lua-resty-cloud.jpg" width="1186" height="715"}} ---- {{#x|☺}} openresty.org ---- {{#x|☺}} qa.openresty.org OpenResty 测试集群 ---- {{img src="images/test-report-new.png" width="978" height="445"}} ---- {{#v|$}} ./dispatcher -r -t {{#c|170}} -a '{{#c|linux x86_64}}' ngx_echo ngx_lua Requires at least {{#x|5}} machines. bucket 1: tl-ngx_lua (264 min) bucket 2: twv-ngx_lua tw-ngx_lua trv-ngx_echo th-ngx_echo (167 min) bucket 3: trv-ngx_lua th-ngx_lua t-ngx_lua tv-ngx_echo tr-ngx_echo (162 min) bucket 4: tv-ngx_lua tl-ngx_echo to-ngx_lua thv-ngx_echo t-ngx_echo (145 min) bucket 5: thv-ngx_lua tr-ngx_lua twv-ngx_echo tw-ngx_echo to-ngx_echo (90 min) ... ---- {{img src="images/cf-arch.png" width="961" height="772"}} ---- {{#x|☺}} Lua SSL {{#x|☺}} Lua CDN {{#x|☺}} Lua WAF (Lua Web 防火墙) ---- {{#x|☺}} Light threads 轻量级线程 ---- {{img src="images/schedule-threads.jpg" width="1100" height="589"}} ---- {{#kw|local}} thread_A, err = {{#x|ngx.thread.spawn}}(func1) {{#cm|-- thread_A keeps running asynchronously}} {{#cm|-- in the background of the current}} {{#cm|-- "light thread".}} ---- {{#kw|local}} ok, res1, res2 = {{#x|ngx.thread.wait}}(thread_A, thread_B) ---- {{#kw|local}} ok, err = {{#x|ngx.thread.kill}}(thread_A) ---- {{#x|☺}} lua-resty-websocket {{#c|WebSocket}} 服务器和客户端 ---- {{#kw|local}} server = {{#kw|require}} \"resty.websocket.server\" {{#kw|local}} wb, err = server:{{#x|new}}{ timeout = 5000, {{#cm|-- in milliseconds}} max_payload_len = 65535, } {{#kw|local}} data, typ, err = wb:{{#x|recv_frame}}() {{#kw|local}} bytes, err = wb:{{#x|send_text}}(\"Hello world\") ---- {{#x|☺}} full-duplex cosockets {{#ci|全双工}}的基于协程的套接字 ---- {{#x|☺}} SSL/TLS cosocket {{img src="images/stock_lock.png" width="128" height="128"}} ---- {{#kw|local}} sock = ngx.socket.tcp() {{#kw|local}} ok, err = sock:connect(\"www.cloudflare.com\", 443) ok, err = sock:{{#x|sslhandshake}}( {{#kw|false}}, {{#cm|-- disable SSL session}} \"www.cloudflare.com\", {{#cm|-- SNI name}} {{#kw|true}} {{#cm|-- verify everything}} ) ---- {{#x|☺}} ssl_certificate_by_lua {{img src="images/stock_lock.png" width="128" height="128"}} 纯 Lua {{#c|动态}}服务 SSL 证书和私钥 ---- {{img src="images/lazyloading.jpg" width="949" height="754"}} ---- {{#kw|ssl_certificate_by_lua}} ' local ssl = require \"{{#x|ngx.ssl}}\" local cert_chain, priv_key = my_load_data() assert(ssl.{{#c|set_der_cert}}(cert_chain)) assert(ssl.{{#c|set_der_priv_key}}(priv_key)) '; ---- {{img src="images/new-nginx-ssl-arch.jpg" width="1234" height="614"}} ---- {{#x|☺}} ssl_balancer_by_lua 纯 Lua 编写 Nginx {{#c|全动态}}负载均衡器 ---- {{#kw|upstream}} { {{#kw|server}} 0.0.0.0; {{#kw|balancer_by_lua}} ' local balancer = require \"{{#x|ngx.balancer}}\" local host, port = my_load_backend_addr() assert(balancer.{{#c|set_cur_peer}}(host, port)) '; } ---- {{#x|☺}} nginx-systemtap-toolkit 基于 {{#ci|Systemtap}} 的 Nginx 工具箱 ---- {{img src="images/nginx-stap-tools-cloud.jpg" width="1186" height="716"}} ---- {{#x|☺}} stapxx (stap++) Systemtap 加上一点{{#c|宏魔法}}…… ---- {{img src="images/stapxx-tools-cloud.jpg" width="1186" height="716"}} ---- {{#x|☺}} How CPU time is spent inside LuaJIT {{#c|CPU 时间}}在 LuaJIT 内部是如何分布的 ---- {{#v|$}} {{#x|lj-vm-states.sxx}} -x 5521 --arg time=60 Start tracing 5521 (/usr/local/nginx-waf/sbin/nginx-waf) Please wait for 60 seconds... Observed 1203 Lua-running samples and ignored 49 unrelated samples. Compiled: {{#c|64%}} (779 samples) C Code (by interpreted Lua): 14% (172 samples) Interpreted: 13% (158 samples) Garbage Collector (compiled): 3% (48 samples) Garbage Collector (not compiled): 3% (42 samples) Trace exiting: 0% (4 samples) ---- {{img src="images/my-day-flame-graph.png" width="1152" height="576"}} ---- {{#x|☺}} When an nginx worker's CPU is too high... 当 nginx worker 进程的 {{#c|CPU 太高}}时…… ---- {{img src="images/on-cpu-sketch.jpg" width="1088" height="512"}} ---- {{#cm|# assuming one nginx worker process has the pid 19647.}} {{#v|$}} {{#x|ngx-rps.sxx -x 19647}} WARNING: Tracing process 19647. Hit Ctrl-C to end. [1376939543] 300 req/sec [1376939544] 235 req/sec [1376939545] 235 req/sec [1376939546] 166 req/sec [1376939547] 238 req/sec [1376939548] 234 req/sec ^C ---- {{#v|$}} {{#x|./sample-bt -p 19647 -t 20 -u}} > a.bt WARNING: Tracing 19647 (/opt/nginx/sbin/nginx) in user-space only... WARNING: Time's up. Quitting now...(it may take a while) ---- {{#cm|# using Brendan Gregg's flame graph tools:}} {{#v|$}} stackcollapse-stap.pl a.bt > a.cbt {{#v|$}} flamegraph.pl a.cbt > a.svg ---- {{img src="images/nginx-c-land-flamegraph.jpg" width="1100" height="538"}} ---- {{#cm|# assuming the nginx worker process pid is 19647:}} {{#v|$}} {{#x|lj-lua-stacks.sxx --arg time=20 --skip-badvars -x 19647}} > a.bt Start tracing 19647 (/opt/nginx/sbin/nginx) Please wait for 20 seconds ---- {{#cm|# using Brendan Gregg's flame graph tools:}} {{#v|$}} stackcollapse-stap.pl a.bt > a.cbt {{#v|$}} flamegraph.pl a.cbt > a.svg ---- {{img src="images/lua-land-flamegraph.jpg" width="1100" height="225"}} ---- {{#x|☺}} When an nginx worker's CPU is low and the throughput is low... 当 nginx worker 进程的 {{#c|CPU 很低}}, 同时{{#c|吞吐量上不去}}的时候…… ---- {{img src="images/off-cpu-sketch.jpg" width="1152" height="448"}} ---- {{#x|☺}} {{#ci|off-CPU}} flame graphs from the {{#x|sample-bt-off-cpu}} tool ---- {{img src="images/off-cpu-flame-graph-nginx-cache-v2.jpg" width="1200" height="658"}} ---- {{img src="images/off-cpu-flame-graph-nginx-cache.jpg" width="1200" height="658"}} ---- {{img src="images/how-systemtap-works.jpg" width="1152" height="576"}} ---- {{#x|☺}} nginx-gdb-utils 基于{{#ci|GDB}} 的Nginx 工具箱 ---- {{img src="images/nginx-gdb-utils-cloud.jpg" width="1186" height="716"}} ---- {{#v|(gdb)}} {{#x|lbt}} C:ngx_http_lua_socket_tcp_receive @.../lib/resty/mysql.lua:191 @.../lib/resty/mysql.lua:530 content_by_lua:10 ---- {{#v|(gdb)}} {{#x|lbt full}} C:ngx_http_lua_socket_tcp_receive @.../lib/resty/mysql.lua:191 local \"self\": table (0x40f181a8) local \"sock\": table (0x40f181b0) @.../lib/resty/mysql.lua:530 local \"self\": table (0x40f18148) local \"opts\": table (0x40f18150) ... ---- {{#v|(gdb)}} {{#x|lgc}} The current memory size (allocated by GC): 898960 bytes ---- {{#v|(gdb)}} {{#x|lgcstat}} 15172 str objects: max=2956, avg = 51, min=18, sum=779126 987 upval objects: max=24, avg = 24, min=24, sum=23688 104 thread objects: max=1648, avg = 1622, min=528, sum=168784 431 proto objects: max=226274, avg = 2234, min=78, sum=963196 952 func objects: max=144, avg = 30, min=20, sum=28900 446 trace objects: max=23400, avg = 1857, min=160, sum=828604 2965 cdata objects: max=4112, avg = 17, min=12, sum=51576 18961 tab objects: max=24608, avg = 207, min=32, sum=3943256 9 udata objects: max=176095, avg = 39313, min=32, sum=353822 ---- ☺ {{#ci|Any questions}}? ☺ 欢迎提问