微服務Zuul網關進行灰度發布


微服務中,新版服務上線的時候,為了保證不出什么問題,可以將少量的請求轉發到新的服務上,然后其他的請求還是轉發到舊的服務上去,等線上的新服務測試通過以后,就可以重新平均分配請求。這種功能就稱為灰度發布。

 

要完成灰度發布,要做的就是修改ribbon的負載均衡策略,通過一些特定的標識,比如我們針對某個接口路徑/gray/publish/test。將10%的請求轉發到新的服務上,將90%的請求轉發到舊的服務上,諸如此類,我們可以制定各種規則進行灰度測試。

 

在微服務中,我們可以通過eureka的metamata進行自定義元數據,然后來修改ribbon的負載均衡策略。

 

在此,可以先通過代碼進行簡單地灰度發布,在實際應用中,可以通過數據庫配置進行灰度靈活發布。

 

首先,我們如果要部署新版的服務user-server,我們用不同的端口啟動這個服務,並配置不同的自定義元數據,配置如下:

server: port: 8181
#Eureka注冊配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
  instance:
    metadata-map:
      forward: 1
server: port: 8182
#Eureka注冊配置
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
  instance:
    metadata-map:
      forward: 2

我們啟動了8181和8182兩個服務,並分別定義了元數據forward: 1forward: 2,然后,開始修改zuul網關,首先導入修改ribbon負載均衡策略的依賴

<!-- 修改Zuul的負載均衡策略,也就是進行灰度發布使用的 -->
        <dependency>
            <groupId>io.jmnarloch</groupId>
            <artifactId>ribbon-discovery-filter-spring-cloud-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

然后,開始修改ribbon的負載均衡策略

package com.dkjk.gateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jmnarloch.spring.cloud.ribbon.support.RibbonFilterContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.*;

/**
 * @author: qjc
 * @createTime: 2020/7/29
 * @Description: 接口安全驗證過濾器
 */
@Component
@Slf4j
public class ValidFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        // 進行跨域請求的時候,並且請求頭中有額外參數,比如token,客戶端會先發送一個OPTIONS請求來探測后續需要發起的跨域POST請求是否安全可接受
        // 所以這個請求就不需要攔截,下面是處理方式
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            log.info("OPTIONS請求不做攔截操作");
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String requestURI = request.getRequestURI();
        if (requestURI.contains("/gray/publish/test")){
            int send = (int) (Math.random() * 100);
            if (send >= 0 && send < 10) {
                //也就是百分之10的請求轉發到forward=1的服務上去
                RibbonFilterContextHolder.getCurrentContext().add("forward", "1");//這句話就代表將請求路由到metadata-map里forward為1的那個服務
            } else {
                //百分之90的請求轉發到forward=2的服務上去
                RibbonFilterContextHolder.getCurrentContext().add("forward", "2");//這句話就代表將請求路由到metadata-map里forward為2的那個服務
            }
        }
        return null;
    }
}

接下來就可以測試接口/gray/publish/test的轉發情況了,結果就是10%的請求轉發到了8181上(即forward為1的服務上),90%的請求轉發到了8182(即forward為2的服務上)

PS:在生產上使用的時候,可以通過創建數據庫表來動態配置負載均衡策略,比如創建一張數據表:

CREATE TABLE `gray_release_config` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `server_name` varchar(255) DEFAULT NULL, //服務名
   `path` varchar(255) DEFAULT NULL,//需要進行灰度發布的接口路徑
     `percent` int(11) DEFAULT NULL,//負載均衡策略,百分之percent的請求轉發到forward上
   `forward` int(11) DEFAULT NULL,//自定義元數據值
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8

然后每隔一段時間同步配置表中的信息,也就是寫個定時任務。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM