Spring Cloud Zuul API 网关服务

API 网关是一个更为智能的应用服务器,它的定义类似于面向对象设计模式中的 Facade 模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤。它除了要实现请求路由负载均衡校验过滤等功能之外, 还需要更多能力比如与服务治理框架的结合、请求转发时的熔断机制服务聚合等一系列高级功能。Spring Cloud 中了提供了基于 Netflix Zuul 实现的 API 网关组件 Spring Cloud Zuul。

对于服务实例的维护间题,Spring Cloud Zuul 通过与 SpringCloud Eureka 进行整合,将自身注册为Eureka 服务治理下的应用,同时从 Eureka 中获得了所有其他微服务的实例信息。这样的设计非常巧妙地将服务治理体系中维护的实例信息利用起来,使得将维护服务实例的工作交给了服务治理框架自动完成,不再需要人工介入。

对于路由规则的维护问题,Zuul 默认会以服务名作为 ContextPath 的方式来创建路由映射,大部分情况下,这样的默认设置已经可以实现大部分的路由需求,除了一些特殊情况(比如兼容一些旧的 URL)还需要做一些特别的配置。

对于类似签名校验、登录校验在微服务架构中的冗余问题。理论上来说,这些校验逻辑在本质上与微服务应用自身的业务并没有多大的关系,所以它们完全可以独立成一个单独的服务存在,只是它们被剥离和独立出来之后,并不是给各个微服务调用,而是在 API 网关服务上进行统一调用来对微服务接口做前置过滤,以实现对微服务接口的拦截和校验。

Spring Cloud Zuul 提供了一套过滤器机制,它可以很好地支持这样的任务。开发者可以通过使用 Zuul 来创建各种校验过滤器,然后指定哪些规则的请求需要执行校验逻辑,只有通过校验的才会被路由到具体的微服务接口,否者就返回错误提示。 通过这样的改造,各个业务层的微服务应用就不再需要非业务性质的校验逻辑了,这使得微服务应用可以更专注于业务逻辑的开发,同时微服务的自动化测试也变得更容易实现。

微服务架构虽然可以将开发单元拆分得更为细致,有效降低了开发难度,但是它所引出的各种问题如果处理不当会成为实施过程中的不稳定因素,甚至掩盖掉原本实施微服务带来的优势。所以,在微服务架构的实施方案中,API网关服务的使用几乎成为必然的选择。

API网关对微服务架构的重要性

  • 作为系统的统一入口,屏蔽了系统内部各个微服务的细节。
  • 与服务治理框架结合,实现自动化的服务实例维护以及负载均衡的路由转发
  • 实现接口权限校验与微服务业务逻辑的解耦
  • 通过服务网关中的过滤器,在各生命周期中去校验请求的内容,将原本在对外服务层做的校验前移,保证了微服务的无状态性,同时降低了微服务的测试难度,让服务本身更集中关注业务逻辑的处理。

请求路由

传统路由方式

传统路由的映射方式 API 网关根据请求的 URL 路径找到最匹配的 path 表达式,直接转发给该表达式对应的 url 或对应 serviceId 下配置的实例地址,以实现外部请求的路由。

在不依赖服务发现机制的情况下,通过在配置文件中具体指定每个路由表达式与服务实例的映射关系来实现 API 网关对外部请求的路由。

传统路由的配置方式并不友好,它需要运维人员花费大量的时间来维护各个路由 path 与 url 的关系 。

面向服务的路由

通过面向服务的路由配置方式,不需要再为各个路由维护微服务应用的具体实例的位置,而是通过简单的 path 与serviceld(服务名) 的映射组合,使得维护工作变得非常简单。 这归功于 Spring Cloud Eureka 的服务发现机制,它使得 API 网关服务可以自动化完成服务实例清单的维护,完美地解决了对路由映射实例的维护问题。

可以直接将 API 网关也看作 Eureka 服务治理下的一个普通微服务应用。它除了会将自己注册到 Eureka 服务注册中心上之外,也会从注册中心获取所有服务以及它们的实例清单。所以在 Eureka 的帮助下,API 网关服务本身就已经维护了系统中所有 serviceId 与实例地址的映射关系。当有外部请求到达 API 网关的时候,根据请求的 URL 路径找到最佳匹配的 path 规则,API 网关就可以知道要将该请求路由到哪个具体的 serviceId上去。由于在 API 网关中已经知道 serviceId 对应服务实例的地址清单,只需要通过 Ribbon 的负载均衡策略,直接在这些清单中选择一个具体的实例进行转发就能完成路由工作。

扫描二维码关注公众号,回复: 10908891 查看本文章

服务路由的默认规则

默认情况下,为 Spring Cloud Zuul 构建的 API 网关服务引入 Spring Cloud Eureka 之后,Zuul 为 Eureka 的每个服务都自动创建一个默认路由规则,这些默认规则的 path 会使用 serviceId 配置的服务名作为请求前缀。

