SpringCloud之在Zuul上实现微服务粒度的限流(jmeter模拟高并发测试吞吐量实战)

1、Google Guava提供了限流工具类RateLimiter,在Zuul下添加如下依赖:

        <!--限流-->
        <dependency>
            <groupId>com.marcosbarbero.cloud</groupId>
            <artifactId>spring-cloud-zuul-ratelimit</artifactId>
            <version>1.5.0.RELEASE</version>
        </dependency>

2、在Zuul服务下新加RateLimitZuulFilter类,继承ZuulFilter,源码如下:

@Component
public class RateLimitZuulFilter extends ZuulFilter {

    private Map<String, RateLimiter> map = Maps.newConcurrentMap();

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SystemPublicMetrics systemPublicMetrics;

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        // 这边的order一定要大于org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter的order
        // 也就是要大于5
        // 否则,RequestContext.getCurrentContext()里拿不到serviceId等数据。
        return 5;
    }

    @Override
    public boolean shouldFilter() {
        // 这里可以考虑弄个限流开启的开关,开启限流返回true,关闭限流返回false,你懂的。
        Collection<Metric<?>> metrics = systemPublicMetrics.metrics();
        Optional<Metric<?>> freeMemoryMetric = metrics.stream()
                .filter(t -> "mem.free".equals(t.getName()))
                .findFirst();
        // 如果不存在这个指标,稳妥起见,返回true,开启限流
        if (!freeMemoryMetric.isPresent()) {
            return true;
        }
        long freeMemory = freeMemoryMetric.get()
                .getValue()
                .longValue();
        // 如果可用内存小于700*1024KB,开启流控
        System.out.println("-----------------------------------freeMemory="+freeMemory);
        return freeMemory < 700*1024L;
    }

    @Override
    public Object run() {
        try {
            RequestContext context = RequestContext.getCurrentContext();
            String key = null;
            // 对于service格式的路由,走RibbonRoutingFilter
            String serviceId = (String) context.get(SERVICE_ID_KEY);
            if (serviceId != null) {
                key = serviceId;
                map.putIfAbsent(serviceId, RateLimiter.create(50));
            }else {
                 // 对于URL格式的路由,走SimpleHostRoutingFilter
                URL routeHost = context.getRouteHost();
                if (routeHost != null) {
                    String url = routeHost.toString();
                    key = url;
                    map.putIfAbsent(url, RateLimiter.create(100));
                }
            }
            RateLimiter rateLimiter = map.get(key);
            if (!rateLimiter.tryAcquire()) {
                accessTokenFail("系统繁忙,请稍后再试!");
            }
        } catch (Exception e) {
            ReflectionUtils.rethrowRuntimeException(e);
        }
        return null;
    }
    /**
     * 请求失败
     * @param message
     */
    public void accessTokenFail(String message){
        Result result = new Result();
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletResponse response = ctx.getResponse();
        ctx.setSendZuulResponse(false);
        result.setType(TypeEnum.FAIL.getCode());
        result.setMessage(message);
        result.setTrue(false);
        result.setCode(TypeEnum.rateLimit.getCode());
        response.setContentType("application/json;charset=UTF-8");
        try {
            response.getWriter().write(objectMapper.writeValueAsString(result));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3、为了方便测试,在Zuul配置中添加如下配置:

#目标主机最大连接数和每个主机的初始连接数。
zuul.host.max-total-connections=1000
zuul.host.max-per-route-connections=500
zuul.semaphore.max-semaphores=5000
#设置Hystrix隔离策略为线程池
zuul.ribbon-isolation-strategy=thread
#每个路由使用独立的线程池
zuul.thread-pool.use-separate-thread-pools=true
#修改线程池中的coreSize 默认10
hystrix.threadpool.default.coreSize=500

4、测试内容截图:

1、下载apache的jmeter进行测试
2、在jmeter里新加测试计划:5000个请求在10秒内完成(500/s),这是我在上面配置的线程数
3、启动测试(十秒内当系统freeMemory<700*1024L KB时,开启自动限流,返回‘系统繁忙’)

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小达哥的垃圾桶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值