*/
rateLimitService.cacheSha1();
/**
*缓存秒杀lua脚本的sha1编码,方便在其他地方获取
*/
redisSeckillServiceImpl.cacheSha1();
return RestOut.success(goodDTO).setRespMsg(“秒杀开启成功”);
}
return RestOut.error(“秒杀开启失败”);
}
…
}
限流器初始化之后,就可以在Zuul内部网关或者Nginx外部网关进行请求拦截时使用分布式限流器进行限流。Zuul内部网关的限流拦截过程如图10- 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 13所示。
图10-13 Zuul内部网关限流拦截示意图
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);