网站首页 > 精选教程 正文
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-09-29 Spring Cloud微服务项目完整示例,含注册中心,网关,断路器等等
- 2024-09-29 API网关从入门到放弃 api网关设计原则
- 2024-09-29 深入浅出深度了解springboot服务gateway网关
- 2024-09-29 网关是如何实现负载均衡的? 网关运行
- 2024-09-29 微服务实战系列(九)-注册中心与网关高可用架构设计
- 2024-09-29 高性能多级网关与多级缓存架构落地实战(超清完结)
- 2024-09-29 Kong网关(github 2.1万star)作者深度解读:为什么需要API网关?
- 2024-09-29 30 微服务网关概述 微服务网关服务
- 2024-09-29 微服务路由网关sia-gateway 微服务 网关 选型
- 2024-09-29 API网关是什么 api网关管理系统
你 发表评论:
欢迎- 最近发表
-
- 我的世界光影MOD下载(我的世界光影mod下载安装)
- 我的世界1.7/1.8VoxelMap小地图MOD下载
- 我的世界1.7.10多世界 整合包(我的世界1.7.10forge整合包)
- 我的世界1.8最好用的修改器下载(我的世界1.8最好用的修改器下载安装)
- 我的世界更多弯曲动作MOD下载(我的世界更多弯曲动作mod下载手机版)
- 我的世界龙珠MOD下载(我的世界龙珠模组整合包下载)
- 我的世界1.7.10以太2 下载(我的世界以太2mod1.12.2)
- 我的世界虚拟人生MOD下载分享(我的世界虚拟人生下载安装)
- 我的世界无正版账号的简单联机方法(非网易版,仅适用于局域网)
- “我的语言极限,即是我的世界的极限。” ——《On Java》书籍推荐
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)