Openresty
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
高并发读缓存
场景
前端通过Restful请求数据,后台已将数据被缓存在redis中,通过Nginx直接从redis中读取数据返回,跳过AP服务器,从而达到分发流量的目的,减轻AP服务器的压力,提高响应速度。
例:
通过ID查询用户信息,Redis中以ID作为key,用户详细数据已json格式存储在value中,请求URL:http://192.168.17.200/users/001
nginx.conf中添加URI映射:
location ~/users/(.*) {
default_type text/html;
# 取得URI中的ID参数,并设置到全局变量
set $user_id $1;
content_by_lua_file lua_script/users.lua;
}
通过正则表达式的方式获取URI参数,Lua中通过ngx.var.user_id获取参数值。
users.lua:
local redis = require "resty.redis"
local ok, err, rtn, red
-- 获取Redis连接
local function connectRedis()
red = redis:new()
ok, err = red:connect("192.168.17.200", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return false
end
return true
end
-- Redis密码认证
local function redisAuth()
local count
-- 连接首次使用时进行认证
count, err = red:get_reused_times()
ngx.say("连接复用次数: ", count, "<br>")
if 0 == count then
ok, err = red:auth("goodluck")
if not ok then
ngx.say("<br>failed to auth: ", err)
return false
end
elseif err then
ngx.say("<br>failed to get reused times: ", err)
return false
end
return true
end
-- 根据参数获取缓存数据
local function getUser()
-- 获取URI参数
local users_cache_key = "users"
local val, err = red:hget(users_cache_key, ngx.var.user_id)
if not val then
ngx.say("<br>failed to get user: ", err)
return
end
if val == ngx.null then
-- TODO 如果缓存中没有命中数据,应该继续向AP服务器发起请求,这里处理未完成
ngx.say("<br>user not in redis")
return
end
ngx.say(val)
end
-- 将连接放入线程池管理
local function putIntoPool()
-- put it into the connection pool of size 100,
-- with 10 seconds max idle time
local ok, err = red:set_keepalive(10000, 100)
if not ok then
ngx.say("<br>failed to set keepalive: ", err)
return
end
end
if connectRedis() then
if redisAuth() then
getUser()
end
putIntoPool()
end
关于set $user_id $1; 变量的并发访问安全性:
- Nginx变量值容器的生命期是与当前正在处理的请求绑定的,而与location无关
- Nginx变量名的可见范围虽然是整个配置,但每个请求都有所有变量的独立副本,或者说都有各变量用来存放值的容器的独立副本,彼此互不干扰
测试
可以看到数据以json字符串的格式返回给客户端,非常适合通过ajax进行异步加载数据。
Redis配置
如果Redis同Nginx不在同一台主机上,Redis需要设置以下三个配置参数:
- bind:设置Redis主机绑定的IP地址;
- requirepass:设置访问认证密码;
- protected-mode:no,关闭保护模式,默认为开启状态;