记住一点:nginx配置文件不少坑来源自你的空格少了或多了。html
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建可以处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。nginx
OpenResty® 经过汇聚各类设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可使用 Lua 脚本语言调动 Nginx 支持的各类 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发链接的高性能 Web 应用系统。git
OpenResty® 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不单单对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。github
若是你的系统是 Centos 或 RedHat 可使用如下命令:web
yum install readline-devel pcre-devel openssl-devel
接下咱们能够在官方(https://openresty.org/cn/)下载最新的 OpenResty 源码包并解压编译安装:shell
wget https://openresty.org/download/ngx_openresty-1.9.7.1.tar.gz # 下载 tar xzvf ngx_openresty-1.9.7.1.tar.gz # 解压 cd ngx_openresty-1.9.7.1/ ./configure make make install
默认状况下程序会被安装到 /usr/local/openresty 目录,你可使用 ./configure --help 查看更多的配置选项。后端
安装成功后,咱们就可使用 openresty 直接输出 html 页面。centos
首先咱们能够建立一个工做目录:api
mkdir /home/www cd /home/www/ mkdir logs/ conf/
其中 logs 目录用于存放日志,conf 用于存放配置文件。cookie
接着,咱们在 conf 目录下建立一个 nginx.conf 文件 代码以下:
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { server { listen 9000; location / { default_type text/html; content_by_lua ' ngx.say("<p>Hello, World!</p>") '; } } }
若是你熟悉 nginx 的配置,应该对以上代码就很熟悉。这里咱们将 html 代码直接写在了配置文件中。
默认状况下 openresty 安装在 /usr/local/openresty 目录中,启动命令为:
/usr/local/openresty/nginx/sbin/nginx -p /home/www/ -c conf/nginx.conf
若是没有任何输出,说明启动成功,-p 指定咱们的项目目录,-c 指定配置文件。
接下来咱们可使用 curl 来测试是否可以正常范围:
curl http://localhost:9000/
输出结果为:
<p>Hello, World!</p>
在 HelloWorld 实例中,咱们直接在 nginx.conf 中写Lua脚本,不少时候,Lua脚本是一个文件。下面演示使用 content_by_lua_file 指令调用Lua脚本文件。
在conf文件夹下建立helloworld.lua:
ngx.say("<p>Hello, World!</p>")
修改你的 nginx.conf 文件内容为:
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { server { listen 9000; location / { default_type text/html; content_by_lua_file 'conf/helloworld.lua'; } } }
中止已启动的nginx进程:
killall -9 nginx
启动nginx进程:
/usr/local/openresty/nginx/sbin/nginx -p /home/www/ -c conf/nginx.conf
接下来咱们可使用 curl 来测试是否可以正常范围:
curl 'localhost:9000'
输出结果为:
<p>Hello, World!</p>
使用 set_by_lua 指定能够用相似调用函数的形式去调用Lua脚本。语法:
set_by_lua $res <lua-script-str> [$arg1 $arg2 ...]
修改你的conf/nginx.conf文件:
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { server { listen 9000; location / { default_type text/html; set_by_lua $res ' local a = tonumber(ngx.arg[1]) local b = tonumber(ngx.arg[2]) return a+b' $arg_a $arg_b; echo $res; } } }
中止已启动的nginx进程,命令:
killall -9 nginx
启动nginx进程:
/usr/local/openresty/nginx/sbin/nginx -p /home/www/ -c conf/nginx.conf
接下来咱们可使用 curl 来测试是否可以正常范围:
curl 'localhost:9000/?a=2&b=5'
输出结果为:
7
set_by_lua_file能够调用本地Lua脚本文件。语法与set_by_lua相同:
set_by_lua_file $res <lua-script-str> [$arg1 $arg2 ...]
在conf文件夹下建立hello.lua文件:
local a = tonumber(ngx.arg[1]) local b = tonumber(ngx.arg[2]) return a+b
在conf文件夹下建立nginx_lua.conf文件:
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { server { listen 9000; location = / { default_type text/html; set_by_lua_file $res "conf/hello.lua" $arg_a $arg_b; echo $res; } } }
启动nginx进程:
/usr/local/openresty/nginx/sbin/nginx -p /home/www/ -c conf/nginx_lua.conf
接下来咱们可使用 curl 来测试是否可以正常范围:
curl 'localhost:9000/?a=2&b=5'
输出结果为:
7
在conf文件夹下建立nginx.conf文件:
worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { server { listen 9000; location / { set $a $host; set $b 'hello world'; default_type text/html; content_by_lua_file 'conf/hello.lua'; } } }
在conf文件夹下建立hello.lua:
local var = ngx.var ngx.say("ngx.var.a : ", var.a, "<br/>") ngx.say("ngx.var.b : ", var.b, "<br/>") ngx.say("<br/>")
启动nginx进程:
/usr/local/openresty/nginx/sbin/nginx -p /home/www/ -c conf/nginx_lua.conf
接下来咱们可使用 curl 来测试是否可以正常范围:
curl 'localhost:9000'
输出结果为:
ngx.var.a : localhost<br/> ngx.var.b : hello world<br/>
如今已经学会了content_by_lua 与 set_by_lua 指令,其它相似的指令还有不少,那么这些指令都是有什么区别呢?主要区别是指令的运行周期不一样,如图所示。(图片来源于网络)
指令 | 所到处理阶段 | 使用范围 | 解释 |
---|---|---|---|
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阶段处理,好比记录访问量/统计平均响应时间 |
将下面的lua脚本复制到你的content_by_lua_file指定的lua文件中便可。
--请求头 local headers = ngx.req.get_headers() ngx.say("headers begin", "<br/>") ngx.say("Host : ", headers["Host"], "<br/>") ngx.say("user-agent : ", headers["user-agent"], "<br/>") ngx.say("user-agent : ", headers.user_agent, "<br/>") 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/>") ngx.say("<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("<br/>") --post请求参数 ngx.req.read_body() ngx.say("post args begin", "<br/>") local post_args = ngx.req.get_post_args() for k, v in pairs(post_args) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ", "), "<br/>") else ngx.say(k, ": ", v, "<br/>") end end ngx.say("post args end", "<br/>") ngx.say("<br/>") --请求的http协议版本 ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "<br/>") --请求方法 ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "<br/>") --原始的请求头内容 ngx.say("ngx.req.raw_header : ", ngx.req.raw_header(), "<br/>") --请求的body内容体 ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "<br/>") ngx.say("<br/>") local request_uri = ngx.var.request_uri; ngx.say("request_uri : ", request_uri, "<br/>"); --解码 ngx.say("decode request_uri : ", ngx.unescape_uri(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.update_time() local now = ngx.now() ngx.say("nowTime : ", now, "<br/>")
访问 http://127.0.0.1:9000/?a=8&b=55 ,手动输入两个Cookie,输出结果:
headers begin Host : 127.0.0.1:9000 user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36 user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36 accept-language : zh-CN,zh;q=0.9 connection : keep-alive accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 cache-control : max-age=0 host : 127.0.0.1:9000 cookie : hello=world; Heelo=Sdd accept-encoding : gzip, deflate upgrade-insecure-requests : 1 user-agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36 headers end uri args begin b: 55 a: 8 uri args end post args begin post args end ngx.req.http_version : 1.1 ngx.req.get_method : GET ngx.req.raw_header : GET /?a=8&b=55 HTTP/1.1 Host: 127.0.0.1:9000 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: hello=world; Heelo=Sdd ngx.req.get_body_data() : nil request_uri : /?a=8&b=55 decode request_uri : /?a=8&b=55 ngx.md5 : 202cb962ac59075b964b07152d234b70 ngx.http_time : Mon, 29 Apr 2019 14:53:17 GMT
Lua如何调用系统shell呢?
--调用系统命令 local t = io.popen('cat /home/www/conf/hello.lua') local a = t:read("*all") t:close() ngx.say(a)
Lua发送Http请求,默认是不支持的,须要引入第三方库。也就是下方这个Github地址的两个文件:http.lua 和 http_headers.lua 。
Github:https://github.com/ledgetech/lua-resty-http/tree/master/lib/resty
流程和上方的Demo相似,不一样的是,须要在你的 lua 文件中写入一行代码:
local http = require "resty.http"
启动你的 nginx ,命令同上。使用 curl 命令测试访问,查看 logs 目录下的 error.log 文件:
2019/04/30 14:23:21 [error] 7093#0: *1 lua entry thread aborted: runtime error: /home/www/conf/helloworld.lua:95: module 'resty.http' not found: no field package.preload['resty.http'] no file '/usr/local/openresty/lualib/resty/http.lua' no file '/usr/local/openresty/lualib/resty/http/init.lua' no file './resty/http.lua' no file '/usr/local/openresty/luajit/share/luajit-2.1.0-beta1/resty/http.lua' no file '/usr/local/share/lua/5.1/resty/http.lua' no file '/usr/local/share/lua/5.1/resty/http/init.lua' no file '/usr/local/openresty/luajit/share/lua/5.1/resty/http.lua' no file '/usr/local/openresty/luajit/share/lua/5.1/resty/http/init.lua' no file '/usr/local/openresty/lualib/resty/http.so' no file './resty/http.so' no file '/usr/local/lib/lua/5.1/resty/http.so' no file '/usr/local/openresty/luajit/lib/lua/5.1/resty/http.so' no file '/usr/local/lib/lua/5.1/loadall.so' no file '/usr/local/openresty/lualib/resty.so' no file './resty.so' no file '/usr/local/lib/lua/5.1/resty.so' no file '/usr/local/openresty/luajit/lib/lua/5.1/resty.so' no file '/usr/local/lib/lua/5.1/loadall.so'
咱们只须要在错误日志的第一个目录下添加上面两个http模块的lua文件便可。目录:
/usr/local/openresty/lualib/resty/
接下来就是重启你的nginx,再次访问,发现不报错了。
local http = require "resty.http" local function http_post_client(url, timeout) local httpc = http.new() timeout = timeout or 30000 httpc:set_timeout(timeout) local res, err_ = httpc:request_uri(url, { method = "GET", headers = { ["Content-Type"] = "application/x-www-form-urlencoded", } }) httpc:set_keepalive(5000, 100) --httpc:close() return res, err_ end
local http = require "resty.http" local function http_post_client(url,body,timeout) local httpc = http.new() timeout = timeout or 30000 httpc:set_timeout(timeout) local res, err_ = httpc:request_uri(url, { method = "POST", body = body, headers = { ["Content-Type"] = "application/x-www-form-urlencoded", } }) httpc:set_keepalive(5000, 100) httpc:close() if not res then return nil, err_ else if res.status == 200 then return res.body, err_ else return nil, err_ end end end
--get local resp, err = http_post_client("http://127.0.0.1/index.html?name=test",3000) --post local body = {"name" = "test"} local resp, err = http_post_client("http://127.0.0.1/index.html?name=test",body,3000)
https://blog.csdn.net/qq_21860077/article/details/83623888
Nginx API for Lua:http://www.javashuo.com/article/p-sgvvczhq-dc.html