IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 灰度方案-svc环境实现方案以及网关源码分析 -> 正文阅读

[Java知识库]灰度方案-svc环境实现方案以及网关源码分析

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

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

前言


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

k8s服务发现


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

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

实现思路


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

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

实现方案

流程图.jpg

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

网关源码(版本3.1.1)


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

基本类

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

网关流程


流程图 (3).jpg

网关源码


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

DefaultWebFilterChain

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

image.png

DispatcherHandler

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

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


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

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

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

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

   Map<String, HandlerResultHandler> 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

image.png

image.png

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

RoutePredicateHandlerMapping

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

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

image.png

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

FilteringWebHandler

image.png

它会加载所有继承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<Void> 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,默认给你加上,路由到生产。如果你加上了,可以自定义逻辑路由到灰度域名。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 11:43:27  更:2022-05-10 11:45:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:48:44-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码