微服务网关之Zuul上

在微服务中网关是非常重要的组件之一,在网关上可以进行路由转发、流量限制熔断、日志监控、安全认证等,除了实现这些基本能力,还可以通过网关实现蓝绿部署、金丝雀部署、灰度测试等。Zuul是Netflix 2012年开源的一款网关工具,Zuul英文的含义是怪兽,寓意看门神兽的意思。 

下图是Zuul的架构图,Zuul由三大部分组成,绿色部分是Filter存储部分,粉红色部分是Filter加载部分,蓝色部分是Filter运行时部分。Zuul本质上是通过Servlet filter实现的,Filter中又细分成Pre Filter,Route Filter,Post Filter。当Http请求发送过来时,经过Zuul Servlet处理,到达Zuul Filter Runner,接着依次执行前置、路由,后置过滤器,在执行这些过滤器规则过程中,如果有上下文需要传递,那么是通过RquestContext对象进行共享和传递的。

Zuul的过滤器由groovy语言编写,groovy是动态脚本语言,所以Zuul也具备了可动态发布的过滤机制,这也是Zuul的亮点之一。在学习过滤器时有几个关键概念需要了解:

类型Type:定义在路由流程中,过滤器被应用的阶段
执行顺序Execution order:在同一个Type中,定义过滤器执行的顺序
条件Criteria:过滤器被执行必须满足的条件
动作Action:如果条件满足,过滤器中将被执行的动作

下图是一个典型的Filter脚本案例,shouldFilter()中返回true或者false,里面编写的实际就是条件Criteria,run()方法中就是具体要执行的过滤器动作。

前面提到了不同类型的过滤器,那么不同过滤器间的区别是什么呢?PRE过滤器指在请求被路由到源服务器前要执行的过滤器,该过滤器中主要完成如:认证、选路由、请求日志等。ROUTING过滤器处理将请求发送到源服务器的过滤器。POST过滤器是在响应从源服务器返回时要被执行的过滤器,该过滤器主要完成如:对响应增加HTTP头,收集统计和度量信息,将响应以流的方式发送回客户端。最后还有ERROR过滤器,如果上述阶段中出现错误要执行的过滤器。

前面介绍了Zuul网关的基本概念,接下来就通过实际例子演示来看看Zuul网关是如何工作的,Demo地址(demo来源于bobo微课)。Demo中包含两部分代码,一部分是改造后的zuul-core代码,一部分是zuul-mobile,即用zuul网关的启动入口程序。先来看看zuul-mobile中关键代码InitializeServletListener这个class。这个class中与zuul强相关的是initZuul(),initZuul()中除了加载一些初始化配置信息(filter的groovy文件地址信息等)外,关键是startZuulFilterPoller(),而startZuulFilterPoller()中核心是从ZuulFilterDaoFactory中获取fitler的信息,即从数据库加载filter相关信息。这部分代码对应上面架构图的绿色和粉色部分,即Filter存储和加载部分。

除了InitializeServletListener还有两个关键类SyncZuulServlet和AsyncZuulServlet,接下来看看其中的SyncZuulServlet().该方法中主要是根据不同类型的Filter执行zuulRunner中封装的方法。而runFilter()中执行的是processZuulFilter(zuulFilter),processZuulFilter中执行的是filter.runFilter(), runFilter()中就是执行run()方法,即groovy的filter中定义的run()中的逻辑。所以这一部分代码对应上面架构图的蓝色部分,即filter运行时部分。

