乐趣区

关于springboot:Spring-Cloud-Gray-微服务灰度路由控制

在 Spring Cloud Gray 由 spring-cloud-gray-client(角色灰度客户端),spring-cloud-gray-client-netflix 和 spring-cloud-tray-server,spring-cloud-gray-webui 组成。
spring-cloud-gray-client 定义了一套灰度路由决策模型,灰度信息追踪模型,以及和 spring-cloud-gray-server 的根本通信性能。
spring-cloud-gray-client-netflix 在 spring-cloud-gray-client 的根底上集成了微服务注册核心 eureka,扩大 ribbon 的负载平衡规定,提供了对 zuul,feign,RestTemplate 的灰度路由能力,并且无缝反对 hystrix 线程池隔离。
spring-cloud-gray-server 负责灰度决策、灰度追踪等信息的治理以及长久化。

注册核心  负责服务的注册和发现。

灰度客户端  灰度的客户端是指依赖了 spring-cloud-gray-client 的服务,个别是指服务生产方。

灰度管控端  负责灰度信息的治理、长久化等保护工作。

灰度客户端会从灰度管控端拉取一份灰度信息的清单,并在内存中保护这份清单信息,清单中蕴含服务,服务实例,灰度策略,灰度追踪字段等。当申请达到网关时,网关就会在灰度追踪中将须要透传的信息记录下来,并将传递给转发的服务实例,前面的接口调用也会依照同样的逻辑将追踪信息透传下去,从而保障所有一个申请在微服务调用链中的灰度路由。

public class CustomMetadataRule extends ZoneAvoidanceRule {

// 检测灰度开关是否启动
private HttpResult checkGraySwitch() {
    String url = "http://127.0.0.1:6015/eureka/apps/switch";
    HttpResult result = new HttpResult();
    result.statusCode = 500;
    try {result = HttpClient.get(url, null);
    } catch (Exception e1) {e1.printStackTrace();
    }

    return result;
}

@Override
public Server choose(Object key) {

    // 获取是否存在存活的服务可调用
    List<Server> serverList = this.getPredicate().getEligibleServers(this.getLoadBalancer().getAllServers());
    // 获取不到服务
    if (CollectionUtils.isEmpty(serverList)) {return null;}

    // 获取灰度开关是否启动
    HttpResult result = checkGraySwitch();

    // 灰度开关被设置成敞开状态, 默认走空 metadata 或者是特定标识是失常的服务, 轮询拜访
    Boolean isOpen = Boolean.parseBoolean(JSONObject.parseObject(result.content).getString("errorMsg"));
    if (result.statusCode == 200 && !isOpen) {
        isOpen = true;
        return RoundRobinRuleBySelf.getInstance().choose(this.getLoadBalancer(), key,isOpen);
    }

    // 灰度公布启动状态, 未被设置成灰度对象, 默认走空 metadata 或者是特定标识是失常的服务, 轮询拜访
    if (StringUtils.isEmpty(CoreHeaderInterceptor.label.get())) {
        isOpen = false;
        return RoundRobinRuleBySelf.getInstance().choose(this.getLoadBalancer(), key,isOpen);
    }
    
    // 灰度公布启动状态, 被设置成灰度对象, 走空特定标识的服务, 轮询拜访
    return RoundRobinRuleBySelf.getInstance().choose(this.getLoadBalancer(), key,!isOpen);
}

}

feignClient 调用 flag 位透传的问题

public class CoreFeignRequestInterceptor implements RequestInterceptor {

private static final Logger logger = LoggerFactory.getLogger(CoreHttpRequestInterceptor.class);

@Override
public void apply(RequestTemplate template) {String header = StringUtils.collectionToDelimitedString(CoreHeaderInterceptor.label.get(),CoreHeaderInterceptor.HEADER_LABEL_SPLIT);
    String tag = CoreHeaderInterceptor.tag.get();
    template.header(CoreHeaderInterceptor.HEADER_LABEL, header).header(CoreHeaderInterceptor.HEADER_TAG, tag);
    logger.info("label:" + header + "tag :" + tag);
}

}

HttpRequest 调用 flag 位透传的问题

public class CoreHttpRequestInterceptor implements ClientHttpRequestInterceptor {

private static final Logger logger = LoggerFactory.getLogger(CoreHttpRequestInterceptor.class);

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {HttpRequestWrapper requestWrapper = new HttpRequestWrapper(request);

    String header = StringUtils.collectionToDelimitedString(CoreHeaderInterceptor.label.get(), CoreHeaderInterceptor.HEADER_LABEL_SPLIT);
    
    String tag = CoreHeaderInterceptor.tag.get();
    
    logger.info("label:"+header + "tag :" + tag);
    
    HttpHeaders headers = requestWrapper.getHeaders();
    headers.add(CoreHeaderInterceptor.HEADER_LABEL, header);
    headers.add(CoreHeaderInterceptor.HEADER_TAG, tag);
    
    return execution.execute(requestWrapper, body);
}

}

退出移动版