使用 Nginx的Lua 扩展 功能

1、Nginx 简介

转自 :https://blog.csdn.net/ygm_linux/article/details/53534933

Nginx 作为一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具有占有内存少,稳定性高等优势。其流行度越来越高,应用也越来越广泛,常见的应用有:网页服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器,高并发大流量站点常用来做接入层的负载均衡,还有非常常见的用法是作为日志采集服务器等。

Nginx 整体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。其中模块化设计是nginx的一大卖点,甚至http服务器核心功能也是一个模块。要注意的是:nginx的模块是静态的,添加和删除模块都要对nginx进行重新编译,这一点与Apache的动态模块完全不同。不过后来淘宝做了二次开发开源的 tengine 是支持 官方所有的 HTTP 模块动态加载而不必重新编译 Nginx,除非是第三方模块才需要重新编译。因此,在生产环境中,推荐用淘宝开源的 tengine,本文也以 tengine 作为示例。

虽然 Nginx 有如此强大的性能以及众多的三方模块支持,但每次重新编译以及寻找三方模块对生产环境来说还是不可接受的,幸运的是,Nginx 它是支持客户自己 Lua 脚本编程扩展相应的功能的,而且可以热加载,这就给生产环境带来了无限可能。比如我现在想要直接用Nginx + redis 做反爬虫和频率限制,Nginx + Kafka 做日志的实时流处理等等。

注:lvs 和 nginx 的负载均衡区别:

LVS:Linux Virtual Server,基于IP的负载均衡和反向代理技术,所以它几乎可以对所有应用做负载均衡,包括http、数据库、在线聊天室等等,LVS工作在4层,在Linux内核中作四层交换,只花128个字节记录一个连接信息,不涉及到文件句柄操作,故没有65535最大文件句柄数的限制。LVS性能很高,可以支持100~400万条并发连接。抗负载能力强、是工作在网络4层之上仅作分发之用,没有流量的产生,这个特点也决定了它在负载均衡软件里的性能最强的,对内存和cpu、IO资源消耗比较低。 

Nginx:基于HTTP的负载均衡和反向代理服务器,Nginx工作在网络的7层,所以它可以针对http应用本身来做分流策略,比如针对域名、URL、目录结构等,相比之下LVS并不具备这样的功能,能够很好地支持虚拟主机,可配置性很强,大约能支持3~5万条并发连接。

2、Lua 简介

Lua 是一个简洁、轻量、可扩展的脚本语言,也是号称性能最高的脚本语言,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark的脚本,当你把他的源码下下来编译后,你会发现解释器居然不到200k,非常变态。。。很多应用程序使用Lua作为自己的嵌入式脚本语言,以此来实现可配置性、可扩展性。

 

Lua原生支持的数据类型非常之少,它只提供了nil、数字(缺省是双精度浮点数,可配置)、布尔量、字符串、表、子程序、协程(coroutine)以及用户自定义数据这8种。但是其处理表和字符串的效率非常之高,加上元表的支持,开发者可以高效的模拟出需要的复杂数据类型(比如集合、数组等)。Lua是一个动态弱类型语言,支持增量式垃圾收集策略。有内建的,与操作系统无关的协作式多线程(coroutine)支持。它还可以用于嵌入式硬件,不仅可以嵌入其他编程语言,而且可以嵌入微处理器中。

3、nginx执行步骤

nginx在处理每一个用户请求时,都是按照若干个不同的阶段依次处理的,与配置文件上的顺序没有关系,详细内容可以阅读《深入理解nginx:模块开发与架构解析》这本书,这里只做简单介绍;

(1)post-read

读取请求内容阶段,nginx读取并解析完请求头之后就立即开始运行;

(2)server-rewrite

server请求地址重写阶段;

(3)find-config

配置查找阶段,用来完成当前请求与location配重块之间的配对工作;

(4)rewrite

location请求地址重写阶段,当ngx_rewrite指令用于location中,就是再这个阶段运行的;

(5)post-rewrite

请求地址重写提交阶段,当nginx完成rewrite阶段所要求的内部跳转动作,如果rewrite阶段有这个要求的话;

