统一网关服务
概述
微服务架构中,后端的各个服务都是可以独立运行的小型应用。在对外提供接口服务时,如果还是按照各个应用独立的方式提供,就好比是多个独立运行的单体系统,不仅失去了微服务架构的意义,而且还提升了管理和使用的复杂度。
微服务网关的作用,就是为后端服务提供一个统一的出入口。后端所有所服务的接口通过网关对外提供服务,就像单体系统中的 核心控制器 一样,拦截所有的请求。并集合服务发现机制,最终将请求分发至指定的服务。
注意
虽说网关是重要的安全防护措施,但是仅靠网关无法达到生产级的防护的。部署至生产环境时,还需要很多其它的安全防护措施,常见的措施例如:
- 在服务器级别做访问控制,限制其它服务的外部直接访问。(如果外部可以直接访问后端服务,网关就失去了作用)
- 在网关服务之前,增加反向代理措施,例如:Nginx 等,避免直接通过IP访问网关,特别时涉及到允许公网访问的场景
- 部署服务器的安全加固等其它安全管控措施
[一]网关动态路由
服务网关拦截到请求之后,将请求转发至对应的服务,就叫做网关路由。网关路由是需要配合服务发现机制才能正常运行的,即通过请求中的指定映射,找到对应的服务。
通常网关路由有两种管理方式:静态路由和动态路由。
- 静态路由:手动在网关服务的配置文件中,配置好具体的映射以及相关配置。这种方式灵活性比较高,可以针对不同的服务进行个性化的定制。但是问题也比较突出,一旦需要修改就需要重启网关服务,对整体的运行产生影响。
- 动态路由:无需在配置文件中进行配置,利用 Spring Cloud 以及生态组件提供的动态能力,动态生成路由。这种方式可能对于服务的个性化定制不够方便,但是对于整体的运行维护来说性价比更高。
Dante Cloud 默认采用的就是动态路由方式,只要服务正常启动并且成功注册到服务注册中心,通过服务名就可以实现请求的转发,无需其它的额外配置。当然,如果你有特殊的
[二]网关轻量级鉴权
[1]背景知识
不管是微服务系统还是单体系统,API 接口的鉴权都是必不可少的安全保障措施。这里,我们不妨先对单体架构和微服务架构中,接口鉴权的相同点与不同点,做一个简单的分析。
虽然,还没有详细介绍微服务架构的的鉴权逻辑,但是凭借我们个人的经验,完全可以做这个分析。
- 相同点:不管哪种架构,都会存在自己的接口(REST API),然后通过某种权限框架或者自研的权限体系进行鉴权。
- 不同点:单体架构就自身一个应用,自己的接口(REST API)自己来鉴权即可。微服务架构是由多个服务组合而成,也一定存在一个地方或者组件对接口(REST API)进行鉴权,但是具体放在哪里、怎么实现会有很大的不同。
继续分析一下,即使没有微服务应用设计和开发经验,也可以想到,要么就是在一个服务中统一进行接口的鉴权,要么就是每个服务自己负责自身接口的接口的鉴权。
而实际的微服务架构鉴权设计中,常见的模式也就是两种:
- 方案一,资源提供服务各自鉴权:这种模式下,对外提供接口的服务(OAuth 2 中的资源服务器),自己对自己的接口进行保护。
- 方案二,服务网关统一认证鉴权:微服务架构中一般都会有微服务网关,比如 Spring Cloud Gateway,作为请求的统一入口,来实现对接口的统一保护。因为是统一入口,那么在网管进行接口的鉴权,就是一个不二的选择。
方案二,就是很多产品宣传的
网关统一鉴权
[2]方案选择
Dante Cloud 的鉴权方案选择的是前面所说的 方案一,即由各个服务负责自身 REST 接口的鉴权。之所以选择这个方案,主要由以下几个原因:
- 因为系统使用的是 Spring Security 生态,而 Spring Security 自身的机制和推荐方式,就是由各个服务自身负责自己接口的鉴权
- 个人观点认为:
网关统一鉴权并不是一个合理的方式- 因为如果要实现网关统一鉴权,势必需要在网关服务中增加更多的管理功能,管理功能的增加就意味着关键数据在“网关”层面的暴露。这不仅弱化了网关保护措施的定位,反而需要更多保护措施来保护网关服务自身。
- 从架构角度考虑,
网关统一鉴权就像是将一个传统单体应用作为网关,网关之后又带了诸多无法保护自身接口安全的 Spring Boot 应用。 网关统一鉴权,网关服务不仅要肩负请求拦截、请求路由职责,还要肩负接口鉴权甚至数据鉴权以及权限管理职责,会增大网关服务的压力。
注意
更详细阐述与解释,参见:《OAuth 2 中的鉴权和动态接口鉴权》
[3]轻量级鉴权逻辑
虽然,Dante Cloud 选择由各个服务自身进行接口的鉴权,但也不代表网关服务什么都不做,Dante Cloud 在网关服务中做了轻量级的鉴权处理。
在微服务架构中,除了个别特定 REST API 以外,剩余 REST API 的访问都需要携带 Token (OAuth2 协议中的 Access Token 或者自定义实现的 Token)。基于这一点考虑,Dante Cloud 在网关服务中增加了 轻量级鉴权。
网关服务 轻量级鉴权,就是网关会对所有请求是否携带 Token 进行分析,除了网关服务中配置的特定请求外,只要是没有携带 Token 的请求都会被网关拦截。这样做的好处是:
- 虽然还是由服务自身进行鉴权,但是通过网关的
轻量级鉴权就可以帮助后端拦截大量无效的请求,从而降低其它服务的压力 - 轻量级鉴权,网关并不需要做太复杂的处理,仅需要在转发请求之前判断是否 Token 即可,对网关的性能影响极低。
- 保持了网关服务的独立和“干净”。网关仍旧是一个
保护器的定位,并没有引入过多与保护不相干的业务或者管理逻辑
[三]动态文档聚合
在面向 REST 接口的应用中,通常都会使用 Swagger 来生成接口文档,以方便开发时查看和调试。
微服务和单体系统不同。
- 单体系统直接集成 Swagger 就可以查看所有接口信息。
- 微服务系统接口分布在不同的服务中。虽然也可以一个服务一个服务的查看,但是不够方便也不便于管理。
所以 Dante Cloud 提供了动态文档聚合功能。
- 文档聚合:在 Gateway 服务聚合了所有服务的文档,可以统一进行查看
- 动态聚合:业务服务在如果没有启动,一方面很难聚合该服务的文档,另一方免即使可以聚合也无法查看和调试接口。动态聚合就是可以根据服务的启动状态,动态聚合有效的服务文档。
在浏览器中,直接访问 Gateway 服务中的 Swagger 就可以查看聚合的文档信息。默认的地址为:http://localhost:8847/swagger-ui.html。显示效果如下:

通过右上角就可以切换查看不同服务的接口文档,下图就是切换到 UAA 文档:
提示
如果服务没有启动,右上角服务列表中将不会显示。

重要
文档聚合功能,建议仅在开发环境或者测试环境开启,正式环境不要开启,以减少安全风险。可以通过修改参数进行开启和关闭,参见:Swagger参数
