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

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

  • 相关阅读:
    怎样运用Oracle的BFILE
    第一个博客
    返回引用的函数
    c++之SQLite的增删改查
    sqlite命令行程序说明
    CreateProcess函数详解
    注册窗口类
    radio button的用法
    跨线程使用CSocket
    关于socket的connect超时的问题
  • 原文地址:https://www.cnblogs.com/java-spring/p/13397270.html
Copyright © 2011-2022 走看看