L'extension Spring Cloud Gateway prend en charge le contrôle multi-version et la publication en niveaux de gris

table des matières

Version en niveaux de gris

Plan de mise en œuvre

nginx + lua (openresty)

Netflix Zuul

Implémenté dans Spring Cloud Gateway

Intégrez des nacos


Version en niveaux de gris

En quoi consiste la version grise, veuillez vous référer au concept . Examinons l'image suivante. En termes simples: afin d'assurer une transition en douceur du processus de mise à niveau du service et d'améliorer l'expérience client, certains utilisateurs et certains utilisateurs seront mis à jour progressivement. Plusieurs versions du client apparaissent en même temps, afin de garantir la disponibilité de plusieurs versions du client, plusieurs versions de la version de serveur correspondante sont nécessaires. La version grise consiste à garantir que plusieurs versions de clients et de serveurs peuvent correctement correspondre les unes aux autres grâce à certaines stratégies.

La version dite grise, c'est-à-dire lorsqu'il y a plusieurs instances d'un service et que les versions des versions d'instance ne sont pas cohérentes, passez

Plan de mise en œuvre

nginx + lua (openresty)

 

Netflix Zuul

Il suffit de personnaliser l'assertion du ruban, le noyau est d'obtenir le numéro de version dans l'en-tête de demande supérieur et inférieur via 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;
                }
            }
        };
    }
}

Numéro de version dans la demande de maintenance

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();
    }
}

Implémenté dans Spring Cloud Gateway

La première réponse, reportez-vous à l'implémentation de zuul, personnalisez l'assertion, puis récupérez les informations de version du haut et du bas. Cependant, comme Spring Cloud Gateway est basé sur la programmation réactive webflux, le TTL traditionnel ou RequestContextHolder ne peut pas gérer correctement les demandes de contexte.

Tout d'abord, comprenons le processus d' équilibrage de charge . Une fois qu'une demande atteint la passerelle, le nom du service correspondant sera analysé, puis toutes les instances disponibles du service seront obtenues, puis notre méthode de filtrage sera appelée pour filtrer toutes les instances de service disponibles pour la demande, et finalement l'équilibrage de charge d'interrogation sera effectué.

Examinons d'abord la stratégie lb par défaut de Spring Clou pour implémenter 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());
	}
}

Il suffit de réécrire la méthode choose pour transmettre la demande de contexte à l'assertion de routage, comme suit

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

Ensuite, vous pouvez l'obtenir via PredicateKey dans l'assertion de routage

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());
	}
}

Finalement calculé en fonction de la version

    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);
	}

}

Intégrez des nacos

La combinaison de la configuration dynamique des nacos permet d'obtenir facilement des niveaux de gris

 

original

● La meilleure optimisation des performances Tomcat8 de l'histoire

Pourquoi Alibaba peut-il résister à 10 milliards en 90 secondes? - L'évolution de l'architecture distribuée à haute concurrence côté serveur

Plateforme de commerce électronique B2B - Fonction de paiement électronique ChinaPay UnionPay

Apprenez le verrouillage distribué de Zookeeper, laissez les enquêteurs vous regarder avec admiration

SpringCloud e-commerce spike microservice-solution de verrouillage distribué Redisson

Découvrez d'autres bons articles, entrez dans le compte officiel - s'il vous plaît moi - excellent dans le passé

Un compte public profond et émouvant 0.0

Je suppose que tu aimes

Origine blog.csdn.net/a1036645146/article/details/109442277
conseillé
Classement