上文给大家介绍的内容是Zuul的插件机制及定制化开发,本文将介绍Zuul的动态路由。
Zuul的动态路由启动时Zuul会读取静态配置文件加载路由信息,将URL Path与路由映射关系建立好,提前加载到内存。在很多场景下,我们需要在不停止Zuul进程的前提下,完成路由映射规则的重新建立,这时候我们就需要动态路由(Dynamic Routing)功能,有两种实现动态路由的方式。
方式一:通过Spring Boot Acturator开启Zuul的Endpoint功能,它支持Refresh动态刷新配置文件,这种方式的好处是Zuul无须做任何修改,也不需要维护路由映射规则,缺点是没有可视化界面,维护起来比较烦琐。
方式二:覆写RouteLocator的List<Route>getRoutes()方法,通过事件刷新机制,从数据库中读取路由配置规则。这是常用的Zuul动态路由解决方案,它可以轻松地实现可视化管理,减少引入新的Spring Cloud组件的依赖绑定。Sia-Gateway(GitHub已开源项目)使用了基于MySQL DB的动态路由机制。如下图所示是Zuul动态路由架构图。
Zuul的动态路由思路及解决方案如下。
首先,Admin作为前端管理界面将用户对路由的添加、修改、删除等操作通过RouteService存储到DB中。DB中的存储结构如下图所示。
字段映射关系如下。
● id:标识路由的唯一ID,唯一主键,可以根据路由ID查找路由。
● ZuulGroupName:网关集群组名,标识这个新建的路由归属在哪个网关集群下面。
● apName:应用名称,标识路由的别名。
● path : 匹 配 路 径 , 新 建 路 由 的 路 径 匹 配 Patten ( 例如/foo/**),所有发到/foo/**路径下的请求都会转发到这个路由下面。
● strategy:后端服务策略,后端路由有以下三种策略(只能选其中一种策略)。
○ SERVICEID策略:针对连接到Eureka上的应用,根据配置的ServiceID,网关会动态匹配一个后端服务。
○ SERVICEURL策略:针对非Eureka上的应用根据配置的URL映射到匹配的URL后端服务上。
○ LISTOFSERVICE策略:针对非Eureka上的应用,可以选择多个IP:PORT(通过逗号分隔)实现路由负载,默认使用RoundRobin方式实现负载均衡。
例如“192.168.1.3:8070,192.168.1.2:8090”。
● SERVICEID:匹配一个新建路由的后端服务唯一标识。● url:后端服务URL,匹配一个新建路由的后端服务URL物理地址。
● stripPrefix:前缀是否生效,标识这个路由在转发时是否需要删除前缀设置。
○ 当stripPrefix=true时,主要的路由映射关系如下:
http://127.0.0.1:8181/api/user/list-
>http://192.168.1.100:8080/user/list
○ 当stripPrefix=false时,主要的路由映射关系如下:
http://127.0.0.1:8181/api/user/list-
>http://192.168.1.100:8080/api/user/list).
其次,Admin对Route的状态管理类似状态机,网关节点的路由状态变更通过事件触发机制实现,以达到路由状态的一致性。如下图所示是路由(Route)状态在Admin上的状态流转图。
当Admin在修改Route状态时,它需要首先进行Route下线,当Route处于发布上线状态时,执行发布路由操作会调用publishRoute操作,publishRoute会调用Gateway的对外刷新接口,Gateway会从Admin同步最新的路由信息,并将Route设置为发布状态。
网关节点的路由管理机制主要由两部分组成,一部分通过自定义RouteLocator从Admin同步最新的路由状态,Admin会访问数据库,并返回给网关节点最新的路由状态信息,另一部分就是路由缓存状态管理,即同步更新。下面是代码实现。