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灰度发布内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决IDEA2020控制台乱码的方法

    解决IDEA2020控制台乱码的方法

    这篇文章主要介绍了解决IDEA2020控制台乱码的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Java获取当前时间并转化为yyyy-MM-dd HH:mm:ss格式的多种方式

    Java获取当前时间并转化为yyyy-MM-dd HH:mm:ss格式的多种方式

    这篇文章主要介绍了Java获取当前时间并转化为yyyy-MM-dd HH:mm:ss格式的多种方式,每种方式结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-03-03
  • IDEA 集成log4j将SQL语句打印在控制台上的实现操作

    IDEA 集成log4j将SQL语句打印在控制台上的实现操作

    这篇文章主要介绍了IDEA 集成log4j将SQL语句打印在控制台上的实现操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 关于SpringMVC在Controller层方法的参数解析详解

    关于SpringMVC在Controller层方法的参数解析详解

    在SpringMVC中,控制器Controller负责处理由DispatcherServlet分发的请求,下面这篇文章主要给大家介绍了关于SpringMVC在Controller层方法的参数解析的相关资料,需要的朋友可以参考下
    2021-12-12
  • java常用工具类 IP、File文件工具类

    java常用工具类 IP、File文件工具类

    这篇文章主要为大家详细介绍了java常用工具类,包括IP、File文件工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • Java自动生成编号的方法步骤

    Java自动生成编号的方法步骤

    在新增数据时,往往需要自动生成编号,本文主要介绍了Java自动生成编号的方法步骤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • Spring Boot 中使用cache缓存的方法

    Spring Boot 中使用cache缓存的方法

    Spring Cache是Spring针对Spring应用,给出的一整套应用缓存解决方案。下面小编给大家带来了Spring Boot 中使用cache缓存的方法,感兴趣的朋友参考下吧
    2018-01-01
  • JAVA实现Excel和PDF上下标的操作代码

    JAVA实现Excel和PDF上下标的操作代码

    这篇文章主要介绍了JAVA实现Excel和PDF上下标,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • java线程池使用后到底要关闭吗

    java线程池使用后到底要关闭吗

    这篇文章主要给大家介绍了关于java线程池使用后到底要不要关闭的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • SpringBoot整合Netty+Websocket实现消息推送的示例代码

    SpringBoot整合Netty+Websocket实现消息推送的示例代码

    WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据,本文主要介绍了SpringBoot整合Netty+Websocket实现消息推送的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01

最新评论