重试,限流与服务降级

本文介绍了spring-cloud架构中关于重试、限流和服务降级的概念。通过配置ribbon实现服务实例间的重试机制,利用redis实现限流功能,并详细讲述了在所有服务不可用时如何进行服务降级。通过实际操作,验证了这些功能的正确性和效果。
摘要由CSDN通过智能技术生成

spring-cloud架构的几个概念理解

ribbon的重试功能

当A服务部署在N台服务器上,ribbon路由到A(n1)…的过程中,如果A(n1)实例异常关闭,则通过配置重试机制可以向后搜索可用的实例,配置项如下:


zuul.retryable=true
ribbon.eager-load.enabled=true
ribbon.restclient.enabled=true
ribbon.ReadTimeout=3000
ribbon.ConnectTimeout=3000
ribbon.MaxAutoRetries=0
ribbon.MaxAutoRetriesNextServer=3
ribbon.okToRetryOnAllOperations=true

结合redis实现限流功能

限流有三种实现算法:计数器,漏桶,令牌桶。计数器结合redis的实现如下:

zuul.routes.demo1.path=/demo1/**
zuul.routes.demo1.serviceId=demo1
zuul.routes.demo1.sensitive-headers=
zuul.routes.demo1.custom-sensitive-headers=true
zuul.routes.demo1.strip-prefix=true
zuul.routes.demo1.qps=10

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        String key = ctx.getRequest().getRequestURI();
        String serviceId = key.substring(0, key.indexOf("/", 1));

        synchronized (this){
            String prop = String.format("zuul.routes.%s.qps", serviceId);
            if (environment.containsProperty(prop)) {
                String s = environment.getProperty(prop);
                long limit = Objects.nonNull(s) ? Long.parseLong(s) : Integer.MAX_VALUE;
                long v = redisService.increment(key, 1, 1);
                if (v > limit) {
                    throw new ZuulException(ZuulEnums.STATUS_BUSY_SERVICE_TEXT.getValue(), ZuulEnums.STATUS_BUSY_SERVICE.getIntValue(), "");
                }
            }
        }

        return null;
    }

当所有的服务An都不可用时,尝试降级

当所有服务不可用时进行降级,降级处理仍然是不能正常提供服务的,只是一种异常的特殊响应。使用FallbackProvider实现降级的代码如下:


public class ZuulFallback implements FallbackProvider {

    private String route;

    public ZuulFallback(String route){
        this.route = route;
    }

    @Override
    public String getRoute() {
        return this.route;
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @SuppressWarnings("unchecked")
            @Override
            public InputStream getBody() throws IOException {
                BaseResult baseResult = new BaseResult();
                baseResult.setStatus(ZuulEnums.STATUS_DOWN_SERVER.getValue());
                baseResult.setMessage(ZuulEnums.STATUS_DOWN_SERVER_TEXT.getValue());
                baseResult.setSuccess(false);
                baseResult.setData(new JSONObject());
                baseResult.setTimestamp(System.currentTimeMillis());
                return new ByteArrayInputStream(JSONObject.toJSONBytes(baseResult, SerializerFeature.WriteMapNullValue));
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
                return httpHeaders;
            }
        };
    }
}

亲测经历

启动的项目有:
注册中心:http://localhost:10010/
网关服务:http://localhost:10012/
接口地址:/demo1/index/test
demo1项目部署两台服务,端口号分别为10013、20013;使用睡眠的方式让/index/test睡眠200ms,目的是让接口平均响应速度在200ms出头一点

启动所有服务,执行测试脚本:

ab -n 10000 -c 1 -p d:/pdata.json -T 'application/json' http://localhost:10012/demo1/index/test

过程中,关闭端口号20013的服务(直接关闭进程,非shutdown的方式),ribbon重试正常,没有异常响应。

由于接口调用差不多需要215ms左右,所以按每秒处理不到5个请求的来算,如果把线程数调整为3(4*3=12>10),因此理论上会报限流异常信息。执行测试脚本:

ab -n 10000 -c 3 -p d:/pdata.json -T 'application/json' http://localhost:10012/demo1/index/test

过程中,限流异常正常响应,观察处理正常的请求数量确实每秒10个。

现在为了观察降级的响应,手动将10013和20013服务都关闭掉,可以观察接口响应的内容确实为降级响应的内容
或者,将限流QPS调整为99999,同时将测试脚本的线程数故意加大,比如100个甚至更多,此时也可以观察到由于demo1单体服务能力的不足导致接口返回降级响应的内容

结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值