自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

你好呀,我是小羊。

工作中经常要涉及到功能发布,这个时候也经常是业务系统最有可能遇到问题的时候,需要要尽量减少发布引起的风险。比如在系统负载比较小的时候使用。还有蓝绿发布、灰度发布等等,今天介绍一下这几种常见的发布,并使用springcloud 实现。

1.传统发布方式

一个系统最初的时候,使用量小,用户少,系统也是单体架构,有时候连系统挂了都没有人发现,这个时候常见的上线新功能就是替换包,然后重启服务。

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

这种方式最简单,也最方便,适合很多小型项目,但是也有一定的缺陷,在服务发布的过程中。系统是不能对外提供服务的。最严重的问题是,如果新功能发布失败,可能会导致长时间不可用。所以为了尽量减少在发布的过程中对用户的影响。提升系统的可用性。我们需要引入更好的发布方法。

2.常见的发布方式

我们在工作中经常遇到这种问题,一个新功能在测试环境运行的很好,测试也测了好几遍都是正常的,但是在生产环境一部署就不行了,不是启动失败,就是功能逻辑不对。这个是由于环境的差异造成的。毕竟生产环境很复杂,用的人也多。为了减少这种情况对业务系统的影响,我们可以引入蓝绿发布。

蓝绿发布

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

蓝绿发布的流程如上图所示,我们把生产环境的系统分为2部分,1套绿环境,1套蓝环境,绿环境是线上正在运行的v1版本,我们现在要发布新的v2版本,具体的操作如下:

  1. 生产的所有用户的流量都切换为绿环境,不经过蓝环境。
  2. 蓝环境的版本升级为v2,然后让测试测试蓝环境的功能。
  3. 确定蓝环境没有功能问题时,可以先将少部分生产的流量切到蓝环境。运行正常后,将所有的生产流量切换为蓝环境。
  4. 将绿环境的版本升级为v2。再将所有的生产的流量都切换为绿环境,至此,发布完成。

不像之前的直接发布方式,蓝绿发布可以解决大部分因为发布新功能导致的问题。测试也有条件去测试生产环境的功能了,在测试的过程中不用担心新功能对生产用户造成的影响。

优点:

  • 升级过程无需停机,用户感知小
  • 升级过程一半资源提供服务
  • 升级/回滚速度快

缺点:

  • 如果出了问题,影响面较广

蓝绿发布中,如果业务在测试生产环境没有发现问题,等到完全升级完成之后才发现问题,比如多发了优惠券,接口有bug等等,这个时候对系统的影响就很大了。为了尽量减少这种情况的影响。我们可以使用灰度发布。

灰度发布

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

灰度发布也叫金丝雀发布。

金丝雀发布由来:以前矿工开矿,在下矿洞前需要检查下方是否有毒气,矿工们先会放一只金丝雀进去探是否有毒气体,看金丝雀能否活下来。

灰度发布(金丝雀发布)主要是为了减少发布过程中的问题对用户的影响,主要流程如上图所示,如果要发布v2版本,先发布一部分节点,导入一部分生产环境的流量,然后再逐步增加,如果发现问题,可以及时修复,这样在发布过程中的问题,可以尽量少的影响用户体验。

优点:

  • 风险控制:灰度发布可以降低新版本引入生产环境时的风险。通过逐步引入新功能,团队可以更容易地发现和解决潜在的问题,而不会对整个用户群体造成影响。
  • 反馈循环:通过逐步引入新版本,团队可以及时获取用户反馈,从而更好地了解新功能的表现和用户体验。这有助于及时调整和改进新功能。
  • 逐步推广:灰度发布允许团队逐步将新版本引入到整个用户群体中,从而更好地控制资源和性能的负载。这有助于避免突然的流量激增和性能问题。

缺点:

  • 部署复杂性:灰度发布需要更复杂的部署和管理流程。需要确保新版本可以与旧版本和灰度版本共存,并且需要确保灰度流量的正确路由和控制。
  • 增加开发时间:由于需要逐步引入新版本,灰度发布可能会增加整个发布周期的时间。这可能会对产品的快速迭代和更新速度产生影响。
  • 管理成本:灰度发布需要更多的管理和监控成本,包括对不同版本的流量和性能进行监控,以及对灰度发布过程中的问题进行跟踪和解决。

3. 蓝绿灰度发布的实现

现在主流的微服务接口调用为springcloud + nacos,下面我以这个技术栈来实现一下动态的蓝绿发布和灰度发布。

