Zuul简介

  Zuul网关是将一个业务系统内部的多个微服务进行封装,对外提供唯一访问入口,实现系统内高内聚,系统间通过网关交互达到松耦合的效果。它可以和Eureka、Ribbon、Hystrix等组件配合使用,实现身份认证与安全、审查与监控、动态路由、压力测试、负载均衡、流量控制等功能。本文基于上篇(SpringCloud系列——Ribbon 负载均衡)实现Zuul动态路由。

Zuul作为路由网关组件,在微服务架构中有着非常重要的作用,主要体现在下面6各方面:

  • Zuul、Ribbon、以及Eureka相结合,可以实现智能路由和负载均衡的功能,Zuul能够将请求流量按某种策略分发到集群状态的多个实例。
  • 网关将所有服务的API接口统一聚合,并统一对外暴露。外界系统调用API接口时都是由网关对外暴露的API接口,外界系统不需要知道微服务系统中各系统相互调用的复杂性。微服务系统夜保护了其内部微服务单元的API接口,防止被外界直接调用,导致服务的敏感信息对外暴露。
  • 网关服务可以做用户身份认证和权限认证,防止非法请求操作API接口,对服务起到保护作用。
  • 网关可以实现监控功能,实时日志输出,对日志进行记录。
  • 网关可以用来实现流量监控,在高流量的情况下对服务进行降级。
  • API接口从内部服务分离出来,方便做测试。

  GitHub地址:https://github.com/Netflix/zuul

  官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-netflix/2.1.0.RC2/single/spring-cloud-netflix.html#_router_and_filter_zuul

代码编写

  首先我们在springCloud下面新建一个springboot项目:zuul-server,pom继承parent,并且在Eureka上面注册(关于Eureka相关操作可参考:SpringCloud系列——Eureka 服务注册与发现

springgateway动态路由 spring cloud zuul 动态路由_微服务

 

 

   maven引入Zuul

<!-- Zuul -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>

配置文件

server.port=10010
spring.application.name=zuul-server
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
#健康检查(需要spring-boot-starter-actuator依赖)
eureka.client.healthcheck.enabled=true
# 续约更新时间间隔(默认30秒)
eureka.instance.lease-renewal-interval-in-seconds=10
# 续约到期时间(默认90秒)
eureka.instance.lease-expiration-duration-in-seconds=10

#zuul代理配置  zuul.routes.服务名.path,服务名要与注册的一致
#应用名映射
zuul.routes.myspringboot.path=/myspringboot/**
zuul.routes.myspringboot.service-id=myspringboot

#URL映射
#zuul.routes.myspringboot.path=/myspringboot/**
#zuul.routes.myspringboot-url.url=http://localhost:10087/

自定义Zuul过滤器,更多的检查规则后续慢慢健全

/**
 * Zuul过滤器,实现了路由检查
 */
public class AccessFilter extends ZuulFilter {

    /**
     * 通过int值来定义过滤器的执行顺序
     */
    @Override
    public int filterOrder() {
        // PreDecoration之前运行
        return PRE_DECORATION_FILTER_ORDER - 1;
    }

    /**
     * 过滤器的类型,在zuul中定义了四种不同生命周期的过滤器类型:
     *     public static final String ERROR_TYPE = "error";
     *     public static final String POST_TYPE = "post";
     *     public static final String PRE_TYPE = "pre";
     *     public static final String ROUTE_TYPE = "route";
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 过滤器的具体逻辑
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        System.out.println(String.format("%s AccessFilter request to %s", request.getMethod(),request.getRequestURL().toString()));
        String accessToken = request.getParameter("accessToken");
        //有权限令牌
        if (!StringUtils.isEmpty(accessToken)) {
            ctx.setSendZuulResponse(true);
            ctx.setResponseStatusCode(200);
            //可以设置一些值
            ctx.set("isSuccess", true);
            return null;
        } else {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody("{\"result\":\"accessToken is not correct!\"}");
            //可以设置一些值
            ctx.set("isSuccess", false);
            return null;
        }
    }

    /**
     * 返回一个boolean类型来判断该过滤器是否要执行
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }
}

启动类,添加@EnableZuulProxy注解并使用自定义过滤器

@EnableZuulProxy
@SpringBootApplication
public class ZuulServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulServerApplication.class, args);
    }

    @Bean
    public AccessFilter accessFilter() {
        return new AccessFilter();
    }
}

效果演示

  启动所有项目,我们在Eureka上注册了四个服务,相比上篇(SpringCloud系列——Ribbon 负载均衡)多了一个Zuul

springgateway动态路由 spring cloud zuul 动态路由_spring_02

 

 

浏览器访问 http://localhost:10010/service-a/ribbon、http://localhost:10010/service-a/ribbon?accessToken=123456

  http://localhost:10010/ 这个端口对外暴露,相对于总入口,后面接不同的路径由,Zuul路由到对应的服务上

  1、没有accessToken是,无法通过检查

  2、携带accessToken时,可正常路由,并且Feign调用、Ribbon负载均衡

springgateway动态路由 spring cloud zuul 动态路由_springgateway动态路由_03

 

后续操作

待更新。。。