La extensión Spring Cloud Gateway admite control de múltiples versiones y lanzamiento en escala de grises

Tabla de contenido

Lanzamiento de escala de grises

Plan de IMPLEMENTACION

nginx + lua (abierto)

Netflix Zuul

Implementado en Spring Cloud Gateway

Integrar nacos


Lanzamiento de escala de grises

Qué es la versión gris, consulte el concepto . Echemos un vistazo a la siguiente imagen. En términos sencillos: para garantizar una transición sin problemas del proceso de actualización del servicio y mejorar la experiencia del cliente, algunos usuarios y algunos usuarios se actualizarán progresivamente. Aparecen múltiples versiones del cliente al mismo tiempo, para asegurar la disponibilidad de múltiples versiones del cliente, se requieren múltiples versiones de la versión del servidor correspondiente. El lanzamiento gris es para asegurar que múltiples versiones de clientes y servidores puedan corresponder correctamente entre sí a través de ciertas estrategias.

La llamada versión gris, es decir, cuando hay varias instancias de un servicio y las versiones de las versiones de la instancia no son consistentes, pasa

Plan de IMPLEMENTACION

nginx + lua (abierto)

 

Netflix Zuul

Solo es necesario personalizar la afirmación de la cinta, el núcleo es obtener el número de versión en el encabezado de solicitud superior e inferior a través de TTL

@Slf4j
public class MetadataCanaryRuleHandler extends ZoneAvoidanceRule {

    @Override
    public AbstractServerPredicate getPredicate() {
        return new AbstractServerPredicate() {
            @Override
            public boolean apply(PredicateKey predicateKey) {
                String targetVersion = RibbonVersionHolder.getContext();
                RibbonVersionHolder.clearContext();
                if (StrUtil.isBlank(targetVersion)) {
                    log.debug("客户端未配置目标版本直接路由");
                    return true;
                }

                DiscoveryEnabledServer server = (DiscoveryEnabledServer) predicateKey.getServer();
                final Map<string, string> metadata = server.getInstanceInfo().getMetadata();
                if (StrUtil.isBlank(metadata.get(SecurityConstants.VERSION))) {
                    log.debug("当前微服务{} 未配置版本直接路由");
                    return true;
                }

                if (metadata.get(SecurityConstants.VERSION).equals(targetVersion)) {
                    return true;
                } else {
                    log.debug("当前微服务{} 版本为{},目标版本{} 匹配失败", server.getInstanceInfo().getAppName()
                            , metadata.get(SecurityConstants.VERSION), targetVersion);
                    return false;
                }
            }
        };
    }
}

Número de versión en la solicitud de mantenimiento

public class RibbonVersionHolder {
    private static final ThreadLocal<string> context = new TransmittableThreadLocal&lt;&gt;();

    public static String getContext() {
        return context.get();
    }

    public static void setContext(String value) {
        context.set(value);
    }

    public static void clearContext() {
        context.remove();
    }
}

Implementado en Spring Cloud Gateway

La primera respuesta, se refiere a la implementación de zuul, personaliza la aserción y luego obtén la información de la versión de arriba a abajo. Sin embargo, debido a que Spring Cloud Gateway se basa en la programación reactiva de webflux, TTL tradicional o RequestContextHolder no pueden mantener las solicitudes de contexto correctamente.

Primero, entendamos el proceso de balanceo de carga . Una vez que una solicitud llega a la puerta de enlace, se analizará el nombre del servicio correspondiente, y luego se obtendrán todas las instancias disponibles del servicio, y luego se llamará a nuestro método de filtrado para filtrar todas las instancias de servicio disponibles para la solicitud y, finalmente, se realizará el equilibrio de carga de sondeo.

Veamos primero la estrategia lb predeterminada de la puerta de enlace de spring clou para implementar LoadBalancerClientFilter

public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
	@Override
	public int getOrder() {
		return LOAD_BALANCER_CLIENT_FILTER_ORDER;
	}

	@Override
	@SuppressWarnings("Duplicates")
	public Mono<void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		return chain.filter(exchange);
	}

	protected ServiceInstance choose(ServerWebExchange exchange) {
		return loadBalancer.choose(
				((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost());
	}
}

Solo necesitamos reescribir el método de elección para pasar la solicitud de contexto a la aserción de enrutamiento, de la siguiente manera

@Override
protected ServiceInstance choose(ServerWebExchange exchange) {
	HttpHeaders headers = exchange.getRequest().getHeaders();
	return loadBalancer.choose(((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(), headers);
}

Entonces puede obtenerlo a través de PredicateKey en la aserción de enrutamiento

public abstract class AbstractDiscoveryEnabledPredicate extends AbstractServerPredicate {

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean apply(@Nullable PredicateKey input) {
		return input != null
				&amp;&amp; input.getServer() instanceof NacosServer
				&amp;&amp; apply((NacosServer) input.getServer(), (HttpHeaders) input.getLoadBalancerKey());
	}
}

Finalmente calculado en base a la versión

    public class GrayMetadataAwarePredicate extends AbstractDiscoveryEnabledPredicate {

	@Override
	protected boolean apply(NacosServer server, HttpHeaders headers) {
		PigxRibbonRuleProperties ribbonProperties = SpringContextHolder.getBean(PigxRibbonRuleProperties.class);

		if (!ribbonProperties.isGrayEnabled()) {
			log.debug("gray closed,GrayMetadataAwarePredicate return true");
			return true;
		}

		final Map<string, string> metadata = server.getMetadata();
		String version = metadata.get(CommonConstants.VERSION);
		// 判断Nacos服务是否有版本标签
		if (StrUtil.isBlank(version)) {
			log.debug("nacos server tag is blank ,GrayMetadataAwarePredicate return true");
			return true;
		}

		// 判断请求中是否有版本
		String target = headers.getFirst(CommonConstants.VERSION);
		if (StrUtil.isBlank(target)) {
			log.debug("request headers version is blank,GrayMetadataAwarePredicate return true");
			return true;
		}

		log.debug("请求版本:{} ,当前服务版本:{}", target, version);
		return target.equals(version);
	}

}

Integrar nacos

La combinación de la configuración dinámica de nacos puede lograr fácilmente una escala de grises

 

original

● La optimización de rendimiento de Tomcat8 más sólida de la historia

¿Por qué Alibaba puede resistir 10 mil millones en 90 segundos? - La evolución de la arquitectura distribuida de alta concurrencia del lado del servidor

Plataforma de comercio electrónico B2B: función de pago electrónico ChinaPay UnionPay

Aprenda el candado distribuido de Zookeeper, deje que los entrevistadores lo miren con admiración

Solución de bloqueo distribuido de Redisson con microservicio de pico de comercio electrónico de SpringCloud

Vea más artículos buenos, ingrese a la cuenta oficial, por favor, excelente en el pasado

Una cuenta pública profunda y conmovedora 0.0

Supongo que te gusta

Origin blog.csdn.net/a1036645146/article/details/109442277
Recomendado
Clasificación