API Gateway

构建web应用的时候,往往需要在“真正的web服务”的基础上,增加一些通用功能,比如记录日志、授权管理、请求速率限制等。对于HTTP请求来说,API Gateway扮演着网关的角色,也可以说是进入系统的唯一节点,API Gateway能够集中地控制和管理通用的功能。
下面是一个来自Mashape Kong的对比:

kong.png

在当前的架构中:

在API Gateway架构中:

目前,API Gateway已经成了AWS的一项重要业务,下面两张图分别展示了亚马逊API Gateway调用流程,以及亚马逊API Gateway请求处理流程:

aws-api-gateway-1.png aws-api-gateway-2.png

在这里要特别强调的是,上文中提及的Mashape Kong。Kong是一个基于ngx_lua实现的API Gateway,github上的地址是:https://github.com/Mashape/kong


VIPServer

VIPServer是阿里中间件团队开发的一个中间层负载均衡(mid-tier load balancing)产品,VIPServer基于P2P模式,是一个七层负载均衡产品。VIPServer提供动态域名解析和负载均衡服务,支持很多诸如多业务单元同单元优先、同机房优先、同区域优先等一系列流量智能调度和容灾策略,支持多种健康监测协议,支持精细的权重控制,提供多级容灾体系、具有对称调用、健康阈值保护等保护功能的解决方案。(上面的介绍摘自http://www.woaiit.com/news/2016052713841.html
下面开始介绍VIPServer的原理:
假设有一个内部服务A和一个内部服务B,在服务A中需要调用服务B,那么通常情况下时序图可能如下所示:

non-vipserver.png

其中:Load Balance层可能是公用的,而每一个服务都有自己的web proxy server和actual web server。
在当前的架构中,有一个缺点:服务间的请求需要经过多层转发,才能到达真正处理请求的后端服务器。当内部服务的数量增大时,服务之间的请求数量也会变得极为可观,如果为了保证高可用,每个服务都使用了公共的内网LVS的话,那么LVS本身的带宽都会成为瓶颈。阿里开发VIPServer的原因之一就是:内网LVS的带宽被跑满。

下面是博主整理的VIPServer工作原理简图:

vipserver.png

VIPServer服务的大体功能包括:

上图中没有体现出,但是需要特别说明的包括:

  1. 在服务A从VIPServer服务请求得到服务B的IP或IP列表时,可以缓存一段时间,并且可以自己实现一些负载均衡策略和重试策略
  2. 服务A可以不直接访问VIPServer服务,而是将域名解析请求发送到dns-f,dns-f是一个自己实现的、部署在本机的DNS服务器,对于在VIPServer上注册的域名,它会请求VIPServer进行处理,并缓存;而“真正的”域名,会交给本机设置的DNS服务器处理。

和VIPServer类似的产品是httpdns


ngx-service-discovery

ngx-service-discovery是基于Openresty(ngx_lua)和Redis实现的一个Nginx自动发现后端upstream,以及对后端upstream进行健康检查的服务框架。里面有一些API Gateway和VIPServer的影子。
下面是该框架中的一些概念:

data-structure.png

其中:hash表名表示Nginx ID,target表示要代理到的数据中心ID,backup表示备用的数据中心ID,abtest表示用来处理AB Test请求的数据中心ID

dc-data-structure.png

其中:hash表名表示数据中心ID;key代表后端节点的地址;value是json格式的,hostname表示该后端节点对应的域名,uripattern表示该后端节点能处理哪些uri,它是一个正则表达式,^/表示所有uri,checkpath是用于健康检查的地址,还可通过checktimeout设置健康检查时的超时时间,weight用于balance算法,表示权重。
当后端服务启动的时候,可以自己向Redis注册,一个后端服务可以注册到多个数据中心或虚拟数据中心上,比如服务127.0.0.1:80可以同时注册到DATA_CENTER-dc1和DATA_CENTER-dc1-ABTest,注册其实就是在一个或多个表示数据中心的hash表中增加一个key/value对,其中,key是服务的地址,value是相关的配置信息。也可以象VIPServer一样,由服务提供方通过web UI去注册

有了上面的概念之后,就可以很好的理解下面要阐述的服务是如何发现的了:

select-backend.png

接下来用文字描述进行补充:

在Nginx ID配置中,保存的是Nginx需要将请求代理到哪个数据中心,包括target数据中心、backup数据中心、abtest数据中心;在数据中心配置中,保存的是某个数据中心上注册了哪些后端节点。
Balancer先去Nginx ID配置中获取到target数据中心和backup数据中心,再根据数据中心配置生成target后端节点列表和backup后端节点列表,接着用请求的host、uri以及健康检查的计数过滤这两个列表,最后根据负载均衡策略先从target后端节点列表中选择节点,然后将请求代理到该节点,如果没找到合适的,那么再去backup后端节点列表中选择,如何仍然没有合适的后端节点,那么服务返回500 INTERNAL ERROR。
因为数据中心信息、节点信息、节点健康信息都在cache中,如果通过一个接口将他们暴漏出来,那么这个接口就是一个弱化版的VIPServer。


测试ngx-service-discovery

example-1.png

注意:Nginx实例的节点类型是通过plugins/MyConfig.lua的NODE_TYPE配置项来配置的;Nginx实例所在的数据中心是通过plugins/MyConfig.lua的DATA_CENTER配置项来配置的。

example-2.png

需要特别注意的是:在数据中心配置信息中,每个节点都有一个hostname和一个uripattern。Balancer在过滤后端节点列表的时候,会要求请求的host和节点的hostname相同,并且请求的uri与节点的uripattern(一个正则表达式)相匹配。测试时,要注意请求头中的Host头域配置中节点的hostname。在生产中,将域名指向Nginx所在的服务器即可。

example-3.png