1、openresty与nginx区别
a、扩展性
nginx主要通过预编译的模块来扩展功能,虽然其模块化架构设计良好,但对于定制化
需求需要重新编译服务器。相比之下,OpenResty通过嵌入Lua脚本可以动态扩展功能,无
需重新编译服务器,开发者可以灵活地调整和添加功能
b、性能与资源使用
nginx在处理静态内容和反向代理方面表现出色,资源消耗低,适合高并发的静态内容
服务。OpenResty在高并发处理能力上继承了Nginx的优势,同时LuaJIT提供了高效的脚本
执行能力,适合动态内容处理和复杂逻辑的实现
c、开发灵活性
nginx的配置文件采用纯文本格式,功能定义相对简单,适合标准化和固定需求的场景
。OpenResty通过Lua脚本可以实现复杂的业务逻辑,适合需要灵活处理和快速迭代的开发
场景
d、应用场景
nginx适合处理静态内容和反向代理,而OpenResty适合高性能Web应用、实时数据处
理和分析、动态内容生成、API网关和微服务架构等场景
2、劣势
a、社区与生态
nginx有着庞大的用户群体和活跃的社区,提供丰富的文档和教程。虽然OpenResty的
用户群体较小,但在开发者社区中备受推崇,尤其是在需要高度定制化的场景中
3、白名单配置
a、安装rsa依赖
wget https://github.com/spacewander/lua-resty-rsa/archive/refs/tags/v1.1.0.tar.gz
tar -zxf lua-resty-rsa-1.1.0.tar.gz
cd lua-resty-rsa-1.1.0/lib/resty
cp rsa.lua /usr/local/openresty/lualib/resty/
b、修改nginx配置(以thinkphp6.0框架为例)
外网访问的配置文件为例
upstream api {
server 192.168.0.191:8888;
}
server {
listen 80;
server_name www.testrsaredislua.com;
error_log /data/nginx/www.testrsaredislua.com_error.log crit;
access_log /data/nginx/www.testrsaredislua.com_acess_$logdate.log access-upstream;
lua_code_cache off;
autoindex off;
server_tokens off;
error_page 401 /401.html;
location / {
proxy_set_header Host $host;
add_header 'Access-Control-Allow-Credentials' 'true';
add_header Access-Control-Allow-Origin "$http_origin";
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Access-Token';
if ($request_method ~* OPTIONS) {
return 200;
}
add_header Cache-Control no-cache;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
access_by_lua_file /data/wwwroot/rsa-redis.lua;
proxy_pass http://api;
}
location = /401.html {
root "/data/wwwroot/error";
}
}
外网转换到内网配置文件为例
server {
listen 8888;
root "/data/wwwroot/gpapi/public";
error_log /data/nginx/www.testrsaredislua.com8888_error.log crit;
access_log /data/nginx/www.testrsaredislua.com8888_acess_$logdate.log access-upstream;
error_page 403 /403.html;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=/$1 last;
}
index index.php;
autoindex off;
}
location = /403.html {
root "/data/wwwroot/error";
}
location = /404.html {
root "/data/wwwroot/error";
}
location = /50x.html {
root "/data/wwwroot/error";
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
c、在/data/wwwroot/目录下创建rsa-redis.lua文件
--引入Redis
local redis = require "resty.redis";
--引入rsa
local rsa = require "resty.rsa";
--Redis链接ip
local ip = "192.168.0.191"
--Redis链接端口
local port = 6379
--Redis连接密码
local pass = "123456"
--鉴权Redis(链接Redis)
local function connAuth()
local red = redis:new();
local connCount, err = red:connect(ip, port);
if not connCount then
ngx.say("failed to connect: ", err)
close_redis(red)
return
end
red:set_timeouts(2000);
local ok, err = red:auth(pass)
if not ok then
ngx.say("failed to auth: ", err)
close_redis(red)
return
end
return red
end
--关闭Redis
local function close_redis(red)
if not red then
return
end
--释放连接(连接池实现)
local pool_max_idle_time = 10000
local pool_size = 100
local ok, err = red:set_keepalive(pool_max_idle_time, pool_size)
if not ok then
ngx.say("set keepalive error : ", err)
end
end
--获取请求者IP
local function getIp()
local clientIP = ngx.req.get_headers()["X-Real-IP"]
if clientIP == nil then
clientIP = ngx.req.get_headers()["x_forwarded_for"]
end
if clientIP == nil then
clientIP = ngx.var.remote_addr
end
return clientIP
end
--获取用户访问IP
local clientIP = getIp();
--封禁token时间(秒)
local token_block_time= 120
--指定token访问频率计数最大值(次)
local token_max_count = 3
--如果数据为空的情况下
local function is_empty(value)
if type(value) == "table" then
return next(value) == nil
elseif type(value) == "string" then
return #value == 0
elseif type(value) == "nil" then
return true
end
return false
end
--过滤特殊字符串(只保留字母与数字,字母不区分大小写)
local function filter_special_chars(s)
local ss = {}
local k = 1
while true do
if k > #s then break end
local c = string.byte(s,k)
if not c then break end
if c<192 then
if (c>=48 and c<=57) or (c>= 65 and c<=90) or (c>=97 and c<=122) then
table.insert(ss, string.char(c))
end
k = k + 1
end
end
return table.concat(ss)
end
--如果头部信息没有指定的参数或是指定参数的值无法解析,加入IP黑名单
--如果同样的头部参数键在封禁token时间内连续访问指定token访问频率计数最大值次以上,加入IP黑名单
local function set_blacklist()
local header = ngx.req.get_headers();
local red = connAuth();
local token, err = header["x-token"];
--如果参数为空的情况下
if not token then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
else
--如果参数值为空的情况下
if is_empty(token) then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
end
--如果同一个token键在封禁token时间内连续访问指定token访问频率计数最大值次
local outputToken = filter_special_chars(token)
local redToken, err = red:get(outputToken);
if redToken ~= ngx.null then
if tonumber(redToken) >= tonumber(token_max_count) then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
else
--累加访问次数
red:incr(outputToken)
end
end
--添加访问次数
if redToken == ngx.null then
red:set(outputToken,1)
end
--设置过期时间
red:expire(outputToken,token_block_time)
--如果参数值采用base64解析不开的情况下
local encrypted, err = tostring(ngx.decode_base64(token))
if not encrypted then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
end
--采用rsa技术解析token base64过后的值内容
local priv_key = '-----BEGIN PRIVATE KEY-----\n' ..red:get('priv_key')..'\n-----END PRIVATE KEY-----';
local priv, err = rsa:new({private_key = priv_key})
local dst, err = rsa.decrypt(priv, encrypted)
if not dst then
local res, err = red:sismember('black-list', clientIP);
if res ~= 1 then
red:sadd('black-list', clientIP)
end
close_redis(red)
return ngx.exit(401)
end
end
end
--查看是否在黑名单里面
local function get_blacklist()
local red = connAuth();
local res, err = red:sismember('black-list', clientIP);
if res == 1 then
close_redis(red);
return ngx.exit(401);
end
close_redis(red);
end
get_blacklist();
set_blacklist();
4、总结
a、OpenResty与Nginx的主要区别
在于OpenResty通过嵌入Lua脚本提供了更高的灵活性和动态扩展性,适合需要复杂逻
辑和快速迭代的开发场景,而Nginx则以其稳定性和对静态内容的优化处理著称。
b、我们做登录系统时,往往无法隐藏用户登录token
采用rsa加密方式后,可以隐藏用户token。但是在现实中,往往不是nginx压力过大,而
是后端压力过大。我们采用openresty来过滤非法访问用户,这样就降低了后端压力。同样也
变相防止了爬虫。
c、openresty中lua可以连接redis或MySQL
只要业务架构设计合理的情况下,有些读的操作可以直接让openresty中lua直接解决,
无需走后端语言(java或是PHP等)。如果你能力可以的情况下,还可以直接让openresty调
用lua,lua再调用go插件或者程序。都知道go语言是处理并发最强大的语言(非C语言等,
只是说对java、php、pythen、node等来说)
d、重点说明
因本身是IT直男,在IT行业中是“一步一个脚印打出来的天下”,基本上常见的语言及中
间件都实践过,并且有自己的一套实战理论。之所以在此提醒的原因,对于我个人而言:
有耐心、有冲劲、有干劲、不怕吃苦、乐于实战研究且有一定的开发能力及设计能力。如果
达不到最基本的标准,请不要使用openresty,他的社区没有nginx的强大