openresty

来源:互联网 发布:仓库管理系统数据字典 编辑:程序博客网 时间:2024/04/26 08:35

openresty

参数相关

ngx.var.args 包含了参数的最原始形式,eg: c=3&d=4,是可以修改的

ngx.var.arg_c是某个具体的参数,如果存在多个c参数的话,就是一个table,不可以被修改。
当修改完ngx.var.args后,ngx.var.arg_c也会被随之修改。

变量

变量生效范围
ngx_lua 变量范围a.进程间lua_shared_dictb.进程内lua中的全局变量c.请求内local lua 变量, ngx.ctxnginx  location匹配命令  ● 已=开头表示精确匹配如 A 中只匹配根目录结尾的请求,后面不能带任何字符串。  ● ^~ 开头表示uri以某个常规字符串开头,不是正则匹配  ● ~ 开头表示区分大小写的正则匹配;  ● ~* 开头表示不区分大小写的正则匹配  ● / 通用匹配, 如果没有其它匹配,任何请求都会匹配到顺序 no优先级:(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)nginx rewrite指令: http://seanlook.com/2015/05/17/nginx-location-rewrite/last和break区别:    location ~ /Print1{        rewrite ^/(.*) /Print2 last;        content_by_lua 'ngx.say("print1")';    }    location ~ /Print2{        content_by_lua 'ngx.say("print2")';    }---回显  print2  location ~ /Print1{        rewrite ^/(.*) /Print2 break;        content_by_lua 'ngx.say("print1")';    }    location ~ /Print2{        content_by_lua 'ngx.say("print2")';    }---回显  print1  location ~ /Print1{        rewrite ^/(.*) /Print2;        content_by_lua 'ngx.say("print1")';    }    location ~ /Print2{        content_by_lua 'ngx.say("print2")';    }---回显  print2
nginx 内置变量
1.nginx 变量:set $a hello;set $b "$a$a";echo $a;注: 变量是全局可见的,变量的创建和使用是分开的,创建变量是在nginx初始化的阶段,变量的使用是在具体的处理阶段,每一个处理location都会创建一个副本。set/geo指令不仅有赋值的作用,还有创建变量的作用。如果直接使用变量,可能nginx都无法启动。nginx变量的生命周期,单独的location或者发生了location内部跳转的地方,比如用echo_exec或者rewrite使用。301302是利用了浏览器进行外部跳转,不一样。Nginx 内建变量最常见的用途就是获取关于请求或响应的各种信息:$uri  $request_uri区别:$uri是去除host外,?之前的部分;$request_uri是包含host和?的部分$arg_变量群,eg: $arg_name是uri中包含了name的时候,$arg_name是name的未解码的数值。$arg_name可以匹配name或者NAME,Name等许多内部变量是只读的,比如$uri或者$request_uri等。应当避免对它们的赋值,可能会出现意想不到的后果。支持改写的变量$args:用来获取当前uri的参数串(?后面的部分),并且可以修改。proxy_pass http://127.0.0.1:8091/testNginx 模块在创建变量时,可以选择是否为变量分配存放值的容器,以及是否自己提供与读写操作相对应的“存取处理程序”。不是所有的 Nginx 变量都拥有存放值的容器。拥有值容器的变量在 Nginx 核心中被称为“被索引的”(indexed);反之,则被称为“未索引的”(non-indexed)。nginx对uri的参数处理不是在读取的时候就进行处理和变量存储,而是当使用了$args_name的时候,才去解析和处理。map $args $foo{    default 0;    debug 1;};用户变量$foo的数值邮nginx内建变量$args来决定。 default是系统默认的,即直接取$foo的时候,$foo0. 如果将$args设置为debug,则$foo1(注:对$arg的设置是在uri中,因为map 指令其实是一个比较特殊的例子,因为它可以为用户变量注册“取处理程序”,而且用户可以自己定义这个“取处理程序”的计算规则。而“取处理程序”只有在该用户变量被实际读取时才会执行,这是一种惰性求值).请求:主请求:由http外部发起的,包括echo_exec和rewrite指令。子请求:由 Nginx 正在处理的请求在 Nginx 内部发起的一种级联请求。“子请求”在外观上很像 HTTP 请求,但实现上却和 HTTP 协议乃至网络通信一点儿关系都没有。它是 Nginx 内部的一种抽象调用,目的是为了方便用户把“主请求”的任务分解为多个较小粒度的“内部请求”,并发或串行地访问多个 location 接口,然后由这些 location 接口通力协作,共同完成整个“主请求”。当然,“子请求”的概念是相对的,任何一个“子请求”也可以再发起更多的“子子请求”,甚至可以玩递归调用(即自己调用自己)。当一个请求发起一个“子请求”的时候,按照 Nginx 的术语,习惯把前者称为后者的“父请求”(parent request)。其执行是按照配置的顺序串行执行。 Nginx 核心在实现“子请求”的时候,就只调用了若干个 C 函数,完全不涉及任何网络或者 UNIX 套接字(socket)通信。我们由此可以看出“子请求”的执行效率是极高的。eg:echo_location变量的独立空间,每个请求的location都会创建一个独立的副本空间,继承父请求的或者外来的。请求对于location跳转后,变量的影响。一些 Nginx 模块发起的“子请求”却会自动共享其“父请求”的变量值容器,比如ngx_auth_request。 ngx_echo, ngx_lua,以及 ngx_srcache 在内的许多第三方模块都选择了禁用父子请求间的变量共享内建变量都作用于当前请求: location /main {        echo "main uri: $uri";        echo_location /sub;    }    location /sub {        echo "sub uri: $uri";    }请求 /main 的结果是    $ curl 'http://localhost:8080/main'    main uri: /main    sub uri: /sub不幸的是,并非所有的内建变量都作用于当前请求。少数内建变量只作用于“主请求”,比如由标准模块 ngx_http_core 提供的内建变量 $request_method. location /main {        set $var main;        auth_request /sub;        echo "main: $var";    }由auth_request发起的自请求,会改变var的数值,也就是说实现了父子请求的变量共享。nginx内建变量:大部分的内建变量都作用于当前请求,例外情况:  location /main {        echo "main method: $request_method";        echo_location /sub;    }    location /sub {        echo "sub method: $request_method";    }总结: 特殊的请求方法:ngx_auth_request或者特殊的内建变量:$request_method对于请求而言,都有特殊的地方。我们并不能通过标准的 $request_method 变量取得“子请求”的请求方法。为了达到我们最初的目的,我们需要求助于第三方模块 ngx_echo 提供的内建变量 $echo_request_method:    location /main {        echo "main method: $echo_request_method";        echo_location /sub;    }    location /sub {        echo "sub method: $echo_request_method";    }如果真如前面那部分读者所担心的,内建变量的值缓存在共享变量的父子请求之间起了作用,这无疑是灾难性的。我们前面在 (五) 中已经看到 ngx_auth_request 模块发起的“子请求”是与其“父请求”共享一套变量的。下面是一个这样的可怕例子:    map $uri $tag {        default     0;        /main       1;        /sub        2;    }    server {        listen 8080;        location /main {            auth_request /sub;            echo "main tag: $tag";        }        location /sub {            echo "sub tag: $tag";        }    }这里我们使用久违了的 map 指令来把内建变量 $uri 的值映射到用户变量 $tag 上。当 $uri 的值为 /main 时,则赋予 $tag 值 1,当 $uri 取值 /sub 时,则赋予 $tag 值 2,其他情况都赋 0. 接着,我们在 /main 接口中先用 ngx_auth_request 模块的 auth_request 指令发起到 /sub 接口的子请求,然后再输出变量 $tag 的值。而在 /sub 接口中,我们直接输出变量 $tag. 猜猜看,如果我们访问接口 /main,将会得到什么样的输出呢?    $ curl 'http://localhost:8080/main'    main tag: 2执行顺序:1.不同的nginx模块有不同的执行阶段,最特殊的是content阶段,只能有一个模块。在其他的同一个处理阶段,不同模块的执行顺序不一定。绝大多数 Nginx 模块在向 content 阶段注册配置指令时,本质上是在当前的 location 配置块中注册所谓的“内容处理程序”(content handler)。每一个 location 只能有一个“内容处理程序”,因此,当在 location 中同时使用多个模块的 content 阶段指令时,只有其中一个模块能成功注册“内容处理程序”。echo 和content_by_lua不能同时执行。一个location里面可以连续写两个echo,但是一个location里面不能连续写两个content_by_luangx_proxy 模块的 proxy_pass 指令和 echo 指令也不能同时用在一个 location 中index autoindex只作用于以/结尾的请求。location / {        root /var/www/;    }location / 中没有使用运行在 content 阶段的模块指令,于是也就没有模块注册这个 location 的“内容处理程序”,处理权便自动落到了在 content 阶段“垫底”的那 3 个静态资源服务模块。首先运行的 ngx_index 和 ngx_autoindex 模块先后看到当前请求的 URI,/index.html 和 /hello.html,并不以 / 结尾,于是直接弃权,将处理权转给了最后运行的 ngx_static 模块。ngx_static 模块根据 root 指令指定的“文档根目录”(document root),分别将请求 URI /index.html 和 /hello.html 映射为文件系统路径 /var/www/index.html 和 /var/www/hello.html,在确认这两个文件存在后,将它们的内容分别作为响应体输出,并自动设置 Content-Type、Content-Length 以及 Last-Modified 等响应头。Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log.最先执行的 post-read 阶段在 Nginx 读取并解析完请求头(request headers)之后就立即开始运行。post-read 阶段之后便是 server-rewrite 阶段。配置语句 set $a hello 直接写在了 server 配置块中,因此它就运行在 server-rewrite 阶段。而 server-rewrite 阶段要早于 rewrite 阶段运行,因此写在 location 配置块中的语句 set $b "$a, world" 便晚于外面的 set $a hello 语句运行。紧接在 server-rewrite 阶段后边的是 find-config 阶段。这个阶段并不支持 Nginx 模块注册处理程序,而是由 Nginx 核心来完成当前请求与 location 配置块之间的配对工作。换句话说,在此阶段之前,请求并没有与任何 location 配置块相关联。因此,对于运行在 find-config 阶段之前的post-read 和 server-rewrite 阶段来说,只有 server 配置块以及更外层作用域中的配置指令才会起作用。这就是为什么只有写在 server 配置块中的 ngx_rewrite 模块的指令才会运行在 server-rewrite 阶段,这也是为什么前面所有例子中的 ngx_realip 模块的指令也都特意写在了 server 配置块中,以确保其注册在 post-read 阶段的处理程序能够生效。运行在 find-config 阶段之后的便是我们的老朋友 rewrite 阶段。由于 Nginx 已经在 find-config 阶段完成了当前请求与 location 的配对,所以从 rewrite 阶段开始,location 配置块中的指令便可以产生作用。前面已经介绍过,当 ngx_rewrite 模块的指令用于 location 块中时,便是运行在这个rewrite 阶段。另外, ngx_set_misc 模块的指令也是如此,还有 ngx_lua 模块的 set_by_lua 指令和 rewrite_by_lua 指令也不例外。rewrite 阶段再往后便是所谓的 post-rewrite 阶段。这个阶段也像 find-config 阶段那样不接受 Nginx 模块注册处理程序,而是由 Nginx 核心完成 rewrite 阶段所要求的“内部跳转”操作(如果 rewrite 阶段有此要求的话)。这里在 location /foo 中通过 rewrite 指令把当前请求的 URI 无条件地改写为 /bar,同时发起一个“内部跳转”,最终跳进了 location /bar 中。这里比较有趣的地方是“内部跳转”的工作原理。“内部跳转”本质上其实就是把当前的请求处理阶段强行倒退到 find-config 阶段,以便重新进行请求 URI 与 location 配置块的配对。比如上例中,运行在 rewrite 阶段的 rewrite 指令就让当前请求的处理阶段倒退回了 find-config 阶段。由于此时当前请求的 URI 已经被 rewrite 指令修改为了 /bar,所以这一次换成了 location /bar 与当前请求相关联,然后再接着从 rewrite 阶段往下执行。不过这里更有趣的地方是,倒退回 find-config 阶段的动作并不是发生在 rewrite 阶段,而是发生在后面的 post-rewrite 阶段。上例中的 rewrite 指令只是简单地指示 Nginx 有必要在 post-rewrite 阶段发起“内部跳转”。这个设计对于 Nginx 初学者来说,或许显得有些古怪:“为什么不直接在 rewrite 指令执行时立即进行跳转呢?”答案其实很简单,那就是为了在最初匹配的 location 块中支持多次反复地改写 URIpost-read:  解析完http headerserver-rewrite: set $var value;find-config: 不支持nginx注册处理程序,完成配置中location块于server的配对工作。rewrite: ngx_set_misc, set_by_lua, rewrite_by_luapost-write:不接受nginx注册处理程序,完成rewrite的跳转。preacess: ngx_limit_req 和 ngx_limit_zone 前者可以控制请求的访问频度,而后者可以限制访问的并发度。access: 用于访问权限的设置post-access:try-files: 对于静态访问的文件,依次处理content: 对http头部做一些处理后,进行跳转log:test.lua文件:调用ngx_lua_module的api接口进行编程https://github.com/openresty/lua-nginx-module#nginx-api-for-lua3.request.luangx.var : nginx 变量,如果要赋值如 ngx.var.b = 2,此变量必须提前声明;另外对于 nginx location 中使用正则捕获的捕获组可以使用 ngx.var [捕获组数字]获取;ngx.req.get_headers:获取请求头,默认只获取前100,如果想要获取所以可以调用ngx.req.get_headers(0);获取带中划线的请求头时请使用如 headers.user_agent 这种方式;如果一个请求头有多个值,则返回的是 table;ngx.req.get_uri_args:获取 url 请求参数,其用法和 get_headers 类似;ngx.req.get_post_args:获取 post 请求内容体,其用法和 get_headers 类似,但是必须提前调用 ngx.req.read_body() 来读取 body 体(也可以选择在 nginx 配置文件使用lua_need_request_body on;开启读取 body 体,但是官方不推荐);ngx.req.raw_header:未解析的请求头字符串;ngx.req.get_body_data:为解析的请求 body 体内容字符串。如上方法处理一般的请求基本够用了。另外在读取 post 内容体时根据实际情况设置 client_body_buffer_size 和 client_max_body_size 来保证内容在内存而不是在文件中。4.response.luareturn ngx.exit(200)  ngx.header:输出响应头;ngx.print:输出响应内容体;ngx.say:通ngx.print,但是会最后输出一个换行符;ngx.exit:指定状态码退出。ngx.redirect()没有生效??????????5.ngx lua处理阶段:Nginx 共11个处理阶段,而相应的处理阶段是可以做插入式处理,即可插拔式架构;另外指令可以在 http、server、server if、location、location if 几个范围进行配置:指令                          所处处理阶段                                       使用范围                              解释init_by_lua                   loading-config                                    http                                  nginx Master进程加载配置时执行;通常用于初始化全局配置/预加载Lua模块                                 init_worker_by_lua            starting-worker                              http                                  每个Nginx Worker进程启动时调用的计时器,如果Master进程不允许则只会在init_by_lua之后调用;通常用于定时拉取配置/数据,或者后端服务的健康检查set_by_lua                    rewrite                                           server,server if,location,location if 设置nginx变量,可以实现复杂的赋值逻辑;此处是阻塞的,Lua代码要做到非常快;   通过set实现的url跳转控制没有那么灵活,所以把控制的逻辑实现最终交给set_by_lua来实现rewrite_by_lua                rewrite tail                                      http,server,location,location if           rrewrite阶段处理,可以实现复杂的转发/重定向逻辑;access_by_lua                 access tail                                      http,server,location,location if           请求访问阶段处理,用于访问控制content_by_lua                content                                          location,location if                         内容处理器,接收请求处理并输出响应header_filter_by_lua          output-header-filter                       http,server,location,location if     设置header和cookiebody_filter_by_lua            output-body-filter                           http,server,location,location if     对响应数据进行过滤,比如截断、替换。log_by_lua                    log                                                   http,server,location,location if     log阶段处理,比如记录访问量/统计平均响应时间a)init_by_lua每次 Nginx 重新加载配置时执行,可以用它来完成一些耗时模块的加载,或者初始化一些全局配置;在 Master 进程创建 Worker 进程时,此指令中加载的全局变量会进行 Copy-OnWrite,即会复制到所有全局变量到 Worker 进程。脚本的声明要放在http中,不能放在server中,因为是一个初始化脚本;不能加ngx.exit(),还没到退出的时候b)init_worker_by_lua用于启动一些定时任务,比如心跳检查,定时拉取服务器配置(主要还是定时器的使用)等等;此处的任务是跟 Worker 进程数量有关系的,比如有2个 Worker 进程那么就会启动两个完全一样的定时任务。放在http部分进行声明,和init_by_lua一样,是全局性的配置,不需要放在单独的server里面。c)set_by_lua设置 nginx 变量,我们用的 set 指令即使配合 if 指令也很难实现负责的赋值逻辑;语法 set_by_lua_file $var lua_file arg1 arg2...; 在 lua代码中可以实现所有复杂的逻辑,但是要执行速度很快,不要阻塞;该lua在执行的时候会发生阻塞,所以这边的lua脚本效率一定要高。set_by_lua中不能执行ngx.say(),但是可以执行ngx.log,也就是说不能作为回显的作用d)rewrite_by_lua执行内部 URL 重写或者外部重定向,典型的如伪静态化的 URL 重写。其默认执行在 rewrite 处理阶段的最后。rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php重写。语法rewrite regex replacement [flag];nginx的rewrite规则参考:已=开头表示精确匹配^~ 开头表示uri以某个常规字符串开头,不是正则匹配~ 开头表示区分大小写的正则匹配;~* 开头表示不区分大小写的正则匹配/ 通用匹配, 如果没有其它匹配,任何请求都会匹配到-f和!-f用来判断是否存在文件-d和!-d用来判断是否存在目录-e和!-e用来判断是否存在文件或目录-x和!-x用来判断文件是否可执行init:上下文为init_by_lua或init_by_lua_file;init_worker:上下文为init_worker_by_lua或init_worker_by_lua_file;ssl_cert:上下文为ssl_certificate_by_lua_block 或 ssl_certificate_by_lua_file;set:上下文为 set_by_lua或 set_by_lua_file;rewrite:上下文为rewrite_by_lua 或 rewrite_by_lua_file;balancer:上下文为balancer_by_lua_block或 balancer_by_lua_file;access:上下文为access_by_lua 或 access_by_lua_file;content:上下文为content_by_lua或 content_by_lua_file;header_filter:上下文为body_filter_by_lua或 body_filter_by_lua_file;body_filter:上下文为log_by_lua或log_by_lua_file;log:上下文为log_by_lua或 log_by_lua_file;timer:上下文为使用ngx.timer的回调函数;e)利用nginx搭建文件服务器http://www.centoscn.com/nginx/2015/0128/4578.html/home/html/abc的使用alias和root区别location /abc/ {    alias /home/html/abc/;}location /abc/ {    root /home/html/;}nginx流量复制:1.tcpcopy2.httpluamoduleeg:根据cookie进行不同的流量分发:a)可以用map实现 b)可以手动获取cookie数值,然后进行分发eg:进行流量复制:在lua中进行串行复制用ngx.location.capture_multi用协程实现:ngx.thread.spawnnginx upstream引流:在http节点下,添加upstream节点在location下添加proxy_pass,这样upstream会引流到节点下。@表示重定向error_page 404 = @redirectionlocal @redirection{    content_by_lua_file xxxx;    http_proxy http://back_end/xxxx    http_proxy http://xxx.com/error.html}rewrite详细解释:1.http://nginx.org/en/docs/http/ngx_http_rewrite_module.htmlrewrite regex replacement [flag];[flag]last:表示继续需找Location进行重定向;break:停止处于同一作用域的后续代码的执行;redirect:302重定向,前提是replacement不是以http://和https://开头;permanent:301永久定向。301302都对于用户来说,表现是一样的,都相当于浏览器发生两次跳转。对于服务端来说,302容易被视为垃圾处理。rewite不能只针对uri生效,不包括域名和http参数location /download/(带download和不带download是有区别的,带download只能用break,而不能用last) {    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;    return  403;}格式:只对uri部分生效rewrite regex replacement [flag];如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。last : 相当于Apache的[L]标记,表示完成rewritebreak : 停止执行当前虚拟主机的后续rewrite指令集redirect : 返回302临时重定向,地址栏会显示跳转后的地址permanent : 返回301永久重定向,地址栏会显示跳转后的地址因为301302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 lastbreak 区别有点难以理解:last一般写在server和if中,而break一般使用在location中last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配breaklast都能组织继续执行后面的rewrite指令breaklast只在location中有区别,break表示跳转后还在本location的作用域,last表示发生了新的跳转匹配。