(6)preaccess

访问权限检查准备阶段,ngx_limit_req和ngx_limit_zone在这个阶段运行,ngx_limit_req可以控制请求的访问频率,ngx_limit_zone可以控制访问的并发度;

(7)access

权限检查阶段,ngx_access在这个阶段运行,配置指令多是执行访问控制相关的任务,如检查用户的访问权限,检查用户的来源IP是否合法;

(8)post-access

访问权限检查提交阶段;

(9)try-files

配置项try_files处理阶段;

(10)content

内容产生阶段,是所有请求处理阶段中最为重要的阶段,因为这个阶段的指令通常是用来生成HTTP响应内容的;

(11)log

日志模块处理阶段;

图:Nginx 模块执行顺序与阶段

4、ngx_lua 运行指令

ngx_lua属于nginx的一部分,它的执行指令都包含在nginx的11个步骤之中了,相应的处理阶段可以做插入式处理,即可插拔式架构,不过ngx_lua并不是所有阶段都会运行的;另外指令可以在http、server、server if、location、location if几个范围进行配置:

指令

所处处理阶段

使用范围

解释

init_by_lua

init_by_lua_file

loading-config

http

nginx Master进程加载配置时执行;

通常用于初始化全局配置/预加载Lua模块

init_worker_by_lua

init_worker_by_lua_file

starting-worker

http

每个Nginx Worker进程启动时调用的计时器,如果Master进程不允许则只会在init_by_lua之后调用;

通常用于定时拉取配置/数据,或者后端服务的健康检查

set_by_lua

set_by_lua_file

rewrite

server,server if,location,location if

设置nginx变量,可以实现复杂的赋值逻辑;此处是阻塞的,Lua代码要做到非常快;

rewrite_by_lua

rewrite_by_lua_file

rewrite tail

http,server,location,location if

rrewrite阶段处理,可以实现复杂的转发/重定向逻辑;

access_by_lua

access_by_lua_file

access tail

http,server,location,location if

请求访问阶段处理,用于访问控制

content_by_lua

content_by_lua_file

content

location,location if

内容处理器,接收请求处理并输出响应

header_filter_by_lua

header_filter_by_lua_file

output-header-filter

http,server,location,location if

设置header和cookie

body_filter_by_lua

body_filter_by_lua_file

output-body-filter

http,server,location,location if

对响应数据进行过滤,比如截断、替换。

log_by_lua

log_by_lua_file

log

http,server,location,location if

log阶段处理,比如记录访问量/统计平均响应时间

关于这部分详细可以参考这篇:

Refer [4] nginx与lua的执行顺序和步骤说明  

Refer [5] ngx_lua用例说明

5、安装 tengine 以及 Lua 扩展

 

(1)先安装Nginx需要的一些类库:

yum install gcc

yum install gcc-c++

注:此步骤只是在你的系统没有安装 gcc/gcc-c++ 的情况下才需要自行编译安装。

(2)编译安装库LuaJit-2.0.3:

./configure --prefix=/usr/local/luajit

make PREFIX=/usr/local/luajit

make install PREFIX=/usr/local/luajit

在/etc/profile文件中增加环境变量,并执行 source /etc/profile 使之生效(非必须):

export LUAJIT_LIB=/usr/install/luajit/lib

export LUAJIT_INC=/usr/install/luajit/include/luajit-2.0

注:此步骤只是在你的系统没有安装 LuaJIT 的情况下才需要自行编译安装。

(3)下载模块依赖 pcre-8.34、zlib-1.2.8、ngx_devel_kit 和 lua-nginx-module,最后编译Nginx:

完整的参数可能这样:

 nginx -V

Tengine version: Tengine/2.1.0 (nginx/1.6.2)

built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) 

TLS SNI support enabled

configure arguments: --prefix=/etc/nginx/ --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-cc-opt='-O2 -g -m64 -mtune=generic' --with-pcre=../pcre-8.33 --with-zlib=../zlib-1.2.8 --with-openssl=../openssl-1.0.1l

先 ./configure 各种配置参数以及模块路径,但我这里只是用来测试就精简了不少参数:

