SpringCloud灰度发布的设计与实现详解

 更新时间:2023年09月01日 08:54:37   作者:魔笛Love  
这篇文章主要介绍了SpringCloud灰度发布的设计与实现详解,灰度从字面意思理解就是存在于黑与白之间的一个平滑过渡的区域,所以说对于互联网产品来说,上线和未上线就是黑与白之分,而实现未上线功能平稳过渡的一种方式就叫做灰度发布,需要的朋友可以参考下

灰度发布

什么是灰度发布呢?要想了解这个问题就要先明白什么是灰度。

灰度从字面意思理解就是存在于黑与白之间的一个平滑过渡的区域,所以说对于互联网产品来说,上线和未上线就是黑与白之分,而实现未上线功能平稳过渡的一种方式就叫做灰度发布。

在一般情况下,升级服务器端应用,需要将应用源码或程序包上传到服务器,然后停止掉老版本服务,再启动新版本。

但是这种简单的发布方式存在两个问题,一方面,在新版本升级过程中,服务是暂时中断的,另一方面,如果新版本有BUG,升级失败,回滚起来也非常麻烦,容易造成更长时间的服务不可用。

在了解了什么是灰度发布的定义以后,就可以来了解一下灰度发布的具体操作方法了。

可以通过抽取一部分用户,比如说选择自己的测试用户,使这些用户的请求全部访问灰度发布的服务,正式用户请求走正常上线的服务,那么就能够将需要灰度发布的版本也连接到正常上线服务中进行测试,没有问题之后将其设置为正常服务即完成版本的上线测试和发布。

实现设计

实现重点主要在:

  • 利用 ThreadLocal+Feign 实现 http head 中实现信息的传递
  • 使用Nacos的元数据,定义需要的灰度服务
  • 自定义Ribbon的路由规则,根据Nacos的元数据选择服务节点

公共配置

ThreadLocal

public class PassParameters {
    private static final Logger log = LoggerFactory.getLogger(PassParameters.class);
    private static final ThreadLocal localParameters = new ThreadLocal();
    public static PassParametersModel get(){
        PassParametersModel model = (PassParametersModel) localParameters.get();
        log.info("ThreadID:{}, threadLocal {}", Thread.currentThread().getId(), model.toString());
        return model;
    }
    public static void set(PassParametersModel model){
        log.info("ThreadID:{}, threadLocal set {}", Thread.currentThread().getId(), model.toString());
        localParameters.set(model);
    }
}

携带灰度发布相关数据的类

public class PassParametersModel {
    private String token;
    private String grayPublish;
}

请求头常量

public class HttpConstants {
    public static final String AUTHORIZATION_HEADER = "Authorization";
    public static final String GRAY_PUBLISH = "Gray-Publish";
    public static final String GRAY_PUBLISH_MEAT_KEY = "grayPublish";
}

AOP请求拦截处理

@Aspect
@Order(1)
@Component
public class PermissionsValidationAspect {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 权限校验以及一些参数的赋值O
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "需要拦截的方法")
    public Object check(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取一些参数
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader(HttpConstants.AUTHORIZATION_HEADER);
        // FIXME:
        // token权限校验,不要去查数据库!!!!
        // 来这里的token肯定都是有用的,因为在网关那里就会进行token有效的校验
        // 校验成功之后进行用户身份的赋值,比如uid、username等关键信息
        // 本次请求涉及到的灰度发布
        // FIXME: 通过用户所属的用户组或其他标识信息,专门指定某些用户是灰度发布测试用户,来设置灰度发布的字段
        String grayPublish = request.getHeader(HttpConstants.GRAY_PUBLISH);
        PassParametersModel model = new PassParametersModel();
        model.setToken(token);
        model.setGrayPublish(grayPublish);
        PassParameters.set(model);
        return joinPoint.proceed();
    }
}

Feign配置

Ribbon请求规则

将会从Nacos中获取元服务器的信息,并根据这个信息选择服务器。

