The flow restrictor micro SpringCloud achieve granularity services on Zuul (jmeter actual analog test throughput high concurrency)

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/qq_31122833/article/details/97784250

1, Google Guava flow restrictor provides tools RateLimiter, add the following in the dependent Zuul:

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

2, in the new service Zuul plus RateLimitZuulFilter classes, inheritance ZuulFilter, source code as follows:

@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, in order to facilitate testing, as follows added Zuul configuration:

#目标主机最大连接数和每个主机的初始连接数。
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, the test shots:

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

 

 

 

Guess you like

Origin blog.csdn.net/qq_31122833/article/details/97784250