为了应对网站的高并发,可以采用的高性能服务器方案。 Nginx c module:性能很高,但是开发成本太高,适用于超大并发(亿级别) LuaJIT OpenResty : Nginx + LuaJIT
ngx_lua 工作原理:
简单的说是讲lua代码嵌入到nginx的配置文件中 通过lua_code_cache on | off 可以开启和关闭代码缓存 开启后性能更高,所以生产环境一般选择开启 测试调试的时候 可以关闭 更方便的测试,开发阶段可以考虑关闭 ngx lua API 尽量调用ngx的api而不要调用lua自己的api,ngx的api是非阻塞的 lua自己的api是阻塞的 eg1:
local json = require "cjson"
ngx.req.read_body()
local args = ngx.req.get_post_args()
if not args or not args.info then
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
local clint_ip = ngx.var.remote_addr
local user_agent = ngx.req.get_headers()['user_agent'] or ''
local info = ngx.decode_base64(args.info)
local response = {}
response.info = info
response.ip = clint_ip
response.user_agent = user_agent
ngx.say(json.encode(response))
连接数据库:
简单的demo:看上去不是异步的 其实是完全的异步非阻塞
local mysql = require "OpenResty.mysql"
local db, err = mysql:new()
if not db then
ngx.say("failed to instantate mysql:", err)
return
end
db:set_timeout(1000) -- 1 sec
local ok, err, errno, sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "ngx_test",
user = "ngx_test",
password = "ngx_test",
max_packet_size = 1024 * 1024
}
if not ok then
ngx.say("failed to connect:", err, ": ", errno, " ", sqlstate)
return
end
ngx.say("connected to mysql.")
res, err, errno, sqlstate =
db:query("create table cats "
.. "(id serial primary key, "
.. "name varchar(5))" )
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
ngx.say("table cats created.")
res, err, errno, sqlstate =
db:query("insert into cats (name) "
.. "values (\'Bob\'),(\'\'),(null)")
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
OpenResty缓存:
shared_dict
在nginx.conf里增加
lua_shared_dict my_cache 128m; # my_cache名字 128m内存空间
demo:
function get_from_cache( key )
local my_cache = ngx.shared.my_cache
local value = my_cache:get(key)
return value
end
预设了内存的大小 共享的内存 多个worker使用同一个shared_dict 同一份数据共享使用 有get set delete add replace incr get_keys get_stale操作 弊端:锁竞争
lua-resty-lrucache:
预设了key的个数,每个worker单独占用,没有锁竞争,但是内存占用大。 lrucache 只有get set delete三个操作 demo:
local lrucache = require "resty.lrucache"
local c = lrucache.new(200)
if not c then
return error("failed to create the cache: " .. (err or "unkonwn"))
end
c:set("dog", 32)
ngx.say("dog: ", c:get("dog"))
缓存失效风暴:
使用lua-resty-lock库解决(对sql加锁)(已经完成wait for lock)
FFI:
为了提高性能 用来调用C函数和使用C的数据结构 demo:
local ffi = require("ffi")
ffi.cdef[[
int.printf(const char *fmt, ...);
]]
ffi.C.printf("Hello %s!", "world\n")
第三方模块:
下好第三方模块,放在resty目录下 require引用 子查询: demo:
location /lua {
content_by_lua '
local res = ngx.location.capture
("/some_other_location")
if res.status == 200 then
ngx.print(res.body)
end';
}
C级别的调用 性能高 capture_multi 并发的发起子查询:
res1, res2, res3 = ngx.location.capture_multi{
{"/foo", {args = "a=3&b=4"}},
{"/bar"},
{"/bar",{ method = ngx.HTTP_POST,body = "hello"}},
}
执行阶段:
在不同的阶段处理不同的行为 [Nginx和lua执行顺序]