public class GrayPublishInterceptor implements RequestInterceptor {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Override
    public void apply(RequestTemplate requestTemplate) {
        PassParametersModel model = PassParameters.get();
        // token
        if (StringUtils.isNotEmpty(model.getToken())) {
            requestTemplate.header(HttpConstants.AUTHORIZATION_HEADER, model.getToken());
        }
        // grayPublish
        if (StringUtils.isNotEmpty(model.getGrayPublish())) {
            requestTemplate.header(HttpConstants.GRAY_PUBLISH, model.getGrayPublish());
        }
		// FIXME: 补充其他需要传递的内容
    }
}

Feign拦截器

将需要传递给下个微服务中的数据进行赋值

public class GrayPublishInterceptor implements RequestInterceptor {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Override
    public void apply(RequestTemplate requestTemplate) {
        PassParametersModel model = PassParameters.get();
        // token
        if (StringUtils.isNotEmpty(model.getToken())) {
            requestTemplate.header(HttpConstants.AUTHORIZATION_HEADER, model.getToken());
        }
        // grayPublish
        if (StringUtils.isNotEmpty(model.getGrayPublish())) {
            requestTemplate.header(HttpConstants.GRAY_PUBLISH, model.getGrayPublish());
        }
		// FIXME: 补充其他需要传递的内容
    }
}

配置使用

这里是全局配置使用

@Configuration
public class FeignConfig {
    // 灰度发布Ribbon规则
    @Bean
    public IRule getRule(){
        return new GrayPublishRibbonRule();
    }
    // header传递
    @Bean
    public GrayPublishInterceptor getInterceptor(){
        return new GrayPublishInterceptor();
    }
}

Nacos元数据配置

通过在application.yml进行配置

# 服务的元数据
spring:
  cloud:
    nacos:
      discovery:
        metadata.grayPublish: HAHAHA_TEST

到此这篇关于SpringCloud灰度发布的设计与实现详解的文章就介绍到这了,更多相关SpringCloud灰度发布内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 自己写的java日志类和方法代码分享

    自己写的java日志类和方法代码分享

    这篇文章主要介绍了一个自己写的java日志类和方法,下面把代码分享给大家
    2014-01-01
  • SpringBoot整合RabbitMQ处理死信队列和延迟队列

    SpringBoot整合RabbitMQ处理死信队列和延迟队列

    这篇文章将通过示例为大家详细介绍SpringBoot整合RabbitMQ时如何处理死信队列和延迟队列,文中的示例代码讲解详细,需要的可以参考一下
    2022-05-05
  • Java Maven Settings配置参考教程

    Java Maven Settings配置参考教程

    这篇文章主要介绍了Java Maven Settings配置参考,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Springboot中加入druid连接池

    Springboot中加入druid连接池

    这篇文章主要介绍了Springboot中加入druid连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,下面来看看文章的具体内容吧
    2022-01-01
  • Java中@JSONField注解的使用详解

    Java中@JSONField注解的使用详解

    这篇文章主要介绍了Java中@JSONField注解的使用,@JSONField是阿里巴巴开源的JSON处理库FastJSON提供的一个注解,用于在Java对象和JSON数据之间进行序列化和反序列化时,对字段的行为进行更精细的控制,需要的朋友可以参考下
    2025-05-05
  • Spring web开发教程之Request获取3种方式

    Spring web开发教程之Request获取3种方式

    这篇文章主要给大家介绍了关于Spring web开发教程之Request获取3种方式的相关资料,request对象是从客户端向服务器发出请求,包括用户提交的信息以及客户端的一些信息,需要的朋友可以参考下
    2023-11-11
  • 使用log4j输出一个类的所有参数的值

    使用log4j输出一个类的所有参数的值

    这篇文章主要介绍了使用log4j输出一个类的所有参数的值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java线程死锁代码详解

    Java线程死锁代码详解

    本篇文章主要介绍了Java线程死锁代码详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-11-11
  • Java中Minio的基本使用详解

    Java中Minio的基本使用详解

    这篇文章主要介绍了Java中Minio的基本使用详解,MinIO 是一个基于Apache License v2.0开源协议的对象存储服务,它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,需要的朋友可以参考下
    2024-01-01
  • springboot项目中后端接收前端传参的方法示例详解

    springboot项目中后端接收前端传参的方法示例详解

    这篇文章主要介绍了springboot项目中一些后端接收前端传参的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06

最新评论