灰度方案-svc环境实现方案以及网关源码分析

灰度方案-svc环境实现方案以及网关源码分析,第1张

个人博客:👉进入博客,关注下博主,感谢~

🌈所有博客均在上面博客首发,其他平台同步更新
🏆大家一起进步,多多指教~

前言

本篇是在k8s服务发现svc环境基础上来实现灰度方案,但是不是基于k8s实现。(我在餐厅吃饭,而不是我通过这个餐厅自己做法自己干饭)

k8s服务发现

在抛开nacos作为注册中心的基础上,大部分公司会采用云原生来实现服务的注册,就是svc。当服务启动之后,pod会被service监听到,然后将end point注册上去,然后将服务名写到iptables

在流量进来的时候,会先经过网关ingress,然后通过iptables,来找到pod地址,进行路由。

实现思路

在初探灰度发布系列–AB Test以及栗子这一篇的时候,我们介绍通过nacos实现灰度,就是通过nacos来拿到所有实例,以及实例里面元数据,进行负载均衡。

在k8s svc里头,我们也可以通过拿到这个服务列表来实现灰度,当然这个实现起来也是可以的。但是今天我们另辟蹊径,找个更简单的方法来实现。

实现方案

如上图所示,灰度用户会有特定标识,比如header不同,或者请求参数不同,ip不同,我们可以在网关层来进行不同打标,然后加上我们特定的标识,图中右边userid,如果生产用户默认给个666,让它路由到test域名,灰度用户路由到dev域名,这样就实现了灰度方案

网关源码(版本3.1.1)

既然我们是基于网关来改造,那么就要熟悉网关源码

基本类
类名用途
DispatcherHandlerHTTP请求处理程序/控制器的中央调度器。分派给注册的处理程序以处理请求,从而提供方便的映射功能。
HandlerMapping将请求映射到处理程序对象
HandlerAdapter用于使用任何处理程序接口
HandlerResultHandler进程处理程序返回值
网关流程

网关源码

gateway在处理请求的时候,首先会在HttpWebHandlerAdapter进入DefaultWebFilterChain

DefaultWebFilterChain

org.springframework.web.server.handler.DefaultWebFilterChain#filter

DispatcherHandler
  1. org.springframework.web.reactive.DispatcherHandler#setApplicationContext

@Override
public void setApplicationContext(ApplicationContext applicationContext) {
   initStrategies(applicationContext);
}


protected void initStrategies(ApplicationContext context) {
   Map mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
         context, HandlerMapping.class, true, false);

   ArrayList mappings = new ArrayList<>(mappingBeans.values());
   AnnotationAwareOrderComparator.sort(mappings);
   this.handlerMappings = Collections.unmodifiableList(mappings);

   Map adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
         context, HandlerAdapter.class, true, false);

   this.handlerAdapters = new ArrayList<>(adapterBeans.values());
   AnnotationAwareOrderComparator.sort(this.handlerAdapters);

   Map beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
         context, HandlerResultHandler.class, true, false);

   this.resultHandlers = new ArrayList<>(beans.values());
   AnnotationAwareOrderComparator.sort(this.resultHandlers);
}

这个类继承了ApplicationContextAware,也就是在类初始化之后会进行相关初始化 *** 作。它会拿到所有HandlerAdapter,HandlerResultHandler,HandlerMapping实现类

  1. org.springframework.web.reactive.DispatcherHandler#handle

这个handler就是每个处理处理逻辑

RoutePredicateHandlerMapping

这个就是路由配置映射,会在路由配置表找,url对应哪个服务,服务在哪里

org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping#lookupRoute

比如说我们添加了header带上特定参数,它在这个类会进行校验判断

FilteringWebHandler

它会加载所有继承GatewayFilter类,然后进行排序。网关基本所有拦截器都会在这层去实现

灰度demo
  • 网关配置
spring:
  cloud:
    gateway:
      routes:
        # 服务
        - id: a1
          uri: https://dev-xx.com
          predicates:
            - Path=/xx/**
            - Header=userid, 888


        - id: a2
          uri: https://test-xx.com
          predicates:
            - Path=/xx/**
            - Header=userid, 666

网关通过header头来区分去哪里,那么我们就要在网关对特定流量进行染色

通过这个类RoutePredicateHandlerMapping,我们知道网关在这里进行路由规则判断,那么其实我们需要在它之前进行做手脚,如果通过GlobalFilter是无法实现的,他也在handler里头,而且优先级比RoutePredicateHandlerMapping低。

  • 方法:实现WebFilter,改写header头
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

@Component
public class MyWebHandler implements WebFilter {


    @Override
    public Mono filter(ServerWebExchange exchange, WebFilterChain chain) {
        String userid = exchange.getRequest().getHeaders().getFirst("userid");
        if (StringUtils.isEmpty(userid)) {
            ServerHttpRequest request = exchange.getRequest().mutate()
                    .header("userid", "666")
                    .build();
            return chain.filter(exchange.mutate().request(request).build());
        }
        return chain.filter(exchange);
    }
}

在这里我们可以实现对Header、host、IP、自定义需求来改写header!

就是如果你不带上userid这个header,默认给你加上,路由到生产。如果你加上了,可以自定义逻辑路由到灰度域名。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/889893.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-14
下一篇 2022-05-14

发表评论

登录后才能评论

评论列表(0条)

保存