1. 程式人生 > 實用技巧 >Zuul閘道器進行灰度釋出

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

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