上面是Zuul运行的核心逻辑,实际除了完成网关功能外,zuul还提供了一个filter管理功能,管理界面是一个很简单的UI界面,主要由webapp/admin目录下的filter.jsp作为前端界面,FilterScriptManagerServlet 作为后端核心处理类完成filter脚本的管理功能。因为zuul-mobile是一个servlet应用,故在IDE工具上配置Tomcat,启动应用,启动成功后访问链接(http://localhost:8080/s2g_zuul_mobile_war/admin/filterLoader.jsp)即可打开filter文件管理界面,结果如下所示:

备注:启动应用前需创建数据库spring2go-zuul-filter,并用/resouces/db下的脚本初始化filter脚本管理table,修改resouces/mobile_zuul.properties里面数据库连接信息,并在本地创建存放filter文件的目录,目录要与mobile_zuul.properties中配置的一致

通过上面的简单管理界面可以上传s2g-zuul-mobile/scripts目录下的groovy filter文件了,上传后,查看数据库可以看到数据表中存放了filter相关信息。

另外,fitler文件也被加载到了本地新建的目录中,对应上面的架构图,则是从数据库中获取filter信息,并加载到本地的过程。

通过管理界面加载脚本后,脚本有三种状态inactive,canary,active,首次加入的脚本都是inactive状态,设置成canary,理论上是验证脚本正确后,再设置成active状态。这里为了实验方面,上传后都设置成了canary,然后直接设置成active状态。接下来先看看preFilter的内容,然后启动应用来验证PreFilter是否生效。以HealthCheck preFilter为例,当url中包含/healthcheck时,返回response "<health>ok</health>",具体代码如下所示:

通过postman访问http://localhost:8080/s2g_zuul_mobile_war/healthcheck,可以看到确实返回了上述定义的response,说明prefilter生效。

接下来再看看TestRoute.groovy,该脚本中有两部分重点逻辑,第一部分是从properties文件中读取配置的路由信息进行解析,存放到routeTable中,key是服务名称,例如student,value是该服务的地址信息,例如http://localhost:9700

第二部分逻辑是:如果请求的url中包含/api/,那么就从请求的url中读取服务名称,再根据服务名称从routeTableRef对象中读取该服务对应的地址,并把url写入ctx.setRouteUrl中。这样Route.groovy filter就可以从ctx中获取url,完成路由转发的功能

Route.groovy脚本中有很多内容,包括集成CAT,Hystrix等,今天的重点是了解如何完成路由转发,所有重点看路由转发部分的逻辑,CAT和Hystrix的集成会在其他文章中进行详细介绍。为了完成路由转发,调用ctx.getRouteUrl()获取解析出来的路由,这个url地址作为httpUriRequest的url。通过这样的处理来完成路由转发。

为了演示路由转发的效果,还需要单独启动一个服务,该服务监听在9700端口上,和上面路由表配置的信息一致。这个服务是个很简单的具备2个get请求接口的服务。Demo地址

服务启动成功,可以直接通过9700端口访问服务,结果如下所示,说明服务启动成功: 

此时再通过zuul网关地址来调用服务接口,也调用成功,说明路由转发的filter生效。

路由表定义时除了定义student服务映射到localhost:9700外,还定义了hello服务映射到localhost:9700.所以通过/api/hello/echoStudentName,也能访问成功,结果如下所示:

以上就是路由转发的过程。接下来再看看post中的filter,以DebugResponse.groovy为例,在properties中将include.debug设置为true,重新启动zuul网关,再次访问服务,查看response header,可以看到打印了很多用于调试的header信息,例如x-zuul-route-url信息,x-zuul-remote-call-cost服务调用耗时信息等。

查看 DebugResponse.groovy的run方法,核心逻辑如下所示,对于获取服务调用时间,是从RquestContext中获取的。

那什么时候由谁负责将服务调用信息写入RequestContext的呢?是由zuul-core目录下的MobileExecuteRoute中的forward()中统计了服务调用的时间,并写入了RequestContext中。

以上就是对Zuul的学习和理解,实际项目中需结合项目实际编写各类Filter,除了上面Demo提供的Filter外,Zuul官网也提供了各种类型的Filter样例,可以启动官网的zuul,修改Filter后,查看接口调用情况来熟悉官网提供的filter。官网例子地址。拉取官网的zuul源代码,在本地启动后,可以调用提供的各种样例接口,了解filter中的逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

taoli-qiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值