./configure --prefix=/opt/soft/nginx --with-pcre=/root/soft/pcre-8.37 --with-zlib=/root/soft/zlib-1.2.8 --with-openssl=/root/soft/openssl-1.0.1p  --add-module=/root/soft/lua-nginx-module-master --add-module=/root/soft/ngx_devel_kit-master --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp

然后 make、make install 即可。

(5)启动Nginx sbin/nginx,浏览器输入http://localhost测试

需要注意的是:

(1)--with-pcre=/root/soft/pcre-8.37 --with-zlib=/root/soft/zlib-1.2.8 指向的是源码路径,而非编译后的路径,否则 make 会报:

 
  1. cd /usr/local/pcre \

  2. && if [ -f Makefile ]; then make distclean; fi \

  3. && CC="gcc" CFLAGS="-O2 -fomit-frame-pointer -pipe " \

  4. ./configure --disable-shared

  5. /bin/sh: ./configure: No such file or directory

  6. make[1]: *** [/usr/local/pcre/Makefile] Error 127

  7. make[1]: Leaving directory `/software/nginx-0.8.53'

  8. make: *** [build] Error 2

 

因为 ./configure --help 看一下帮助说明:

--with-pcre=DIR                 set path to PCRE library sources

set path to PCRE library sources 是让你设置到源码目录,而不是编译安装后的目录

(2)pcre、zlib、openssl 等系统库如果系统没有集成自带,一定要单独编译安装,而 lua-nginx-module、ngx_devel_kit 等插件模块只需要指源码路径给 nginx 一起编译即可,不需要单独编译。

6、一个 Nginx + Lua 测试的例子

 
  1. user work work;

  2. worker_processes 7;

  3.  
  4. error_log /opt/data1/logs/nginx/error.log;

  5. pid /var/run/nginx.pid;

  6. worker_rlimit_nofile 800000;

  7.  
  8. events {

  9. use epoll;

  10. worker_connections 65535;

  11. }

  12.  
  13. http {

  14.  
  15. server {

  16. listen 80;

  17.  
  18. set $idTest "idTest_11111111111" ;

  19. log_format tracklog '$idTest $msec $remote_addr - $remote_user [$time_local] $request '

  20. '"$status" resp_body:"$resp_body" --"$ref1"-- '

  21. '"$http_user_agent"';

  22.  
  23. location ~ /gzip/(.*) {

  24. default_type "text/html";

  25.  
  26. set $resp_body "";

  27. content_by_lua '

  28. --zlib 解码 post gzip 数据

  29. local zlib = require "zlib"

  30. local encoding = ngx.req.get_headers()["Content-Encoding"]

  31.  
  32. if encoding == "gzip" then

  33. ngx.req.read_body()

  34. local body = ngx.req.get_body_data()

  35. ngx.say("++++++++++++++++++++++++++++body data:")

  36. ngx.print(body)

  37. if body then

  38. --ngx.var.resp_body = "55555555555555"

  39. local stream = zlib.inflate()

  40. ngx.var.resp_body = stream(body)

  41. end

  42. end

  43. ';

  44.  
  45. access_log on;

  46. access_log /opt/data1/logs/nginx/pc/track/ooxx.com.access.log tracklog;

  47. }

  48.  
  49. location ~ /post/(.*) {

  50. default_type "text/html";

  51. lua_need_request_body on;

  52. set $resp_body "";

  53. content_by_lua '

  54. ngx.var.resp_body = ngx.var.request_body

  55. ';

  56.  
  57. access_log on;

  58. access_log /opt/data1/logs/nginx/pc/track/ooxx.com.access.log tracklog;

  59. }

  60.  
  61.  
  62. location ~ /lua/(.*) {

  63. default_type "text/html";

  64. set $ref1 "Hello,Nginx & Lua !";

  65. #设置nginx变量

  66. set $a $1;

  67. set $b $host;

  68.  
  69. content_by_lua '

  70. --nginx变量

  71. local var = ngx.var

  72. ngx.say("ngx.var.a : ", var.a, "
    ")

  73. ngx.say("ngx.var.b : ", var.b, "
    ")

  74. ngx.say("ngx.var[2] : ", var[2], "
    ")

  75. ngx.var.b = 2;

  76. ngx.say("
    ")

  77.  
  78. --请求头

  79. ngx.say(ngx.var.httpRef, "
    ")

  80. local headers = ngx.req.get_headers()

  81. for k,v in pairs(headers) do

  82. if type(v) == "table" then

  83. ngx.say(k, " : ", table.concat(v, ","), "
    ")

  84. else

  85. ngx.say(k, " : ", v, "
    ")

  86. end

  87. end

  88. ngx.say("------------headers end-----------", "


    ")

  89.  
  90. --get请求uri参数

  91. ngx.say("uri args begin", "
    ")

  92. local uri_args = ngx.req.get_uri_args()

  93. for k, v in pairs(uri_args) do

  94. if type(v) == "table" then

  95. ngx.say(k, " : ", table.concat(v, ", "), "
    ")

  96. else

  97. ngx.say(k, ": ", v, "
    ")

  98. end

  99. end

  100. ngx.say("uri args end", "
    ")

  101. ngx.say("a: ",ngx.var.arg_a, "
    ")

  102. ngx.say("b: ",ngx.var.arg_b, "
    ")

  103.  
  104. --未经解码的请求 uri

  105. local request_uri = headers["Host"] .. "/" .. ngx.var.request_uri;

  106. ngx.say("request_uri : ", request_uri, "
    ");

  107. --解码后的 uri

  108. local decode_request_uri = headers["Host"] .. "/" .. ngx.unescape_uri(ngx.var.request_uri);

  109. ngx.var.ref1 = decode_request_uri;

  110. ngx.say("decode request_uri : ", decode_request_uri, "
    ");

  111. --MD5

  112. ngx.say("ngx.md5 : ", ngx.md5("123"), "
    ")

  113. --http time

  114. ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "
    ")

  115. --ngx.var.http_referer = "*********************"

  116.  
  117. ';

  118.  
  119.  
  120.  
  121. log_format LogFormatv1 '$idTest@$msec@$remote_addr@-@$remote_user@[$time_local]@$request@'

  122. '"$status"@$body_bytes_sent@"$http_referer"@'

  123. '"$http_user_agent"';

  124.  
  125. access_log on;

  126.  
  127. access_log /opt/data1/logs/nginx/PCv1/track/ooxx.com.access.log LogFormatv1;

  128. }

  129.  
  130. }

  131. }

需要注意的是线上的 Nginx 可能面对的是高并发场景,对于自己的 Lua 代码最好做个压力测试,比如:

 
  1. tcpcopy 

  2.  
  3. 或者

  4.  
  5. ab -c100 -n10000 'http://test.abc.com/lua/test%20haha/?a=3&b=4'

7、关于 64bit Cgywin 下编译安装 Tengine 的一些问题

(1)openSSL 库不支持 64bit Cygwin

 
  1. cryptlib.c:1:0: 错误:您选择的 CPU 不支持 x86-64 指令集

  2.  /* crypto/cryptlib.c */

  3.  ^

  4. cryptlib.c:1:0: 错误:您选择的 CPU 不支持 x86-64 指令集

  5. : recipe for target 'cryptlib.o' failed

  6. make[3]: *** [cryptlib.o] Error 1

  7. make[3]: Leaving directory '/home/Jun/softs/openssl-1.0.1r/crypto'

  8. Makefile:281: recipe for target 'build_crypto' failed

这种要么自己去网上找补丁 patch,要么换成 Cygwin 32bit,还有一种解决方案就是自己在安装 Cygwin 包的时候把 openssl 也装上,也就是说选择安装包的时候尽量装全一点。省得后续自己装遇到各种问题。

这样如果你自己已经装了 openssl 那么可以在configure 的时候去掉openssl 相关的编译依赖选项:

./configure  --with-openssl=/root/soft/openssl-1.0.1p (去掉该项) 

(2)nginx 启动报错:

nginx: [emerg] the maximum number of files supported by select() is 64

毕竟 Cygwin 还是依赖 windows的,各种参数得针对 windows 优化,比如这个报错是说默认配置文件里的 worker_connections 不能超过 64 个,你改成 20 即可。

 
  1. events {

  2.     use epoll;

  3.     worker_connections  65535;

  4. }

比如我这里的编译配置参数是(注意有些目录可能需要提前自己创建):

./configure --prefix=/opt/soft/nginx --with-pcre=/home/Jun/softs/pcre-8.38 --with-zlib=/home/Jun/softs/zlib-1.2.8    --add-module=/home/Jun/softs/ngx_devel_kit-master --add-module=/home/Jun/softs/echo-nginx-module-master  --add-module=/home/Jun/softs/form-input-nginx-module-master     --add-module=/home/Jun/softs/set-misc-nginx-module-master  --add-module=/home/Jun/softs/lua-nginx-module-master --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp

最后 nginx.conf 稍加修改如下(注意有些目录可能需要提前自己创建):

 
  1. worker_processes  2;

  2.  

  3. #error_log  /var/log/nginx/error.log;

  4. pid        /var/run/nginx.pid;

  5.  

  6. events {

  7.     worker_connections  20;

  8. }

  9.  

  10. http {

  11.      

  12.     server {

  13.         listen                          80;

  14.  

  15.         set $idTest "idTest_11111111111" ;

  16.  

  17.         log_format  tracklog '$idTest $msec $remote_addr - $remote_user [$time_local] $request '

  18.                       '"$status" $body_bytes_sent --"$ref1"-- '

  19.                       '"$http_user_agent"';

  20.  

  21.         log_format  LogFormatv1 '$idTest@$msec@$remote_addr@-@$remote_user@[$time_local]@$request@'

  22.                       '"$status"@$body_bytes_sent@"$http_referer"@'

  23.                       '"$http_user_agent"';

  24.  

  25.         access_log  on;

  26.          

  27.         location ~ /lua/(.*) {

  28.             default_type "text/html";  

  29.             set $ref1 "Hello,Nginx & Lua !";    

  30.             #设置nginx变量  

  31.             set $a $1;   

  32.             set $b $host;

  33.          

  34.         content_by_lua '   

  35.             --nginx变量  

  36.             local var = ngx.var  

  37.             ngx.say("ngx.var.a : ", var.a, "
    ")  

  38.             ngx.say("ngx.var.b : ", var.b, "
    ")  

  39.             ngx.say("ngx.var[2] : ", var[2], "
    ")  

  40.             ngx.var.b = 2;  

  41.             ngx.say("
    ")  

  42.    

  43.             --请求头  

  44.            ngx.say(ngx.var.httpRef, "
    ")

  45.            local headers = ngx.req.get_headers()  

  46.            for k,v in pairs(headers) do  

  47.                 if type(v) == "table" then  

  48.                     ngx.say(k, " : ", table.concat(v, ","), "
    ")  

  49.                 else  

  50.                     ngx.say(k, " : ", v, "
    ")  

  51.                 end  

  52.             end  

  53.             ngx.say("------------headers end-----------", "


    ")  

  54.              

  55.             --get请求uri参数  

  56.             ngx.say("uri args begin", "
    ")  

  57.             local uri_args = ngx.req.get_uri_args()  

  58.             for k, v in pairs(uri_args) do  

  59.                 if type(v) == "table" then  

  60.                     ngx.say(k, " : ", table.concat(v, ", "), "
    ")  

  61.                 else  

  62.                     ngx.say(k, ": ", v, "
    ")  

  63.                 end  

  64.             end  

  65.             ngx.say("uri args end", "
    ")  

  66.             ngx.say("a: ",ngx.var.arg_a, "
    ")

  67.             ngx.say("b: ",ngx.var.arg_b, "
    ")

  68.  

  69.             --未经解码的请求 uri  

  70.             local request_uri = headers["Host"] .. "/" .. ngx.var.request_uri;  

  71.             ngx.say("request_uri : ", request_uri, "
    ");  

  72.             --解码后的 uri  

  73.             local decode_request_uri = headers["Host"] .. "/" .. ngx.unescape_uri(ngx.var.request_uri); 

  74.             ngx.var.ref1 = decode_request_uri;

  75.             ngx.say("decode request_uri : ", decode_request_uri, "
    ");  

  76.             --MD5  

  77.             ngx.say("ngx.md5 : ", ngx.md5("123"), "
    ")  

  78.             --http time  

  79.             ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "
    ")  

  80.             --ngx.var.http_referer = "*********************"

  81.             ';

  82.              

  83.             access_log              /var/log/nginx/ooxx.com.access.log               tracklog;

  84.         }

  85.  

  86.     }

  87. }

最后 nginx -s reload 效果如下,http://localhost/lua/?a=1&b=2  请求也正常,和 linux 下结果一致:

8、关于 nginx 正则说明

(1)location 匹配语法规则

Nginx location 的正则匹配语法与优先级容易让新同学迷惑。

 

~      #波浪线表示执行一个正则匹配,区分大小写

~*    #表示执行一个正则匹配,不区分大小写

=      #进行普通字符精确匹配,与location在配置文件中的顺序无关,= 精确匹配会第一个被处理

@     #"@" 定义一个命名的 location,使用在内部定向时,例如 error_page, try_files

^~     标识符后面跟一个字符串。表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,Nginx将在这个字符串匹配后停止进行正则表达式的匹配(location指令中正则表达式的匹配的结果优先使用),如:location ^~ /images/,你希望对/images/这个目录进行一些特别的操作,如增加expires头,防盗链等,但是你又想把除了这个目录的图片外的所有图片只进行增加expires头的操作,这个操作可能会用到另外一个location,例如:location ~* \.(gif|jpg|jpeg)$,这样,如果有请求/images/1.jpg,nginx如何决定去进行哪个location中的操作呢?结果取决于标识符^~,如果你这样写:location /images/,这样nginx会将1.jpg匹配到location ~* \.(gif|jpg|jpeg)$这个location中,这并不是你需要的结果,而增加了^~这个标识符后,它在匹配了/images/这个字符串后就停止搜索其它带正则的location。

例如:

 
  1. location  = / {

  2.   # 只匹配"/".

  3.   [ configuration A ] 

  4. }

  5. location  / {

  6.   # 匹配任何请求,因为所有请求都是以"/"开始

  7.   # 但是更长字符匹配或者正则表达式匹配会优先匹配

  8.   [ configuration B ] 

  9. }

  10. location ^~ /images/ {

  11.   # 匹配任何以 /images/ 开始的请求,并停止匹配 其它location

  12.   [ configuration C ] 

  13. }

  14. location ~* \.(gif|jpg|jpeg)$ {

  15.   # 匹配以 gif, jpg, or jpeg结尾的请求. 

  16.   # 但是所有 /images/ 目录的请求将由 [Configuration C]处理.   

  17.   [ configuration D ] 

  18. }

 

请求URI例子:

  • / -> 符合configuration A

  • /documents/document.html -> 符合configuration B

  • /images/1.gif -> 符合configuration C

  • /documents/1.jpg ->符合 configuration D

=      表示精确的查找地址,如location = /它只会匹配uri为/的请求,如果请求为/index.html,将查找另外的location,而不会匹配这个,当然可以写两个location,location = /和location /,这样/index.html将匹配到后者,如果你的站点对/的请求量较大,可以使用这个方法来加快请求的响应速度。

@      表示为一个location进行命名,即自定义一个location,这个location不能被外界所访问,只能用于Nginx产生的子请求,主要为error_page和try_files。

(2)location 优先级官方文档

  1. =前缀的指令严格匹配这个查询。如果找到,停止搜索。

  2. 所有剩下的常规字符串,最长的匹配。如果这个匹配使用^〜前缀,搜索停止。

  3. 正则表达式,在配置文件中定义的顺序。

  4. 如果第3条规则产生匹配的话,结果被使用。否则,如同从第2条规则被使用。

(3)正则语法

~      为区分大小写的匹配。

~*     不区分大小写的匹配(匹配firefox的正则同时匹配FireFox)。

!~     不匹配的

!~*    不匹配的

.     匹配除换行符以外的任意字符

\w     匹配字母或数字或下划线或汉字

\s     匹配任意的空白符

\d     匹配数字

\b     匹配单词的开始或结束

^     匹配字符串的开始

$     匹配字符串的结束

\W     匹配任意不是字母,数字,下划线,汉字的字符

\S     匹配任意不是空白符的字符

\D     匹配任意非数字的字符

\B     匹配不是单词开头或结束的位置

捕获     (exp)     匹配exp,并捕获文本到自动命名的组里

(?exp)     匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)

(?:exp)     匹配exp,不捕获匹配的文本,也不给此分组分配组号

零宽断言     (?=exp)     匹配exp前面的位置

(?<=exp)     匹配exp后面的位置

(?!exp)     匹配后面跟的不是exp的位置

(?

注释     (?#comment)     这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

Refer:

[1] agentzh 的 Nginx 教程(版本 2015.03.19)

http://openresty.org/download/agentzh-nginx-tutorials-zhcn.html

[2] HttpLuaModule

http://wiki.nginx.org/HttpLuaModule

[3] nginx lua api翻译

http://blog.csdn.net/imlsz/article/details/42915473

[4] nginx与lua的执行顺序和步骤说明

http://www.mrhaoting.com/?p=157

[5] ngx_lua用例说明

http://www.mrhaoting.com/?p=165

[6] 第二章 Nginx+Lua开发入门

http://jinnianshilongnian.iteye.com/blog/2186448

[7] 在Nginx使用Lua扩展功能

http://yikebocai.com/2014/11/generate-seqid-in-nginx-by-lua/

[8] nginx location匹配规则

http://www.nginx.cn/115.html

http://blog.csdn.net/gzh0222/article/details/7845981

[9] 平台服务部署及Web框架

http://weibo.com/p/1001643875679132642345

[10] 我所熟悉的网站负载均衡技术

http://zyan.cc/post/307/

[11] Nginx、LVS及HAProxy负载均衡软件的优缺点详解

http://www.csdn.net/article/2014-07-24/2820837

[12] Nginx 与 Lua 实现一个简单的服务端推方案

http://blogread.cn/it/article/5883?f=wb

[13] 深入 Nginx:我们是如何为性能和规模做设计的

http://blog.jobbole.com/88766/

[14] 本博客 Nginx 配置之性能篇

https://imququ.com/post/my-nginx-conf-for-wpo.html

[15] 系统负载能力浅析

http://www.rowkey.me/blog/2015/09/09/load-analysis/

[16] Nginx学习总结:常用module(二)

http://shift-alt-ctrl.iteye.com/blog/2231359

[16] 为最佳性能调优 Nginx

http://blog.jobbole.com/87531/

[17] Nginx 重写规则指南

http://www.techug.com/85916-2

[18] 跟我学Nginx+Lua开发目录贴

http://jinnianshilongnian.iteye.com/blog/2190344

[19] 第二章 Nginx+Lua开发入门

http://jinnianshilongnian.iteye.com/blog/2186448

[20] Nginx Third party modules

http://wiki.nginx.org/3rdPartyModules

[21] Tengine 新特性介绍

http://tengine.taobao.org/index_cn.html

[22] Nginx开发从入门到精通

http://tengine.taobao.org/book/

[23] Tengine dso动态加载模块

http://www.mylinuxer.com/532.html

[24] Tengine动态模块加载的使用方法

http://www.bkjia.com/Linux/992215.html#top

[25] OpenResty的现状、趋势、使用及学习方法

http://dwz.cn/2j0Dv1

[26] 使用nginx+lua+graphicmagick搭建图片处理服务器

http://shanks.leanote.com/post/Untitled-55ca439338f41148cd000759-23

[27] How to handle gziped capture?

https://github.com/openresty/lua-nginx-module/issues/12

[28] Nginx与Gzip请求

http://huoding.com/2013/09/02/283

转自 :https://blog.csdn.net/ygm_linux/article/details/53534933

你可能感兴趣的:(使用 Nginx的Lua 扩展 功能)