主要的技术点有以下:

  1. 如何标记服务为蓝绿环境

服务标记可以利用nacos的元数据 metadata:

spring:
  application:
    name: provider1
  cloud:
    nacos:
      discovery:
        # nacos 注册地址
        server-addr: localhost:8848
        # nacos 元数据,标记版本和环境
        metadata:
          version: green-v1
      config:
        server-addr: localhost:8848
server:
  port: 8001

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码
  1. 如何获取不同环境的服务 springcloud 可以通过 继承 DelegatingServiceInstanceListSupplier 类来获取某个服务上面注册中心的所有节点,然后可以通过 nacos 的元数据进行过滤,这样就可以区分蓝绿环境的服务了。

获取注册的服务列表:

Flux<List<ServiceInstance>> listFlux = delegate.get(request);

根据消费者的环境来获取生产者的环境:

private List<ServiceInstance> filteredByVersion(List<ServiceInstance> instances, String version) {

        for (ServiceInstance instance : instances) {
            log.info("==> 服务:[{}]在注册中心的实例信息:[{}]", getServiceId(), writeValueAsString(instance));
        }

        // 1、获取 请求头中的 version 和 ServiceInstance 中 元数据中 version 一致的服务
        List<ServiceInstance> selectServiceInstances = instances.stream()
                .filter(instance -> instance.getMetadata().get(VERSION_HEADER_NAME) != null
                        && Objects.equals(version, instance.getMetadata().get(VERSION_HEADER_NAME)))
                .collect(Collectors.toList());
        if (!selectServiceInstances.isEmpty()) {
            log.info("返回请求服务:[{}]为version:[{}]的有:[{}]个", getServiceId(), version, selectServiceInstances.size());
            for (ServiceInstance instance : selectServiceInstances) {
                log.info("==> 服务:[{}]根据version过滤选择实例信息:[{}]", getServiceId(), writeValueAsString(instance));
            }
            return selectServiceInstances;
        }

        // 2、返回 version=default 的实例
        selectServiceInstances = instances.stream()
                .filter(instance -> Objects.equals(instance.getMetadata().get(VERSION_HEADER_NAME), "default"))
                .collect(Collectors.toList());
        log.info("返回请求服务:[{}]为version:[{}]的有:[{}]个", getServiceId(), "default", selectServiceInstances.size());
        for (ServiceInstance instance : selectServiceInstances) {
            log.info("==> 服务:[{}]根据version过滤选择实例信息:[{}]", getServiceId(), writeValueAsString(instance));
        }

        if (!selectServiceInstances.isEmpty()) {
            log.info("返回请求服务:[{}]为version:[{}]的有:[{}]个", getServiceId(), version, selectServiceInstances.size());
            for (ServiceInstance instance : selectServiceInstances) {
                log.info("==> 服务:[{}]根据version过滤选择实例信息:[{}]", getServiceId(), writeValueAsString(instance));
            }
            return selectServiceInstances;
        }

        return instances;
    }

从请求头中获取version 字段来确定版本,实际生产中可以根据自己的需求来确定规则,比如根据用户账号进行hash。

public void apply(RequestTemplate requestTemplate) {
        String version = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest()
                .getHeader("version");
        log.info("feign 中传递的 version 请求头的值为:[{}]", version);
        requestTemplate
                .header("version", version);
    }

请求蓝环境v2接口进行测试:

wget --no-check-certificate --quiet 
  --method GET 
  --timeout=0 
  --header 'version: blue-v2' 
   'http://localhost:7001/consumer/consumer1/test1'

调用结果:

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

请求绿环境v1接口进行测试:

wget --no-check-certificate --quiet 
  --method GET 
  --timeout=0 
  --header 'version: green-v1' 
   'http://localhost:7001/consumer/consumer1/test1'

调用结果:

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

灰度发布的原理类似,不同的地方是灰度发布需要逐步切换生产流量到新版本,可以通过nacos 修改服务的权重来实现。

4. 代码地址

springcloud nacos 实现蓝绿发布,灰度发布
https://gitee.com/yangzheng1/springcloud-deploy

5. 往期精彩推荐


  国内免费使用chatGPT的方法

数据库实时同步方案

推荐一款开源的大屏报表项目

欢迎点赞转发给我鼓励~

自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码关注我获取更多IT分享 自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

原文始发于微信公众号(小羊架构):自从有了蓝绿发布和灰度发布,再也不用担心发布事故了,附源码

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/260126.html

(0)
Java朝阳的头像Java朝阳

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!