网关如何实现高可用?
2018,12,10 博客

业内通常用多少9来衡量网站的可用性,例如QQ的可用性是4个9,也就是QQ能够保证在一年里,服务在99.99%的时间是可用的,只有0.01%的时间不可用,大约最多53分钟。

对于大多数网站,2个9是基本可用;3个9是叫高可用;4个9是拥有自动恢复能力的高可用。

实现高可用的主要手段是数据的冗余备份服务的失效转移,这两种手段具体可以怎么做呢,在网关里如何体现?

一、集群部署

保障服务可用是网关的一个重要职责,服务通过网关开放出去,如果不是集群部署,整个网关只有一个节点,这个节点挂了,网关就相当于挂了,这样网关存在的意义其实不大,所以一般网关会跟根据服务器性能进行集群部署。虽然网关可以只在一个地方部署集群,相当于是单数据中心部署,但是企业可以根据服务性质进行地域性的数据中心部署,每个数据中心包含几个网关节点,这样每一个数据中心既可以当作是地区用户的访问中心,也能够当作是数据的灾备中心。这样部署已经能够保障网关的正常可用。

EOLINKER AGW(GOKU API Gateway)的集群部署架构图

二、负载均衡

一套完整的网关应该包含一个控制台与多个网关节点,控制台内的配置项对所有的节点生效。通常一台服务器只部署一个网关节点,并且通过IP地址注册在控制台中,节点会通过主动/被动更新的方式获取控制台上的最新配置信息。

这里说的负载均衡不是架设在网关前的负载设备(nginx或f5),而是网关节点本身的负载,网关的每个节点都能够对所有后端进行负载。如下图所示,每个网关节点都能够将请求分发到服务1、服务2和服务3。也就是说,一个请求从客户端过来,首先被负载设备(nginx)分发到某个节点,再由节点(网关)将请求分发到具体后端。

EOLINKER AGW(GOKU API Gateway)的负载均衡

三、健康检查

尽管上面已经加了两层负载,但是,假设我们的某个节点出了问题,或者说某个后端服务出了问题。nginx有可能会把请求负载到有问题的节点,节点也有可能会把请求负载到有问题的后端,这时候服务最终的结果仍是不可用,如果能及时把有问题的节点和有问题的后端移出负载范围就好了。如何及时知道节点出了问题或者说是后端出了问题?其实也不难,像是监控检查一样,定期去检查目标对象,对象没有返回结果就是有问题了。

健康检查这里有两种,一种是nginx对网关节点的健康检查,另一种是网关节点对后端服务的健康检查。

nginx如何对节点进行健康检查,网上有很多相关教程。这里主要探讨的是网关节点对服务后端的健康检查,我们可以对后端设定正常返回的结果(根据请求状态码、超时期限、或是其他条件),定期访问后端服务,若发现返回异常,则控制台将该后端从负载列表里移除。发现异常时网关同样会产生告警。移除后网关也会定期访问该后端服务,若发现后端服务已恢复,则恢复对该后端的负载。

四、节点自动重启

网关针对异常情况导致停止运行的节点会进行自动重启。制台每隔30秒去访问一遍运行中的节点列表,若发现节点返回异常,则进行重试,若重试过程拿到正常返回,则视为节点正常;若重试3次后节点仍返回异常,则视为节点异常,自动重启节点。

五、熔断

我们可能还遇到这种情况,由于某些接口或服务的不可控因素,比如网络连接缓慢,资源被占用或者暂时不可用等,导致对这些服务的调用失败,但是这些错误通常在一段时间内可以恢复正常。

但是,难保有些原因使错误结果超出预期,并且这种错误可能严重到系统的部分失去响应,甚至导致整个服务的完全不可用。比如由并发请求引起的阻塞,这种对请求的阻塞可能会占用宝贵的系统资源,如内存,线程,数据库连接等等,消耗的资源使其他系统不相关的部分受影响甚至拖累整个系统。在这种情况下,对客户端立即返回错误可能是一种更好的选择,等到发现服务可用的时候再恢复访问。

判断服务不可用就切断对服务的访问,这种机制像是电路的保护机制,我们都形象地称其为熔断。熔断跟心跳检测不太一样,心跳检测是主动地去探测接口是否正常,而熔断是使用过程中才会触发的。

简单来说,熔断是指接口在一定时间内访问失败达到一定的次数,就触发熔断。熔断启动后,网关不会对该接口进行转发,而是直接返回预先设定的内容。每隔一段时间网关会检测接口是否恢复正常,等到接口恢复正常,网关才会恢复对该接口的转发。在EOLINKER AGW(GOKU API Gateway)里熔断是根据接口返回的状态码触发的,异常的状态码我们能设置多个,比如说常见的404或500。

所以熔断这个机制可以分为三个部分:

          successCounts:熔断期后,判断请求是否恢复正常的条件,若连续请求成功次数达标,则恢复转发,服务自动转入监控期;否则,继续进入熔断期。如此反复。

EOLINKER AGW(GOKU API Gateway)熔断插件执行流程

六、服务降级

服务降级有点像熔断的其中一部分,但是使用上没有熔断那么苛刻,我们可以根据服务的返回来判断是否需要进行服务降级。例如根据HTTP状态码,只要接口返回异常状态码就可以进行服务降级,接口返回正常的状态码,网关就会正常转发。服务降级时,由网关返回服务降级预先设定的内容。

服务降级也能分为三个部分:

         matchStatusCodes:异常状态码:一般是404、500等

          statusCode:服务降级时返回的状态码

          接口返回正常状态码即可恢复服务。

七、接口重试

虽然有很多机制保障接口的可访问,但是一个请求报错的原因有很多,偶然一次报错不一定是服务不可用,最简单的,第一次不行,应该再访问一次或几次,以确定结果。

请求重试可以说是网关对接口转发的基本要求,每个接口都应该可以设置重试次数。当请求失败后,网关应立即再次请求,直到拿到正常返回,或是达到重试阈值,再将结果返回给客户端。

小结

一个请求过来,首先经过nginx的一层负载,到达网关,然后由网关负载到真实后端,若后端有问题,网关会进行重试访问,多次访问后仍返回失败,可以通过熔断或服务降级立即返回结果。而且,由于是负载均衡,网关重试时不一定会访问到出错的后端。