大家如果觉得我写的好,可以关注这个项目,之后我的学习过程中都会把学习笔记放入这个项目中。
https://github.com/IndustriousSnail/learning-notes

Spring Cloud Zuul服务网关

目录

一、服务网关简介

1.1 为什么要使用服务网关

假设,我们有许多微服务,商品、订单、用户等等。那么前端不可能为每一个服务单独配置地址,必须有一个统一的接口地址。 所以就需要使用服务网关作为这些服务的统一入口。

1.2 服务网关的要素

  1. 稳定行,高可用
  2. 性能,并发性
  3. 安全性
  4. 扩展性

作为所有服务的统一入口,如果它挂了,那所有的服务都挂了。所以这两点必须保证。所以这上面的都需要做到。

1.3 Zuul的特点

1.路由+过滤器=Zuul
2.核心是一系列的过滤器

1.4 Zuul中的HTTP请求生命周期

Spring Cloud Zuul服务网关

如图所示,Zuul中定义了四种标准过滤器:

1. 前置(Pre)
2. 后置(Post)
3. 路由(Route)
4. 错误(Error)

这四种过滤器靠RequestContext通信。

1. 当HTTP请求到达时,首先进入PreFilters(前置过滤器)。
2. 之后会经过RoutingFilter(路由过滤器)进行路由转发,分发给服务。
3. 最后服务响应HTTP请求之后,经过PostFilter(后置路由器)。
4. 如果上述过滤器发生异常时,会进入ErrorFilter.
5. customFilters(自定义过滤器)可以加载任何一个位置。

二、Zuul组件的使用

2.1 简单使用案例

1.新建Zuul项目,同样需要引入Eureka和Config依赖。 还有Zuul依赖。
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

2.在Application启动类上增加@EnableZuulProxy注解

@SpringBootApplication
@EnableZuulProxy   //开启网关服务
public class ZuulApplication {

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

3.启动项目。就可以使用网关访问其他服务的接口了。

比如,我们的网关端口是6080。 我们有一个服务order,他有一个接口test。
如果访问order的话是“localhost:8080/test”。那么使用网关访问则是:

localhost:6080/order/test

1.localhost为网关的地址。

2.6080为网关的端口。

3.order为要访问接口的服务的名称。

4./test为要访问的接口。

2.2 自定义路由

上面我们使用的是“服务的名称+服务的url”进行接口调用。如果要自定义路由规则,需要使用以下配置。
zuul:
  # 路由配置
  routes:
    # 自定义规则的规则名称
    myOrder:
      # 自定义的路由路径
      path: /myOrder/**
      # 要路由到的服务的名称
      serviceId: order
  # 简洁写法, order为要路由到的服务名称,后面是自定义的路由路径。
  #  order: /myOrder/**
  # 如果要禁止某个接口的外部调用,可以使用如下配置
  #  ignored-patterns:  #这个参数接受一个set<String>,String是一个正则表达式。具体写法如下
  #    - /order/test   # 禁止“/order/test”这个路径的访问
  #    - /myOrder/test 

之后使用下面地址同样可以访问到接口(之前的也可以使用)。

http://localhost:6080/myOrder/test

2.3 查看所有路由规则

1.增加配置,关闭安全限制。
management:
  security:
    enabled: false

2.访问routes接口

http://localhost:6080/routes   //低版本访问这个
http://localhost:6080/application/routes  //高版本访问这个

3.可以看到浏览器打印了如下内容

{
    /myOrder/**: "order",
    /config/**: "config",
    /order/**: "order"
}

前面的是路由规则,后面是服务名称。

2.4 Cookie的传递

如果使用了Zuul,那么Cookie是无法正常传递到Controller中的。 是因为Zuul默认对Http Header进行了敏感过滤。对应源码中的下列一段代码。
private Set<String> sensitiveHeaders = new LinkedHashSet<>(
		Arrays.asList("Cookie", "Set-Cookie", "Authorization"));

如果要解除Cookie的限制。或者增加敏感头的配置,需要对sensitiveHeaders进行配置。
比如,解除敏感头,只需要将sensitiveHeaders配置为空,如下:

zuul:
  # 路由配置
  routes:
    # 自定义规则的规则名称
    myOrder:
      # 自定义的路由路径
      path: /myOrder/**
      # 要路由到的服务的名称
      serviceId: order
      # 将该配置配置为空,不让其拦截Cookie。
      sensitiveHeaders:

三、自定义过滤器的使用

1.自定义过滤器,继承ZuulFilter类
@Component
public class CustomFilter extends ZuulFilter {  //继承抽象类ZuulFilter,并将其注入bean

    /**
     * 定义过滤器的类型。
     * @return 过滤器类型。可以包含"pre","post","route","error"四种。
     */
    @Override
    public String filterType() {
        //import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
        return PRE_TYPE;  //使用pre(前置过滤器)
    }

    /**
     * 定义过滤器的顺序。 数值越小越靠前。
     * 可以到“import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants”
     * 这个类下面查看其他系统过滤器的优先级。
     * @return 过滤器的优先级。值越小越先执行。
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * @return 是否启动该过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 处理逻辑
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("pre拦截器");
        RequestContext requestContext = RequestContext.getCurrentContext();//获取当前上下文
        HttpServletRequest httpServletRequest = requestContext.getRequest(); //获取HttpServletRequest
        //拿到HttpServletRequest之后,就可以做一些自己的处理逻辑
        //....处理逻辑
        //比如,我们校验url中是否含有token参数
        String token = httpServletRequest.getParameter("token");
        if(StringUtils.isEmpty(token)){
            //如果参数中没有token参数,则直接返回失败,不再转发到各个服务Controller。
            requestContext.setSendZuulResponse(false);  //设置发送Zuul响应为False。
            requestContext.setResponseStatusCode(401); //设置http状态码
        }
        //处理逻辑结束。
        return null;
    }
}

2.重启Zuul Server就行了。

相关文章: