Nginx 做为一款面向性能设计的HTTP服务器,相较于Apache、lighttpd具备占有内存少,稳定性高等优点。其流行度愈来愈高,应用也愈来愈普遍,常见的应用有:网页服务器、反向代理服务器以及电子邮件(IMAP/POP3)代理服务器,高并发大流量站点经常使用来作接入层的负载均衡,还有很是常见的用法是做为日志采集服务器等。html
Nginx 总体采用模块化设计,有丰富的模块库和第三方模块库,配置灵活。其中模块化设计是nginx的一大卖点,甚至http服务器核心功能也是一个模块。要注意的是:nginx的模块是静态的,添加和删除模块都要对nginx进行从新编译,这一点与Apache的动态模块彻底不一样。不事后来淘宝作了二次开发开源的 tengine 是支持 官方全部的 HTTP 模块动态加载而没必要从新编译 Nginx,除非是第三方模块才须要从新编译。所以,在生产环境中,推荐用淘宝开源的 tengine,本文也以 tengine 做为示例。linux
虽然 Nginx 有如此强大的性能以及众多的三方模块支持,但每次从新编译以及寻找三方模块对生产环境来讲仍是不可接受的,幸运的是,Nginx 它是支持客户本身 Lua 脚本编程扩展相应的功能的,并且能够热加载,这就给生产环境带来了无限可能。好比我如今想要直接用Nginx + redis 作反爬虫和频率限制,Nginx + Kafka 作日志的实时流处理等等。nginx
注:lvs 和 nginx 的负载均衡区别:c++
LVS:Linux Virtual Server,基于IP的负载均衡和反向代理技术,因此它几乎能够对全部应用作负载均衡,包括http、数据库、在线聊天室等等,LVS工做在4层,在Linux内核中做四层交换,只花128个字节记录一个链接信息,不涉及到文件句柄操做,故没有65535最大文件句柄数的限制。LVS性能很高,能够支持100~400万条并发链接。抗负载能力强、是工做在网络4层之上仅做分发之用,没有流量的产生,这个特色也决定了它在负载均衡软件里的性能最强的,对内存和cpu、IO资源消耗比较低。 git
Nginx:基于HTTP的负载均衡和反向代理服务器,Nginx工做在网络的7层,因此它能够针对http应用自己来作分流策略,好比针对域名、URL、目录结构等,相比之下LVS并不具有这样的功能,可以很好地支持虚拟主机,可配置性很强,大约能支持3~5万条并发链接。github
Lua 是一个简洁、轻量、可扩展的脚本语言,也是号称性能最高的脚本语言,用在不少须要性能的地方,好比:游戏脚本,nginx,wireshark的脚本,当你把他的源码下下来编译后,你会发现解释器竟然不到200k,很是变态。。。不少应用程序使用Lua做为本身的嵌入式脚本语言,以此来实现可配置性、可扩展性。正则表达式
Lua原生支持的数据类型很是之少,它只提供了nil、数字(缺省是双精度浮点数,可配置)、布尔量、字符串、表、子程序、协程(coroutine)以及用户自定义数据这8种。可是其处理表和字符串的效率很是之高,加上元表的支持,开发者能够高效的模拟出须要的复杂数据类型(好比集合、数组等)。Lua是一个动态弱类型语言,支持增量式垃圾收集策略。有内建的,与操做系统无关的协做式多线程(coroutine)支持。它还能够用于嵌入式硬件,不只能够嵌入其余编程语言,并且能够嵌入微处理器中。redis
nginx在处理每个用户请求时,都是按照若干个不一样的阶段依次处理的,与配置文件上的顺序没有关系,详细内容能够阅读《深刻理解nginx:模块开发与架构解析》这本书,这里只作简单介绍。nginx实际把http请求处理流程划分为了11个阶段,这样划分的缘由是将请求的执行逻辑细分,以模块为单位进行处理,各个阶段能够包含任意多个HTTP模块并以流水线的方式处理请求。这样作的好处是使处理过程更加灵活、下降耦合度。这11个HTTP阶段以下所示:数据库
1)NGX_HTTP_POST_READ_PHASE:编程
接收到完整的HTTP头部后处理的阶段,它位于uri重写以前,实际上不多有模块会注册在该阶段,默认的状况下,该阶段被跳过。
2)NGX_HTTP_SERVER_REWRITE_PHASE:
URI与location匹配前,修改URI的阶段,用于重定向,也就是该阶段执行处于server块内,location块外的重写指令,在读取请求头的过程当中nginx会根据host及端口找到对应的虚拟主机配置。
3)NGX_HTTP_FIND_CONFIG_PHASE:
根据URI寻找匹配的location块配置项阶段,该阶段使用重写以后的uri来查找对应的location,值得注意的是该阶段可能会被执行屡次,由于也可能有location级别的重写指令。
4)NGX_HTTP_REWRITE_PHASE:
上一阶段找到location块后再修改URI,location级别的uri重写阶段,该阶段执行location基本的重写指令,也可能会被执行屡次。
5)NGX_HTTP_POST_REWRITE_PHASE:
防止重写URL后致使的死循环,location级别重写的后一阶段,用来检查上阶段是否有uri重写,并根据结果跳转到合适的阶段。
6)NGX_HTTP_PREACCESS_PHASE:
下一阶段以前的准备,访问权限控制的前一阶段,该阶段在权限控制阶段以前,通常也用于访问控制,好比限制访问频率,连接数等。
7)NGX_HTTP_ACCESS_PHASE:
让HTTP模块判断是否容许这个请求进入Nginx服务器,访问权限控制阶段,好比基于ip黑白名单的权限控制,基于用户名密码的权限控制等。
8)NGX_HTTP_POST_ACCESS_PHASE:
访问权限控制的后一阶段,该阶段根据权限控制阶段的执行结果进行相应处理,向用户发送拒绝服务的错误码,用来响应上一阶段的拒绝。
9)NGX_HTTP_TRY_FILES_PHASE:
为访问静态文件资源而设置,try_files指令的处理阶段,若是没有配置try_files指令,则该阶段被跳过。
10)NGX_HTTP_CONTENT_PHASE:
处理HTTP请求内容的阶段,大部分HTTP模块介入这个阶段,内容生成阶段,该阶段产生响应,并发送到客户端。
11)NGX_HTTP_LOG_PHASE:
处理完请求后的日志记录阶段,该阶段记录访问日志。
以上11个阶段中,HTTP没法介入的阶段有4个:
3)NGX_HTTP_FIND_CONFIG_PHASE
5)NGX_HTTP_POST_REWRITE_PHASE
8)NGX_HTTP_POST_ACCESS_PHASE
9)NGX_HTTP_TRY_FILES_PHASE
剩余的7个阶段,HTTP模块均能介入,每一个阶段可介入模块的个数也是没有限制的,多个HTTP模块可同时介入同一阶段并做用于同一请求。
图:Nginx 模块执行顺序与阶段
Refer:
Nginx请求处理流程你了解吗?
https://mp.weixin.qq.com/s/otQIhuLABU3omOLtRfJnZQ
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用例说明
(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.3四、zlib-1.2.八、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 会报:
cd /usr/local/pcre \ && if [ -f Makefile ]; then make distclean; fi \ && CC="gcc" CFLAGS="-O2 -fomit-frame-pointer -pipe " \ ./configure --disable-shared /bin/sh: ./configure: No such file or directory make[1]: *** [/usr/local/pcre/Makefile] Error 127 make[1]: Leaving directory `/software/nginx-0.8.53' 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 一块儿编译便可,不须要单独编译。
user work work; worker_processes 7; error_log /opt/data1/logs/nginx/error.log; pid /var/run/nginx.pid; worker_rlimit_nofile 800000; events { use epoll; worker_connections 65535; } http { server { listen 80; set $idTest "idTest_11111111111" ; log_format tracklog '$idTest $msec $remote_addr - $remote_user [$time_local] $request ' '"$status" resp_body:"$resp_body" --"$ref1"-- ' '"$http_user_agent"'; location ~ /gzip/(.*) { default_type "text/html"; set $resp_body ""; content_by_lua ' --zlib 解码 post gzip 数据 local zlib = require "zlib" local encoding = ngx.req.get_headers()["Content-Encoding"] if encoding == "gzip" then ngx.req.read_body() local body = ngx.req.get_body_data() ngx.say("++++++++++++++++++++++++++++body data:") ngx.print(body) if body then --ngx.var.resp_body = "55555555555555" local stream = zlib.inflate() ngx.var.resp_body = stream(body) end end '; access_log on; access_log /opt/data1/logs/nginx/pc/track/ooxx.com.access.log tracklog; } location ~ /post/(.*) { default_type "text/html"; lua_need_request_body on; set $resp_body ""; content_by_lua ' ngx.var.resp_body = ngx.var.request_body '; access_log on; access_log /opt/data1/logs/nginx/pc/track/ooxx.com.access.log tracklog; } location ~ /lua/(.*) { default_type "text/html"; set $ref1 "Hello,Nginx & Lua !"; #设置nginx变量 set $a $1; set $b $host; content_by_lua ' --nginx变量 local var = ngx.var ngx.say("ngx.var.a : ", var.a, "<br/>") ngx.say("ngx.var.b : ", var.b, "<br/>") ngx.say("ngx.var[2] : ", var[2], "<br/>") ngx.var.b = 2; ngx.say("<br/>") --请求头 ngx.say(ngx.var.httpRef, "<br/>") local headers = ngx.req.get_headers() for k,v in pairs(headers) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ","), "<br/>") else ngx.say(k, " : ", v, "<br/>") end end ngx.say("------------headers end-----------", "<br/><br/><br/>") --get请求uri参数 ngx.say("uri args begin", "<br/>") local uri_args = ngx.req.get_uri_args() for k, v in pairs(uri_args) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ", "), "<br/>") else ngx.say(k, ": ", v, "<br/>") end end ngx.say("uri args end", "<br/>") ngx.say("a: ",ngx.var.arg_a, "<br/>") ngx.say("b: ",ngx.var.arg_b, "<br/>") --未经解码的请求 uri local request_uri = headers["Host"] .. "/" .. ngx.var.request_uri; ngx.say("request_uri : ", request_uri, "<br/>"); --解码后的 uri local decode_request_uri = headers["Host"] .. "/" .. ngx.unescape_uri(ngx.var.request_uri); ngx.var.ref1 = decode_request_uri; ngx.say("decode request_uri : ", decode_request_uri, "<br/>"); --MD5 ngx.say("ngx.md5 : ", ngx.md5("123"), "<br/>") --http time ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "<br/>") --ngx.var.http_referer = "*********************" '; log_format LogFormatv1 '$idTest@$msec@$remote_addr@-@$remote_user@[$time_local]@$request@' '"$status"@$body_bytes_sent@"$http_referer"@' '"$http_user_agent"'; access_log on; access_log /opt/data1/logs/nginx/PCv1/track/ooxx.com.access.log LogFormatv1; } } }
须要注意的是线上的 Nginx 可能面对的是高并发场景,对于本身的 Lua 代码最好作个压力测试,好比:
tcpcopy 或者 ab -c100 -n10000 'http://test.abc.com/lua/test%20haha/?a=3&b=4'
(1)openSSL 库不支持 64bit Cygwin
cryptlib.c:1:0: 错误:您选择的 CPU 不支持 x86-64 指令集 /* crypto/cryptlib.c */ ^ cryptlib.c:1:0: 错误:您选择的 CPU 不支持 x86-64 指令集 <builtin>: recipe for target 'cryptlib.o' failed make[3]: *** [cryptlib.o] Error 1 make[3]: Leaving directory '/home/Jun/softs/openssl-1.0.1r/crypto' 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 便可。
events { use epoll; worker_connections 65535; }
好比我这里的编译配置参数是(注意有些目录可能须要提早本身建立):
./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 稍加修改以下(注意有些目录可能须要提早本身建立):
worker_processes 2; #error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 20; } http { server { listen 80; set $idTest "idTest_11111111111" ; log_format tracklog '$idTest $msec $remote_addr - $remote_user [$time_local] $request ' '"$status" $body_bytes_sent --"$ref1"-- ' '"$http_user_agent"'; log_format LogFormatv1 '$idTest@$msec@$remote_addr@-@$remote_user@[$time_local]@$request@' '"$status"@$body_bytes_sent@"$http_referer"@' '"$http_user_agent"'; access_log on; location ~ /lua/(.*) { default_type "text/html"; set $ref1 "Hello,Nginx & Lua !"; #设置nginx变量 set $a $1; set $b $host; content_by_lua ' --nginx变量 local var = ngx.var ngx.say("ngx.var.a : ", var.a, "<br/>") ngx.say("ngx.var.b : ", var.b, "<br/>") ngx.say("ngx.var[2] : ", var[2], "<br/>") ngx.var.b = 2; ngx.say("<br/>") --请求头 ngx.say(ngx.var.httpRef, "<br/>") local headers = ngx.req.get_headers() for k,v in pairs(headers) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ","), "<br/>") else ngx.say(k, " : ", v, "<br/>") end end ngx.say("------------headers end-----------", "<br/><br/><br/>") --get请求uri参数 ngx.say("uri args begin", "<br/>") local uri_args = ngx.req.get_uri_args() for k, v in pairs(uri_args) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ", "), "<br/>") else ngx.say(k, ": ", v, "<br/>") end end ngx.say("uri args end", "<br/>") ngx.say("a: ",ngx.var.arg_a, "<br/>") ngx.say("b: ",ngx.var.arg_b, "<br/>") --未经解码的请求 uri local request_uri = headers["Host"] .. "/" .. ngx.var.request_uri; ngx.say("request_uri : ", request_uri, "<br/>"); --解码后的 uri local decode_request_uri = headers["Host"] .. "/" .. ngx.unescape_uri(ngx.var.request_uri); ngx.var.ref1 = decode_request_uri; ngx.say("decode request_uri : ", decode_request_uri, "<br/>"); --MD5 ngx.say("ngx.md5 : ", ngx.md5("123"), "<br/>") --http time ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "<br/>") --ngx.var.http_referer = "*********************" '; access_log /var/log/nginx/ooxx.com.access.log tracklog; } } }
最后 nginx -s reload 效果以下,http://localhost/lua/?a=1&b=2 请求也正常,和 linux 下结果一致:
(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。
例如:
location = / { # 只匹配"/". [ configuration A ] } location / { # 匹配任何请求,由于全部请求都是以"/"开始 # 可是更长字符匹配或者正则表达式匹配会优先匹配 [ configuration B ] } location ^~ /images/ { # 匹配任何以 /images/ 开始的请求,并中止匹配 其它location [ configuration C ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配以 gif, jpg, or jpeg结尾的请求. # 可是全部 /images/ 目录的请求将由 [Configuration C]处理. [ configuration D ] }
请求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 优先级官方文档
=前缀的指令严格匹配这个查询。若是找到,中止搜索。
全部剩下的常规字符串,最长的匹配。若是这个匹配使用^〜前缀,搜索中止。
正则表达式,在配置文件中定义的顺序。
若是第3条规则产生匹配的话,结果被使用。不然,如同从第2条规则被使用。
(3)正则语法
~ 为区分大小写的匹配。
~* 不区分大小写的匹配(匹配firefox的正则同时匹配FireFox)。
!~ 不匹配的
!~* 不匹配的
. 匹配除换行符之外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也能够写成(?'name'exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读
[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://blog.csdn.net/gzh0222/article/details/7845981
[9] 平台服务部署及Web框架
http://weibo.com/p/1001643875679132642345
[10] 我所熟悉的网站负载均衡技术
[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 重写规则指南
[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的现状、趋势、使用及学习方法
[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请求