网站首页 > 技术教程 正文
Zuul内部网关实现秒杀限流
秒杀限流操作既可以在内部网关Zuul中完成,又可以在外部网关Nginx中完成。内部网关Zuul可以通过ZuulFilter过滤器的形式对获取秒杀令牌的请求进行拦截,然后通过Redis令牌桶限流服务实现分布式限流。
从前面的内容可知,Redis中存储限流令牌桶信息的是一个哈希表结构,其内部的键值对包括max_permits、curr_permits、rate、last_mill_second四个hash key,而整个令牌桶哈希表结构的缓存key的格式为rate_limiter:seckill:1(1为商品ID),其中重要的部分是秒杀商品ID,该ID表示限流统计的范围是针对一个秒杀商品的,而不是针对整个秒杀接口。
秒杀商品(假设ID为1)的限流令牌桶的Redis哈希表结构如图10-12所示。
在秒杀没有开始之前需要初始化限流令牌桶的Redis哈希表结构,虽然真正的初始化工作是在rate_limit.lua脚本中完成的,但是需要通过Java程序进行调用,并传入相关的初始化参数。什么时候进行限流令牌桶的初始化呢?生产环境上的秒杀开始之前应该有一个秒杀商品暴露(或者启动)的动作,该动作可以手动或者自动完成,限流的初始化工作可以在秒杀暴露时完成。
下面是一个限流的初始化的简单示例:
package com.crazymaker.springcloud.seckill.controller;
//省略import
@RestController
@RequestMapping("/api/seckill/good/")
@Api(tags = "秒杀练习 商品管理")
public class SeckillGoodController
{
/**
*开启商品秒杀
*
*@param dto商品id
*@return商品goodDTO
*/
@PostMapping("/expose/v1")
@ApiOperation(value = "开启商品秒杀")
RestOut<SeckillGoodDTO> expose(@RequestBody SeckillDTO dto)
{
Long goodId = dto.getSeckillGoodId();
SeckillGoodDTO goodDTO = seckillService.findGoodByID(goodId);
if (null != goodDTO)
{
//初始化秒杀的限流器
rateLimitService.initLimitKey(
"seckill",
String.valueOf(goodId),
SeckillConstants.MAX_ENTER,
SeckillConstants.PER_SECKOND_ENTER
);
/**
*缓存限流lua脚本的sha1编码,方便在其他地方获取
*/
rateLimitService.cacheSha1();
/**
*缓存秒杀lua脚本的sha1编码,方便在其他地方获取
*/
redisSeckillServiceImpl.cacheSha1();
return RestOut.success(goodDTO).setRespMsg("秒杀开启成功");
}
return RestOut.error("秒杀开启失败");
}
...
}
限流器初始化之后,就可以在Zuul内部网关或者Nginx外部网关进行请求拦截时使用分布式限流器进行限流。Zuul内部网关的限流拦截过程如图10-13所示。
Zuul网关限流过滤器类SeckillRateLimitFilter的代码如下:
package com.crazymaker.springcloud.cloud.center.zuul.filter;
//省略import
@Slf4j
@ConditionalOnBean(RedisRateLimitImpl.class)
@Component
public class SeckillRateLimitFilter extends ZuulFilter
{
/**
*Redis限流服务实例
*/
@Resource(name = "redisRateLimitImpl")
RateLimitService redisRateLimitImpl;
@Override
public String filterType()
{
return "pre"; //路由之前
}
/**
*过滤的顺序
*/
@Override
public int filterOrder()
{
return 0;
}
/**
*这里可以编写逻辑判断是否要过滤,true为永远过滤
*/
@Override public boolean shouldFilter()
{
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
/**
*如果请求已经被其他的过滤器终止,本过滤器就不做处理
**/
if (!ctx.sendZuulResponse())
{
return false;
}
/**
*对秒杀令牌进行限流
*/
if (request.getRequestURI().startsWith
("/seckill-provider/api/seckill/redis/token/v1"))
{
return true;
}
return false;
}
/**
*过滤器的具体逻辑
*/
@Override
public Object run()
{
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String goodId = request.getParameter("goodId");
if (goodId != null)
{
String cacheKey = "seckill:" + goodId;
Boolean limited = redisRateLimitImpl.tryAcquire(cacheKey);
if (limited)
{
/**
*被限流后的降级
*/
String msg = "参与抢购的人太多,请稍后再试一试";
fallback(ctx, msg);
return null;
}
return null;
} else
{
/**
*参数输入错误时的降级处理
*/
String msg = "必须输入抢购的商品";
fallback(ctx, msg);
return null;
}
}
/**
*被限流后的降级处理
*
*@param ctx
*@param msg
*/
private void fallback(RequestContext ctx, String msg)
{
ctx.setSendZuulResponse(false);
try
{
ctx.getResponse().setContentType("text/html;charset=utf-8");
ctx.getResponse().getWriter().write(msg);
} catch (Exception e)
{ e.printStackTrace();
}
}
}
本文给大家讲解的内容是高并发核心编程,Spring Cloud+Nginx秒杀实战,Zuul内部网关实现秒杀限流
- 下篇文章给大家讲解的是高并发核心编程,Spring Cloud+Nginx秒杀实战,Nginx高性能秒杀和限流;
- 觉得文章不错的朋友可以转发此文关注小编;
- 感谢大家的支持!
猜你喜欢
- 2024-10-16 NGINX配置跨域CORS支持(nginx跨域解决方案)
- 2024-10-08 前端Nginx那些事,精益求精(前端 nginx)
- 2024-10-08 nginx中request_body_size ,body_bytes_sent ,bytes_sent 区别
你 发表评论:
欢迎- 最近发表
-
- linux日志文件的管理、备份及日志服务器的搭建
- Linux下挂载windows的共享目录操作方法
- Linux系统中的备份文件命令(linux系统中的备份文件命令有哪些)
- 麒麟KYLINOS|通过不同方法设置用户访问文件及目录权限
- 「Linux笔记」系统目录结构(linux目录的结构及含义)
- linux中修改归属权chown命令和chgrp命令
- 工作日报 2021.10.27 Android-SEAndroid权限问题指南
- Windows和Linux环境下,修改Ollama的模型默认保存路径
- 如何强制用户在 Linux 上下次登录时更改密码?
- 如何删除Linux文件夹中除某些扩展名之外的所有文件?
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)