微服务中的灰度发布是什么?实现思路又是什么?
聊技术,不止于技术

1
id: user-routeuri: lb://user-loginpredicates:=/user/**
id: user-route-grayuri: lb://user-loginpredicates:Path=/user/**=Jack
2
Spring Cloud Gateway的
3
版本号如何指定
4
灰度发布的实现
public class HeaderUsernameRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderUsernameRoutePredicateFactory.Config> {public static final String USERNAME = "Username";public HeaderUsernameRoutePredicateFactory() {super(Config.class);}public ShortcutType shortcutType() {return ShortcutType.GATHER_LIST;}public List<String> shortcutFieldOrder() {return Collections.singletonList("username");}public Predicate<ServerWebExchange> apply(Config config) {List<String> usernames = config.getUsername();return new GatewayPredicate() {public boolean test(ServerWebExchange serverWebExchange) {String username = serverWebExchange.getRequest().getHeaders().getFirst(USERNAME);if (!StringUtils.isEmpty(username)) {return usernames.contains(username);}return false;}public String toString() {return String.format("Header: Username=%s", config.getUsername());}};}public static class Config {private List<String> username;}}
public class GrayRoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;private final String serviceId;private final AtomicInteger position;public GrayRoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {this.serviceId = serviceId;this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;this.position = new AtomicInteger(new Random().nextInt(1000));}public Mono<Response<ServiceInstance>> choose(Request request) {HttpHeaders headers = (HttpHeaders) request.getContext();ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);return supplier.get(request).next().map(list -> getInstanceResponse(list, headers));}private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, HttpHeaders headers) {List<ServiceInstance> serviceInstances = instances.stream().filter(instance -> {//根据请求头中的版本号信息,选取注册中心中的相应服务实例String version = headers.getFirst("Version");if (version != null) {return version.equals(instance.getMetadata().get("version"));} else {return true;}}).collect(Collectors.toList());if (instances.isEmpty()) {if (log.isWarnEnabled()) {log.warn("No servers available for service: " + serviceId);}return new EmptyResponse();}int pos = Math.abs(this.position.incrementAndGet());ServiceInstance instance = serviceInstances.get(pos % serviceInstances.size());return new DefaultResponse(instance);}}
public class GrayReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;private final LoadBalancerClientFactory clientFactory;public GrayReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory) {this.clientFactory = clientFactory;}public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {URI url = (URI) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);String schemePrefix = (String) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);if (url != null && ("grayLb".equals(url.getScheme()) || "grayLb".equals(schemePrefix))) {ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);if (log.isTraceEnabled()) {log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);}return this.choose(exchange).doOnNext((response) -> {if (!response.hasServer()) {throw NotFoundException.create(true, "Unable to find instance for " + url.getHost());} else {URI uri = exchange.getRequest().getURI();String overrideScheme = null;if (schemePrefix != null) {overrideScheme = url.getScheme();}DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance((ServiceInstance) response.getServer(), overrideScheme);URI requestUrl = this.reconstructURI(serviceInstance, uri);if (log.isTraceEnabled()) {log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);}exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);}}).then(chain.filter(exchange));} else {return chain.filter(exchange);}}private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {URI uri = (URI) exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);GrayRoundRobinLoadBalancer loadBalancer = new GrayRoundRobinLoadBalancer(clientFactory.getLazyProvider(uri.getHost(), ServiceInstanceListSupplier.class), uri.getHost());return loadBalancer.choose(this.createRequest(exchange));}private Request createRequest(ServerWebExchange exchange) {HttpHeaders headers = exchange.getRequest().getHeaders();return new DefaultRequest<>(headers);}protected URI reconstructURI(ServiceInstance serviceInstance, URI original) {return LoadBalancerUriTools.reconstructURI(serviceInstance, original);}public int getOrder() {return LOAD_BALANCER_CLIENT_FILTER_ORDER;}}
id: user-route-grayuri: grayLb://user-loginpredicates:Path=/user/**HeaderUsername=Jack:AddRequestHeader=Version,v2id: user-routeuri: grayLb://user-loginpredicates:Path=/user/**:AddRequestHeader=Version,v1
聊技术,不止于技术。
评论
