OpenResty® 入门学习记录
OpenResty® 入门学习使用
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty 安装
运行环境:CentOS 7.2
wget https://openresty.org/download/openresty-1.13.6.2.tar.gz
tar -xzvf openresty-1.13.6.2.tar.gz
./configure # 默认, --prefix=/usr/local/openresty 程序会被安装到/usr/local/openresty目录。
make
make install
与安装Nginx 一样需要确定已经安装了依赖:pcre、zlib、openssl ,可查看《Nginx 模块开发简单了解》
OpenResty 的Hello World
创建测试目录
mkdir ~/work
cd ~/work
mkdir logs/ conf/
创建配置文件
conf/nginx.conf
其中包含以下内容:
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
location / {
default_type text/html;
content_by_lua '
ngx.say("<p>Hello, World</p>")
';
}
}
}
启动Nginx 服务器
# 添加配置文件到nginx # 就已经直接启动nginx
/sbin/nginx -c /usr/local/openresty/work/conf/nginx.conf
测试访问
使用curl 访问本地的Web服务
curl http://localhost:8080/
# 返回信息:<p>Hello, World</p>
# 发现启动之后 -s stop 关不掉 ,只好使用ps -ef | grep nginx ,kill -9 nginx ε=(´ο`*)))唉
到这里,Hello World 完成了 ヾ(@▽@)ノ
OpenResty 常用API
获取请求参数1
ngx.say() : 直接返回请求结果
ngx.var.arg_key : 获取请求中key参数的vaule
location / {
default_type text/html;
content_by_lua '
ngx.say(ngx.var.arg_b) # 这里参数arg_参数key
';
}
# 访问:http://192.168.1.251:8080/lua_var?a=323&b=333333
# 返回:333333
获取请求参数2
- ngx.req.get_uri_args 获取在uri上的get类型参数,返回的是一个table类型的数据结构。
- ngx.req.read_body 读取body,这在解析body之前,一定要先读取body。
- ngx.req.get_post_args 获取form表单类型的参数,返回结果是一个table类型的数据。
local arg = ngx.req.get_uri_args()
for k,v in pairs(arg) do
ngx.say("[GET ] key:", k, " v:", v)
end
ngx.req.read_body() -- 解析 body 参数之前一定要先读取 body
local arg = ngx.req.get_post_args()
for k,v in pairs(arg) do
ngx.say("[POST] key:", k, " v:", v)
end
-- 访问:http://192.168.1.251:8080/lua_var?b=323&c=333333
-- 返回:[GET ] key:b v:323 [GET ] key:c v:333333
可以直接在
content_by_lua '....代码.....';
也可以新建一个单独的文件
test.lua
,使用content_by_lua_file /usr/example/lua/lua_request.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
返回结果:
Host : 192.168.1.251:8080
user-agent : Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
user-agent : Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
host : 192.168.1.251:8080
accept-language : zh-CN,zh;q=0.9
accept-encoding : gzip, deflate
user-agent : Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36
connection : keep-alive
accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
cache-control : max-age=0
upgrade-insecure-requests : 1
获取http其他信息的方法
- ngx.req.http_version() 获取http版本
- ngx.req.get_method() 获取请求方法(GET、POST等)
- ngx.req.raw_header() 原始的请求头内容
- ngx.req.get_body_data() 请求的body内容体
测试结果:ngx.req.http_version : 1.1
ngx.req.get_method : GET
ngx.req.raw_header : GET /lua_var?b=323&c=333333 HTTP/1.1 Host: 192.168.1.251:8080 Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9
ngx.req.get_body_data() : nil
输出响应
ngx.header.a="1" --ngx.header 向响应头输出内容
ngx.header.b={"a","b"}
ngx.say("hello","</br>") --ngx.say 输出响应体
ngx.print("sss") --ngx.print输出响应体
return ngx.exit(200) --ngx.exit 指定http状态码退出
日志输出
ngx.log(ngx.ERR, "log",log) --参数:日志级别,key,vaule
重定向
ngx.redirect("http://www.baidu.com", 302)
共享内存
在http模块加上以下:
lua_shared_dict shared_data 1m;
local shared_data = ngx.shared.shared_data
local i = shared_data:get("i")
if not i then
i = 1
shared_data:set("i",i)
end
i = shared_data:incr("i",1)
ngx.say("i:",i)
多次访问,浏览器打印:
i:1
i:2
i:3
i:4
i:5
执行结束返回
用法: ngx.exit(status)
执行上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer., balancer_by_lua, ssl_certificate_by_lua*
ngx.exit()
的使用相对简单些:
- 当传入的status >= 200(200即为ngx.HTTP_OK),
ngx.exit()
会中断当前请求,并将传入的状态码(status)返回给nginx。 - 当传入的status == 0(0即为ngx.OK)则
ngx.exit()
会中断当前执行的phrase(ngx-lua模块处理请求的阶段,如content_by_lua*),进而继续执行下面的phrase。 - 对于
ngx.exit()
需要进一步注意的是参数status的使用,status可以传入ngx-lua所定义的所有的HTTP状态码常量(如:ngx.HTTP_OK、ngx.HTTP_GONE、ngx.HTTP_INTERNAL_SERVER_ERROR等)和两个ngx-lua模块内核常量(只支持NGX_OK和NGX_ERROR这两个,如果传入其他的如ngx.AGAIN等则进程hang住)。 - 文档中推荐的
ngx.exit()
最佳实践是同return
语句组合使用,目的在于增强请求被终止的语义(return ngx.exit(...)
)。
关于Lua以及ab压力测试
Lua 注意的事项
下标从 1 开始,这个是和其他编程语言很大的不同。
不区分 array 和 dict ,会导致处理 json 的时候,无法区分 array 和 object。
默认全局变量,需要在所有变量前加 local,忘记的话,可能导致各种难查的 bug。
自带的字符串正则匹配规则和通常的 PCRE 不同,使用的话,学习成本较高。
Lua 标准库和周边库,都是阻塞的,需要自己甄别哪些可以和 OpenResty 搭配使用。新手很容易使用了阻塞的库,而导致性能急剧下降。
ab压力测试
所以,由于线上的 Nginx 可能面对的是高并发场景,对于自己的 Lua 代码最好做个压力测试 ,例子:
# ab的全称是Apache Bench,是Apache自带的网络压力测试工具
yum -y install httpd-tools
# -n 执行的请求数量
# -c 并发请求个数
ab -n 1000 -c 100 http://www.baidu.com/
深入学习方向
Openresty的基础就是以上这些了,其他的就是LUA语言的东东了。
深入学习的话,Openresty官网有许多开源的组件:连接Mysql的LuaRestyMySQLLibrary 、连接Redis的LuaRestyRedisLibrary 等等,有好多好多。有使用需求的时候去研究一下就可以了,这些的文档都写的非常的全了。
参考资料
博客:https://blog.csdn.net/forezp/article/details/78616856
小杭 (^U^)ノ~YO
本文来自博客园,作者:小-杭,转载请注明原文链接:https://www.cnblogs.com/xiaohangblog/articles/16296516.html
欢迎转载小杭的博客,记得关注点赞收藏哦 (#^.^#)