路径匹配

不论是使用传统路由的配置方式还是服务路由的配置方式,都需要为每个路由规则定义匹配表达式,也就是 path参数。

当使用通配符的时候,经常会碰到这样的问题:一个 URL 路径可能会被多个不同路由的表达式匹配上。Zuul 的路由匹配算法中,在使用路由规则匹配请求路径的时候是通过线性遍历的方式,在请求路径获取到第一个匹配的路由规则之后就返回并结束匹配过程。 所以当存在多个匹配的路由规则时,匹配结果完全取决于路由规则的保存顺序。路由规则通过 LinkedHashMap 保存,也就是说,路由规则的保存是有序的,而内容的加载是通过遍历配置文件中路由规则依次加入的。由于 properties 的配置内容无法保证有序,所以当出现这种情况的时候,为了保证 路由的优先顺序,需要使用 YAML 文件来配置,以实现有序的路由规则。

:properties 的配置内容为什么无法保证有序?因为 Properties 继承自 Hashtable,而 Hashtable 是无序的,不保证进出顺序。

请求过滤

为了实现对客户端请求的安全校验和权限控制,最简单和粗暴的方法就是为每个微服务应用都实现一套用于校验签名和鉴别权限的过滤器或拦截器。不过,这样的做法并不可取,它会增加日后系统的维护难度,因为同一个系统中的各种校验逻辑很多情况下都是大致相同或类似的,这样的实现方式会使得相似的校验逻辑代码被分散到了各个微 服务中去,冗余代码的出现是我们不希望看到的。

所以比较好的做法是将这些校验逻辑剥离出去,构建出一个独立的鉴权服务。在完成了剥离之后,有不少开发者会直接在微服务应用中通过调用鉴权服务来实现校验,但是这样的做法仅仅只是解决了鉴权逻辑的分离,并没有在本质上将这部分不属于冗余的逻辑从原有的微服务应用中拆分出,冗余的拦截器或过滤器依然会存在。

对于这样的问题,更好的做法是通过前置的网关服务来完成这些非业务性质的校验。 由于网关服务的加入,外部客户端访问系统已经有了统一入口, 既然这些校验与具体业务无关,那何不在请求到达的时候就完成校验和过滤,而不是转发后再过滤而导致更长的请求延迟。同时,通过在网关中完成校验和过滤,微服务应用端就可以去除各种复杂的过滤器和拦截器了,这使得微服务应用接口的开发和测试复杂度也得到了相应降低。Zuul 允许开发者在 API 网关上通过定义过滤器来实现对请求的拦截与过滤,实现的方法非常简单,只需继承 ZuulFilter 抽象类并实现它定义的 4 个抽象函数即可。

Cookie与头信息

默认情况下 Spring Cloud Zuul 在请求路由时,会过滤掉 HTTP 请求头信息中的一些敏感信息,防止它们被传递到下游的外部服务器。默认的敏感头信息通过 zuul.sensitiveHeaders 参数定义,包括 CookieSet-CookieAuthorization 三个属性。所以在开发 Web 项目时常用的 Cookie 在 Spring Cloud Zuul 网关中默认是不会传递 的,这就会引发 一个常见的问题:如果要将已经使用了 Spring Security、Shiro 等安全框架构建的 Web 应用通过Spring Cloud Zuul 构建的网关来进行路由时,由于 Cookie 信息无法传递,Web应用将无法实现登录和鉴权。可以通过指定路由的参数配置来解决这个问题。

不推荐通过设置全局参数为空来覆盖默认值的方法,虽然可以实现 Cookie 的传递,但是破坏了默认设置的用意。在微服务架构的 API 网关之内,对于无状态的 RESTful API 请求肯定是要远多于这些 Web 类应用请求的,甚至还有一些架构设计会将 Web 类应用和 App 客户端一样都归为 API 网关之外的客户端应用。

Hystrix 和 Ribbon 支持

spring-cloud-starter-zuul 依赖包含了 spring-cloud-starter-hystrix 和 spring-cloud-starter-ribbon 模块的依赖,所以 Zuul 天生就拥有线程隔离和断路器的自我保护功能,以及对服务调用的客户端负载均衡功能。但要注意,当使用 path 与 url 的映射关系来配置路由规则的时候,对于路由转发的请求不会采用 HystrixCommand 来包装,所以这类路由请求没有线程隔离和断路器的保护,并且也不会有负载均衡的能力。因此在使用 Zuul 的时候尽量使用 path 和 serviceId 的组合来进行配置,这样不仅可以保证API网关的健壮稳定,也能用到 Ribbon 的客户端负载均衡功能。

参考:

《Spring Cloud 微服务实战》翟永超 著

发布了66 篇原创文章 · 获赞 151 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/siriusol/article/details/105586406