spring cloud灰度發布

灰度發布、藍綠發布、金絲雀發布各是什么意思,可以看這篇http://www.appadhoc.com/blog/product-release-strategy/

新建三個項目:

  • 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>

他的原理是通過匹配 請求里面的路由參數與eureka注冊中心上實例配置的metadata里面的參數值,如果都匹配上了,才選擇該實例節點。

代碼修改

1、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

2、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

3、server項目
在application.yml里增加:

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

驗證

啟動gateway,client,server項目,
模擬請求在header里面設置dispatch-version=v1,發現訪問正常,如果把dispatch-version改成v2,發現訪問不了
這時,修改client和server項目的端口,并且dispatch-version改成v2,再啟動新實例,這時再模擬請求dispatch-version=v2,發現訪問正常了。
來回修改dispatch-version的值,發現v1的請求只會訪問v1版本,v2的請求只會訪問v2版本。至此,灰度發布的demo已驗證成功。

參考githup上的開源項目jmnarloch

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容