一、openresty的安装
下载源码
安装依赖
apt-get install libpcre3-dev \
libssl-dev perl make build-essential curl
编译
tar -xzvf openresty-VERSION.tar.gz
# --without-http_redis2_module 将不能使用http_redis2模块
./configure --prefix=/usr/local/openresty \
--with-luajit \
--without-http_redis2_module \
--with-http_iconv_module \
--with-http_postgres_module
make
make install
启动
cd /usr/local/openresty/nginx/sbin
./nginx
![](https://img-blog.csdnimg.cn/img_convert/2dbc6c91ad6b1e2dd351081fedfff328.png)
二、应用
httpredis
httpredis只能读取redis
vim conf/nginx-httpredis.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.cpf.com;
root html;
index index.html;
location / {
default_type text/plain;
set $redis_key "m";
redis_pass 127.0.0.1:6379;
error_page 404 = @fetch;
}
location @fetch {
root html;
}
}
}
在html 目录下创建一个1.html文件,内容为:"i am 1.html"
在redis中无key "m"时:
![](https://img-blog.csdnimg.cn/img_convert/6e4c68dbbac49abc92ea1345580622b6.png)
在redis中有key "m"时:
![](https://img-blog.csdnimg.cn/img_convert/6b7497c076d603746d11767d6e6306ba.png)
httpredis2module
httpredis2module可以读写redis
vim conf/nginx-httpredis2module.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name www.cpf.com;
root html;
index index.html;
location /get {
set_unescape_uri $key 'n';
redis2_query get $key;
redis2_pass 127.0.0.1:6379;
}
location /set {
set_unescape_uri $key 'n';
redis2_query set $key 'nValue';
redis2_pass 127.0.0.1:6379;
}
}
}
![](https://img-blog.csdnimg.cn/img_convert/74ad04d608cdbf3feebfc467ed822871.png)
lua redis
设置获取redis中的key
vim conf/nginx-openresty-lua-redis.conf
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 8082;
server_name localhost;
location / {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/lua-openresty-redis.lua;
}
}
}
vim lua/lua-openresty-redis.lua
-- 引用resty的redis
local redis = require "resty.redis";
local red = redis:new();
-- 连接redis
local ok,err = red:connect("127.0.0.1",6379);
if not ok then
ngx.say("faild to connect",err);
return
end
ok,err = red:set("dKey","dValue");
if not ok then
ngx.say("failed to set dKey",err);
return
end
ok,err = red:get("dKey")
if not ok then
ngx.say("dKey is null")
else
ngx.say("dKey's value is :"..ok)
end
return
![](https://img-blog.csdnimg.cn/img_convert/de816d51b58332c81c9774c8364867ca.png)
![](https://img-blog.csdnimg.cn/img_convert/6a1828ba70829fb51458e39f16afcb91.png)
lua获取查询参数
vim conf/nginx-param.c
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 8081;
location / {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/lua-http-param.lua;
}
}
}
vim lua/lua-http-param.lua
-- 获取get请求的参数
local arg = ngx.req.get_uri_args();
for k,v in pairs(arg)
do
ngx.say("key:",k," value:",v);
end
./sbin/nginx -p ./ -c conf/nginx-param.conf
![](https://img-blog.csdnimg.cn/img_convert/4ccd3f86d40f51963c8a15693a129e36.png)
lua获取请求头参数
vim conf/nginx-param.conf
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 8081;
location / {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/lua-header-param.lua;
}
}
}
vim lua/lua-header-param.lua
local headers = ngx.req.get_headers();
for k,v in pairs(headers)
do
ngx.say("[header] key:",k," value:",v);
end
./sbin/nginx -p ./ -c conf/nginx-param.conf
![](https://img-blog.csdnimg.cn/img_convert/26cc1e8ca6e5175054ab9e8be33116a0.png)
lua获取请求表单
vim conf/nginx-param.conf
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 8081;
location / {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/lua-post-kv-param.lua;
}
}
}
vim lua/lua-post-kv-param.lua
-- 获取post body kv参数
-- 重要:读取body
ngx.req.read_body();
local postArgs = ngx.req.get_post_args();
for k,v in pairs(postArgs)
do
ngx.say("[post] key:",k," value:",v);
end
./sbin/nginx -p ./ -c conf/nginx-param.
![](https://img-blog.csdnimg.cn/img_convert/5213bb8e2fe795d4c4a416e3aec4fa25.png)
读取全部body
vim conf/nginx-param.conf
worker_processes 1;
error_log logs/error.log;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 8081;
location / {
default_type text/html;
content_by_lua_file /usr/local/openresty/nginx/lua/lua-post-body-param.lua;
}
}
}
vim lua-post-body-param.lua
-- 获取body体参数
-- 所有获取body的操作,这个很重要
ngx.req.read_body();
local body = ngx.req.get_body_data();
ngx.say(body);
./sbin/nginx -p ./ -c conf/nginx-param.
![](https://img-blog.csdnimg.cn/img_convert/df393097975f828a3b10a1f3d7238c67.png)
nginx+lua+redis 限流
![](https://img-blog.csdnimg.cn/img_convert/dbdac12ade29f439c8c4753d349b0332.png)
vim lua/ip-limit-access.lua
ngx.log(ngx.INFO,"ip limit access");
local redis = require "resty.redis";
local red = redis:new();
--链接redis
red:connect("127.0.0.1",6379);
-- 需要写链接成功的判断。
--判断是否限流
limit = red:get("limit");
if limit == '1' then
return ngx.exit(503);
end
inc = red:incr("testLimit");
if inc <= 2 then
red:expire("testLimit",1);
else
red:set("limit",1);
red:expire("limit",10);
end
vim conf/nginx-ip-limit.conf
worker_processes 1;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 8083;
location / {
default_type text/html;
access_by_lua_file /usr/local/openresty/nginx/lua/ip-limit-access.lua;
log_by_lua_file /usr/local/openresty/nginx/lua/ip-limit-log.lua;
proxy_pass http://localhost:8080/;
}
}
}
~
启动上游服务器go run main.go
package main
import (
"time"
"github.com/gin-gonic/gin"
)
func main() {
e := gin.New()
e.GET("/", func(ctx *gin.Context) {
ctx.String(200, time.Now().String())
})
e.Run()
}
启动nginx: ./sbin/nginx -p ./ -c conf/nginx-ip-limit.conf
![](https://img-blog.csdnimg.cn/img_convert/121bc77f7d19fc3ea6412598149b25e1.png)
nginx+lua +redis 防爬虫(ip黑名单)
爬虫种类:
善意的:baidu、google
恶意的:恶意窃取网站内容
防爬虫的方法:
限制user-agent: 非浏览器会带上这个头。如postman
限制ip
添加验证码
限制cookie
本次我们使用限制ip的方式:
在lua中有一个黑名单缓存,这个缓存定时去redis更新。nginx的访问ip在这个缓存中查询,如果查询到,则拒绝访问。
![](https://img-blog.csdnimg.cn/img_convert/34db662231fe8159fcf6403df957e5c4.png)
在redis中添加黑名单
![](https://img-blog.csdnimg.cn/img_convert/f6c81fae109f18a9896cb72a02839a00.png)
vim lua/black-list-access.lua
ngx.log(ngx.INFO,"black list");
-- 获取nginx中的ip_black_list
local ip_black_list = ngx.shared.ip_black_list;
local last_update_time=ip_black_list:get("last_update_time");
if last_update_time == nil or last_update_time < (ngx.now()-2) then
local redis = require "resty.redis";
local red = redis:new();
local ok,err = red:connect("127.0.0.1",6379);
if not ok then
ngx.log(ngx.INFO,"connect error");
else
local local_black_list,err = red:smembers("ip_black_list");
ip_black_list:flush_all();
for k,v in pairs(local_black_list)
do
ip_black_list:set(v,true);
end
ip_black_list:set("last_update_time",ngx.now());
end
end
local ip=ngx.var.remote_addr;
ngx.log(ngx.INFO,"request ip is "..ip);
-- 判断是否在黑名单
if ip_black_list:get(ip) then
return ngx.exit(503);
end
vim conf/nginx-black-list.conf
worker_processes 1;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http {
## 定义共享空间
lua_shared_dict ip_black_list 1m;
include mime.types;
default_type application/octet-stream;
server {
listen 8083;
location / {
default_type text/html;
access_by_lua_file /usr/local/openresty/nginx/lua/black-list-access.lua;
proxy_pass http://localhost:8080/;
}
}
}
./sbin/nginx -p ./ -c conf/nginx-black-list.conf
![](https://img-blog.csdnimg.cn/img_convert/7fec42636ed1d184610872cb7a25d1d2.png)