本来该插件设想是非暴力修改,扩展方式重写 LoadBalancerRule 相关负载均衡器规则,但发现会有并发问题,所以这里暴力重写了LoadBalancerRule 相关类,以后时间允许的情况下再做调整与修改(不忘初心)
-
一般我们微服务调用是多层级的,比如 图1
-
这个时候,如果我们整个链条下的某个服务开发了新版本需要灰度发布,但是其他服务是正式版本, 比如 服务1 有个灰度版本需要上线 图2
-
如果我们 服务2 有灰度版本,如下 图3
-
或者所有服务都有灰度版本 图4
-
基本原理介绍完了,说一下细节,上面流程图中,服务3,没有调用下层服务了,相当于他是最底层服务【叶级服务】。 所以这个层级的服务,只需要设置 标识就行了,标注他是不是灰度服务,同时标注他的版本号, consul和eureka 设置方法不同。 同时不需要安装插件
-
对于服务2,服务1 整个调用链中间的服务,同样需要适应上面第5条,如果是灰度服务就需要标注灰度版本,同时需要安装插件。
-
由于 gateway 基于 netty+webflux,和zuul 核心原理不同,zuul 基于 Servlet 容器, 可以直接使用。但是gateway 有一个专属版本,以自己实现一个过滤器实现。
-
重点:核心原则,服务如果没有加入【版本标识】,该插件会识别成正式服务,如果有【版本标识】该插件会识别成灰度服务。 但是【正常请求】,如果访问下层服务没有正式服务,只有灰度服务的时候,不会调用,会报告异常,也就是说,整个调用链条所有服务必须要有正式服务, 当【灰度请求】,如果访问下层服务,下层服务有对应版本的灰度服务,会调用;如果没有对应版本的灰度服务,会调用正式版本服务,这样也就做到了 调用链当中部分【服务灰度发布的需求】
- 如何发起【灰度请求】呢,前端程序请求的时候,增加一个自定义头 version, 自定义头内容为版本号,这里的版本号会对应上面【第5条】提到 服务版本标识。注意哟,请求头的版本号要和服务的版本标识完全对应上哟,不然无法识别,会调用正式服务去,再啰嗦一句,正式服务不要加版本识
相关负载均衡规则请使用 com.labidc.gray.deploy.ribbon.rules 下的实现 跟官方一一对应
默认是 com.labidc.gray.deploy.ribbon.rules.GrayDeployZoneAvoidanceRule
如果有自己实现的规则请修改 setLoadBalancer 的 loadBalancer 为 com.labidc.gray.deploy.ribbon.GrayDeployILoadBalancerWrapper
- 添加tag
spring: cloud: consul: discovery: tags: - version=1.0.1
- maven添加依赖
<dependency> <groupId>com.labidc</groupId> <artifactId>labidc-gray-deploy-consul</artifactId> <version>${labidc-gray-deploy.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
- 【网关】, gateway, 由于gateway 基与webflux 使用Netty 作为容器, 所有有个专门为gateway实现的一个插件(注意该插件以来了consul,如果需要和eureka配合使用,请自行修改源码), 其他配置方法一样
<dependency> <groupId>com.labidc</groupId> <artifactId>labidc-gray-deploy-gateway</artifactId> <version>${labidc-gray-deploy.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
spring: cloud: gateway: discovery: locator: enabled: true routes: - id: gray_demo uri: lb://product-service-demo3 predicates: - Path=/test_service/** filters: - StripPrefix=1 - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback
- 添加元数据map
eureka: instance: metadata-map: version: 1.0.0
- maven添加依赖
<dependency> <groupId>com.labidc</groupId> <artifactId>labidc-gray-deploy-eureka</artifactId> <version>${labidc-gray-deploy.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
- 【网关】zuul2
# 路由规则配置 zuul: #忽略所有默认服务配置 ignored-services: "*" routes: product-provider: # 这个设置非常关键,要手动设置敏感的请求header, 否则所有请求头都会被过滤,这样设置 # 主要是为了放行version请求头 sensitive-headers: Cookie,Set-Cookie,Authorization # 路由请求前缀 gray_service path: /gray_service/** # 取消掉gray_service 访问到后端服务 stripPrefix: true serviceId: product-service-demo1
添加maven 配置
<dependency> <groupId>com.labidc</groupId> <artifactId>labidc-gray-deploy-eureka</artifactId> <version>${labidc-gray-deploy.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
调用链记录服务版本加入依赖
<dependency> <groupId>com.labidc</groupId> <artifactId>labidc-gray-deploy-zipkin</artifactId> <version>${labidc-gray-deploy.version}</version> </dependency>
当前请求的 header/attribute 需要传递到下游服务
注意
- 向下游服务的请求中已有的header不会被配置覆盖
- attribute 会转换为 header 传递到下游服务
- 优先等级 原有 header > header > attribute
- attribute 默认传递 String 和 基本类型 对象需要实现接口 HeadTransmitAttributeObjectTransform 并 注册为bean
spring: gray: deploy: transmit: headers: - header1 - header2 attributes: - attribute1 - attribute2