Spring Cloud 简单灰度发布

需求

新建三个项目:

  • demo-server 服务端
  • demo-client 客户端
  • demo-gateway 网关层

现在希望可以根据用户请求调用不同版本的代码,如下所示

gateway -> client(v1版本) -> server(v1版本)
        -> client(v2版本) -> server(v2版本)

分析

可知,gateway项目和client项目,需要我们根据不同参数来干涉负载分发。Spring Cloud是使用ribbon作为负载均衡,这里我们引入如下pom依赖:

<dependency>
    <groupId>io.jmnarloch</groupId>
    <artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId>
    <version>2.1.0</version>
</dependency>

GitHub:https://github.com/jmnarloch/ribbon-discovery-filter-spring-cloud-starter

其原理是通过匹配请求里面的路由参数与Eureka注册中心上实例配置的metadata里面的参数值,如果都匹配上了,才选择该实例节点。

实现

gateway项目

AccessFilter extends ZuulFilter的run方法中增加如下代码:

RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
//灰度示例
RibbonFilterContextHolder.clearCurrentContext();
String version = request.getHeader("dispatch-version");

if (version != null && !"".equals(version)) {
    RibbonFilterContextHolder.getCurrentContext().add("dispatch-version", version);
}

注意:gateway项目记得配置zuul.routes.client-api.sensitiveHeaders=Cookie,Set-Cookie,Authorization

client项目

新增WebMvcConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);
        registry.addInterceptor(new VersionInterceptor());
    }

}

新增VersionInterceptor

import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class VersionInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        RibbonFilterContextHolder.clearCurrentContext();
        String version = request.getHeader("dispatch-version");
        if (version != null && !"".equals(version)) {
            RibbonFilterContextHolder.getCurrentContext().add("dispatch-version", version);
        }

        return true;
    }
}

application.yml里增加:

eureka:
  instance:
    metadata-map:
      dispatch-version: v1

server项目

application.yml里增加:

eureka:
  instance:
    metadata-map:
      dispatch-version: v1

验证

  • 启动gatewayclientserver项目
  • 模拟请求在header里面设置dispatch-version=v1,发现访问正常,如果把dispatch-version改成v2,发现访问不了
  • 这时,修改clientserver项目的端口,并且dispatch-version改成v2,再启动新实例,这时再模拟请求dispatch-version=v2,发现访问正常。
  • 来回修改dispatch-version的值,发现v1的请求只会访问v1版本,v2的请求只会访问v2版本。至此,灰度发布的demo已验证成功。
上一篇 互联网产品的3种发布策略
下一篇 Spring Cloud Gray 3.0 灰度解决方案
目录
文章列表
1 url参数和map之间的转换
url参数和map之间的转换
2
Android测试(8):UI Automator自动化测试
Android测试(8):UI Automator自动化测试
3
Python 3.8下载安装pycrypto报错解决
Python 3.8下载安装pycrypto报错解决
4
通过javax.validation.constraints下的注解实现字段验证
通过javax.validation.constraints下的注解实现字段验证
5
Vue全局Filter体验
Vue全局Filter体验
最新评论
一位WordPress评论者
一位WordPress评论者
2月12日
您好,这是一条评论。若需要审核、编辑或删除评论,请访问仪表盘的评论界面。评论者头像来自 Gravatar。