zoukankan      html  css  js  c++  java
  • 微服务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

    然后每隔一段时间同步配置表中的信息,也就是写个定时任务。

  • 相关阅读:
    HTML元素解释
    Java命名规范
    HDU 1058 Humble Numbers(DP,数)
    HDU 2845 Beans(DP,最大不连续和)
    HDU 2830 Matrix Swapping II (DP,最大全1矩阵)
    HDU 2870 Largest Submatrix(DP)
    HDU 1421 搬寝室(DP)
    HDU 2844 Coins (组合背包)
    HDU 2577 How to Type(模拟)
    HDU 2159 FATE(二维完全背包)
  • 原文地址:https://www.cnblogs.com/java-spring/p/13397270.html
Copyright © 2011-2022 走看看