本文将带领大家精读3个Nginx Lua编程实战案例,学不会就来砍我

(1)getCache(self,goodId):根据商品id取得Redis商品缓存。

(2)goUpstream(self):通过capture内部请求访问上游接口获取商品数据。

(3)setCache(self,goodId,goodString):设置商品缓存,此方法用于模拟后台Java代码。

缓存操作类RedisCacheDemo的核心代码如下:

—启动调试,正式环境请注释

local mobdebug = require(“luaScript.initial.mobdebug”);

mobdebug.start();

–导入自定义的基础模块

local basic = require(“luaScript.module.common.basic”);

–导入自定义的RedisOperator模块

local redisOp = require(“luaScript.redis.RedisOperator”);

local PREFIX = “GOOD_CACHE:”

–RedisCacheDemo类

local _RedisCacheDemo = { }

_RedisCacheDemo.__index = _RedisCacheDemo

–类的方法new

function _RedisCacheDemo.new(self)

local object = {}

setmetatable(object, self)

return object;

end

–根据商品id取得缓存

function _RedisCacheDemo.getCache(self,goodId)

–创建自定义的redis操作对象

local red = redisOp:new();

–打开连接

if not red:open() then

basic:error(“redis连接失败”);

return nil;

end

–获取缓存数据 local json = red:getValue(PREFIX … goodId);

red:close();

if not json or json==ngx.null then

basic:log(goodId … “的缓存没有命中”);

return nil;

end

basic:log(goodId … “缓存成功命中”);

return json;

end

–通过capture方法回源上游接口

function _RedisCacheDemo.goUpstream(self)

local request_method = ngx.var.request_method

local args = nil

–获取参数的值

if “GET” == request_method then

args = ngx.req.get_uri_args()

elseif “POST” == request_method then

ngx.req.read_body()

args = ngx.req.get_post_args()

end

–回源上游接口,比如Java后端rest接口

local res = ngx.location.capture(“/java/good/detail”,{

method = ngx.HTTP_GET,

args = args --重要:将请求参数原样向上游传递

})

basic:log(“上游数据获取成功”);

–返回上游接口的响应体body

return res.body;

end

–设置缓存,此方法主要用于模拟Java后台代码

function _RedisCacheDemo.setCache(self, goodId ,goodString)

–创建自定义的redis操作对象

local red = redisOp:new();

–打开连接

if not red:open() then

basic:error(“redis连接失败”);

return nil;

end

–set缓存数据

red:setValue(PREFIX … goodId,goodString);

–60秒内过期

red:expire(PREFIX … goodId, 60);

basic:log(goodId … “缓存设置成功”);

–归还连接到连接池

red:close();

return json;

end

return _RedisCacheDemo;

在nginx-redis-demo.conf配置文件中编写一个location配置块来使用该脚本,该配置块是提供给外部调用的商品查询接口/good/detail,具体代码如下:

首先从缓存中查询商品

未命中再回源到

后台 #首先从缓存中查询商品,未命中再回源到Java后台

location = /good/detail {

content_by_lua_block {

local goodId=ngx.var.arg_goodid;

–判断goodId参数是否存在

if not goodId then

ngx.say(“请输入goodId”);

return;

end

–首先从缓存中根据id查询商品

local RedisCacheDemo = require “luaScript.redis.RedisCacheDemo”;

local redisCacheDemo = RedisCacheDemo:new();

local json = redisCacheDemo:getCache(goodId);

–判断缓存是否被命中

if not json then

ngx.say(“缓存是否被命中,回源到上游接口
”);

–若没有命中缓存,则回源到上游接口

json = redisCacheDemo:goUpstream();

else

ngx.say(“缓存已经被命中
”);

end

ngx.say(“商品信息:”,json);

}

}

出于调试方便,在nginx-redis-demo.conf配置文件中再编写一个location配置块来模拟Java容器的后台商品查询接口/java/good/detail。

理论上,后台接口的业务逻辑是从数据库查询商品信息并缓存到Redis,然后返回商品信息。这里为了方便演示对其进行简化,具体的代码如下:

#模拟Java后台接口查询商品,然后设置缓存

location = /java/good/detail {

#指定规则为internal内部规则,防止外部请求命中此规则

internal;

content_by_lua_block {

local RedisCacheDemo = require “luaScript.redis.RedisCacheDemo”;

–Java后台将从数据库查找商品,这里简化成模拟数据

local json=‘{goodId:商品id,goodName:商品名称}’;

–将商品缓存到Redis

local redisCacheDemo = RedisCacheDemo:new();

redisCacheDemo:setCache(ngx.var.arg_goodid, json);

–返回商品到下游网关

ngx.say(json);

}

}

}

修改了nginx-redis-demo.conf文件后重启OpenRestry,然后使用浏览器访问商品查询外部接口/good/detail,并且多次刷新,发现从二次请求开始就能成功命中缓存,其结果如图8-26所示。

本文将带领大家精读3个Nginx Lua编程实战案例,学不会就来砍我

图8-26 使用浏览器访问商品查询外部接口/good/detail的结果

