作者:李林成
推荐理由:该篇文档把openresty请求分发讲解的比较通俗易懂,而且有demo输出,其这篇文章的请求分发有着很高的应用价值。
为什么要用openrest,而没有选择nginx
主要是openresty实现的了,方便操作lua业务处理
openresty是什么
是一个基于nginx与lua的高性能web平台,其内部集成了大量精良的lua库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态web应用、web服务和动态网关。它打包了标准的 Nginx核心,以及很多的常用的第三方模块,以及它们的大多数依赖项。
比如:MySQL、PostgreSQL、Memcached 以及 Redis访问模块。它的主要语言是lua。
openresty特点
开发人员可以使用Lua脚本调动 Nginx 支持的各种 C 以及 Lua 模块,
可以快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。
业务场景:
计量和供销原本都是通过dpp系统平台接口转发。如果出现集团网络网线断掉,或者出现网络波动和dpp服务器出现问题,都会导致所有厂区手持机和供销系统不能用。
因为考虑到app不能直接调两个系统接口。计量系统如果转换供销系统也是很不合理的,原本计量业务就已经很重,如果在转发供销接口。后期维护和扩展就会很困难,而且计量系统本身不适合做接口转换。
所以我们最终讨论在计量系统搭建openresty应用。那么50多家厂区不可能同时在维护每一台openresty应用。所以我们就通过接口转发的时候,把计量ip和供销ip做为参数,通过lua脚本解析参数拿到计量ip和供销ip来指定服务。并进行转发
在openresty解析所遇到的问题:
在请求post请求的时候出现了一直获取不到参数。
Lua接受post请求body过大导致get_post_args()无法获取到参数!
Lua实际问题则是request body大于client_body_buffer_size默认值,导致ngx.req.get.post.args()无法获取到参数。
原因:当post请求bodt size大于client_body_buffer_size默认值8k或者16时,请求报文参数将会被nginx缓存到硬盘当中,此时ngx.req.get_post_args()是无法获取到参数,此时可以通过ngx.req.get_body_data() 或者ngx.req.get_body_file()中获取。获取后的参数是通过unicode编码过的,我们如果要取得原始的值,还需要进行unicode解码。
而且ngx.req.get_post_args()只能在rewrite_by_lua, access_by_lua, content_by_lua*阶段使用,且在使用前需要先调用ngx.req.read_body(),或打开lua_need_request_body 选项强制本模块读取请求体(此方法不推荐)
在openresty使用到了
正则表达式
1.~ 为区分大小写、~* 为不区分大小写匹配、!和!*分别为区分大小写不匹配及不区分大小写不匹配、()匹配包含多个路径、||并且匹配相应的路径入口
2.Set 指令:该指令用于定义一个变量。并给变量赋值这个定义的变量是联合的
3.在使用rewritr_by_lua方法的还是要注意if在rewritr_by_lua之前执行。
4.在set_by_lua模块中read_body是被禁止调用的(failed to run set_by_lua: set_by_lua:6: API disabled in the context of set_by_lua stack traceback: [C]: in function ‘read_body’ set_by_lua:6: in function <set_by_lua:1>)
5.所以我使用rewrite_by_lua,通过rewrite_by_lua把lua文件直接嵌入到nginx.conf文件中
OpenResty:请求处理¥¥接口服务
location ~ /(app-business|smp|saleApp/smp)/ {
set $userinfo '';
rewrite_by_lua '
local request_method = ngx.var.request_method
local cjson = require "cjson";
if request_method == "GET" then
local arg = ngx.req.get_uri_args()
ngx.var.userinfo = arg["supplyIp"]
elseif request_method == "POST" then
ngx.req.read_body()
local arg = ngx.req.get_body_data()
ngx.var.userinfo =cjson.decode(arg)["supplyIp"]
end;
if ngx.var.userinfo == nil then
ngx.var.userinfo = arg["jlIp"]
end;
if string.sub(ngx.var.userinfo,1,5) ~= "http:" then
ngx.var.userinfo="http://"..ngx.var.userinfo
end;
';
proxy_pass $userinfo/smp/$request_uri;
}