nginx misc

nginx子请求: 包括ngx.location.capture(uri),都是从 server rewrite phase 开始执行起的,同时会跳过 access phase.

调试

nginx 调试

nginx coredump

nginx lua 调试
1.watch命令可以查看内存,监控全局变量的内存信息会更好一些:watch *(ngx_shm_zone_init_pt *)0xXXXXX2.宏定义info macro MAC_NAMEp MAC_NAME如果要调试宏,需要将-g选项更改为--ggdb3,得到的编译文件会比较大。如果运行到main,info macro MAC_NAME无法显示,可以先list宏的文件位置再去查询。原因是gdb将当前代码列表作为一个作用域。r3.cgdb4.strace/pstackstrace:  -p pid / -o filename / -f 跟踪其通过fork产生的子进程/ -t 系统调用的发起时间/ -T 系统调用的消耗时间pstack 进程号: 查看函数调用堆的关系5.获得nginx程序执行的完整流程:方法很多: system tap/ gcc -finstrument- functions 提供函数调用追踪记录功能。  其他方法??将地址转换为函数名: addr2line -e a -a 0x4005666.打桩测试:对于slab机制,直接观看不明显,打桩测试然后再gdb跟踪7.特殊应用逻辑的调试:对于IE/火狐发出请求的行为已经固定; 对于构造curl/wget的源码定制比较困难;解决方法:自己写socket通信的客户端。8. lua调试http://wiki.jikexueyuan.com/project/lua/debugging.html
openresty lua调试
1.lua脚本调试:A用zerobrane:进行本地测试:A配置环境变量export ZBS=/opt/zbstudioexport LUA_PATH="./?.lua;$ZBS/lualibs/?/?.lua;$ZBS/lualibs/?.lua"export LUA_CPATH="$ZBS/bin/linux/x64/?.dll;$ZBS/bin/linux/x64/clibs/?.dll"/opt/zbstudio/lualibs/?/?.lua;/opt/zbstudio/lualibs/?.luac/opt/zbstudio/bin/linux/x64/?.dll;/opt/zbstudio/bin/linux/x64/clibs/?.dll用zerobrane加载lua后启动即可。B openresty lua调试修改nginx.conf文件    lua_package_path "$prefix/app/lib/?.lua;$prefix/app/etc/?.lua;$prefix/app/src/?.lua;$prefix/../luajit/share/lua/5.1/?.lua;/opt/zbstudio/lualibs/?/?.lua;/opt/zbstudio/lualibs/?.lua;";    lua_package_cpath "$prefix/app/lib/?.so;$prefix/../luajit/lib/lua/5.1/?.so;/opt/zbstudio/bin/linux/x64/?.so;/opt/zbstudio/bin/linux/x64/clibs/?.so;";在脚本中增加如下配置:require('mobdebug').start('127.0.0.1')require('mobdebug').done()启动远程ie进行调试:起动IDE,执行调试。我们IDE菜单上的project-> project directory-> choose选择打开,我们这个工程的目录,选set from current file, 把工程中的test.lua作为当前要处理的文件。下面关键的一点,在project 菜单里,一定要点选 "Start Debugger Server"。B用lua debug进行调试nginx调试方法,在编译的时候打开debug选项http://blog.sina.com.cn/s/blog_6d579ff40100xm7t.html2. 在构造 OpenResty 时,启用其 ./configure 脚本的 --with-debug 选项,此时会开启 LuaJIT 的断言检查和 API 检查。 3. 配置 nginx 生成 core dump 文件(见文档 http://wiki.nginx.org/Debugging#Core_dump ),这样你可以在 nginx worker 崩溃时得到 core dump 文件。然后你可以使用 gdb 对此 core dump 进行分析,比如使用 bt full 命令得到崩溃位置上完整的 C 调用栈轨迹。也可以使用我们的 nginx gdb utils 项目中的工具从 core dump 得到更多的信息:https://github.com/openresty/nginx-gdb-utils#readme 特别是其中的 lbt、lgc、lgcstat、lvmst 这些gdb 扩展命令。 4. 检查你使用的 OpenResty 以外的 Lua C 模块或者使用了使用了 LuaJIT FFI 的 Lua 模块(即 Lua 库),以及是否使用了 OpenResty 以外的 NGINX C 模块。这些我们未测试过的 Lua 库或者 NGINX 模块可能会引入我们无法控制的内存问题。 5. 尝试使用 Valgrind memcheck 工具运行你的 nginx 应用,检查是否有内存问题。在此运行模式下,建议使用下面的命令构造 OpenResty:      ./configure --with-debug --with-no-pool-patch \            --with-luajit-xcflags='-DLUAJIT_USE_SYSMALLOC -DLUAJIT_USE_VALGRIND' 然后在 valgrind 运行模式下,在 nginx.conf 中作如下配置:     worker_processes  1;     daemon off;     master_process off; 在用 valgrind 启动 nginx 以后,再用你的测试请求不断访问 nginx,直到 valgrind 产生错误报告。 > 我用的是openresty-1.4.3.6  + ngx_lua-0.9.7 版本 >
0 0