Nginx+Redis实现黑名单拦截

==================

我们在日常维护网站时经常会遇到这样一个需求,对于黑名单之内的IP需要拒绝提供服务。实现IP黑名单拦截有很多途径,比如以下方式:

(1)在操作系统层面配置iptables防火墙规则,拒绝黑名单中IP的网络请求。

(2)使用Nginx网关的deny配置指令拒绝黑名单中IP的网络请求。

(3)在Nginx网关的access处理阶段,通过Lua脚本检查客户端IP是否在黑名单中。

(4)在Spring Cloud内部网关(如Zuul)的过滤器中检查客户端

IP是否在黑名单中。

以上检查方式都是基于一个静态的、提前备好的黑名单进行的。在系统实际运行过程中,黑名单往往需要动态计算,系统需要动态识别出大量发起请求的恶意爬虫或者恶意用户,并且将这些恶意请求的IP放入一个动态的IP黑名单中。

Nginx网关可以依据动态黑名单内的IP进行请求拦截并拒绝提供服务。这里结合Nginx和Redis提供一个基于动态IP黑名单进行请求拦截的实现。

首先是黑名单的组成,黑名单应该包括静态部分和动态部分。静态部分为系统管理员通过控制台设置的黑名单。动态部分主要通过流计算框架完成,具体的方法为:将Nginx的访问日志通过Kafka消息中间件发送到流计算框架,然后通过滑动窗口机制计算出窗口内相同IP的访问计数,将超出阈值的IP动态加入黑名单中,流计算框架可以选用ApacheFlink或者Apache Storm。当然,除了使用流计算框架外,也可以使用RxJava滑动窗口进行访问计数的统计。

这里对黑名单的计算和生成不做研究,假定IP黑名单已经生成并且定期更新在Redis中。Nginx网关可以直接从Redis获取计算好的IP黑名单,但是为了提升黑名单的读取速度,并不是每一次请求过滤都从Redis读取IP黑名单,而是从本地的共享内存black_ip_list中获取,同时定期更新到本地共享内存中的IP黑名单。

Nginx+Redis实现黑名单拦截的系统架构如图8-27所示。

本文将带领大家精读3个Nginx Lua编程实战案例,学不会就来砍我

图8-27 Nginx+Redis实现黑名单拦截的系统架构

这里提供一个“Nginx+Redis”实现黑名单拦截的参考实现,具体的Lua脚本如下:

—启动调试,正式环境请注释

local mobdebug = require(“luaScript.initial.mobdebug”);

mobdebug.start();

–导入自定义的基础模块

local basic = require(“luaScript.module.common.basic”);

–导入自定义的RedisOperator模块

local redisOp = require(“luaScript.redis.RedisOperator”);local ip = basic.getClientIP();

basic.log(“ClientIP:”…ip);

–lua_shared_dict black_ip_list 1m; #配置文件定义的ip_blacklist共享内存变量

local black_ip_list = ngx.shared.black_ip_list

–获得本地缓存的刷新时间,如果没有过期,就直接使用

local last_update_time = black_ip_list:get(“last_update_time”);

if last_update_time ~= nil then

local dif_time = ngx.now() - last_update_time

if dif_time < 60 then --缓存1分钟,没有过期

if black_ip_list:get(ip) then

return ngx.exit(ngx.HTTP_FORBIDDEN) --直接返回403

end

return

end

end

local KEY = “limit:ip:blacklist”;

–创建自定义的redis操作对象

local red = redisOp:new();

–打开连接

red:open();

–获取缓存的黑名单

local ip_blacklist = red:getSmembers(KEY);

–归还连接到连接池

red:close();

if not ip_blacklist then

basic.log(“black ip set is null”);

return;

else

–刷新本地缓存

black_ip_list:flush_all();

–同步redis黑名单到本地缓存

for i,ip in ipairs(ip_blacklist) do

–本地缓存redis中的黑名单

black_ip_list:set(ip,true);

end

–设置本地缓存的最新更新时间

black_ip_list:set(“last_update_time”,ngx.now());

最后希望可以帮助到大家!

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

image

(2)刷的算法题(还有左神的算法笔记)

image

(3)面经+真题解析+对应的相关笔记(很全面)

image

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

在这里,最后只一句话:祝大家offer拿到手软!!
最新更新时间

black_ip_list:set(“last_update_time”,ngx.now());

最后希望可以帮助到大家!

千千万万要记得:多刷题!!多刷题!!

之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!

篇幅有限,以下只能截图分享部分的资源!!

(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)

[外链图片转存中…(img-zLxxmVhI-1720114477981)]

(2)刷的算法题(还有左神的算法笔记)

[外链图片转存中…(img-NUAlpNbp-1720114477982)]

(3)面经+真题解析+对应的相关笔记(很全面)

[外链图片转存中…(img-o3vyUVYX-1720114477982)]

(4)视频学习(部分)

ps:当你觉得学不进或者累了的时候,视频是个不错的选择

在这里,最后只一句话:祝大家offer拿到手软!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值