为了提高系统的性能和可靠性,将应用服务进行拆分微服务化。作为系统入口的 API 网关也逐渐成为了标配。
今天我们一起来看看 API 网关的设计思路,需要承载了哪些功能?以及如何选择流行的 API 网关?
什么是 API 网关
既然需要 API 网关为我所用,首先就让我们来了解一下什么是 API 网关。
什么是 API 网关
网关一词最早出现在网络设备,比如两个相互独立的局域网之间通过路由器进行通信,中间的路由被称之为网关。
任何一个应用系统如果需要被其他系统调用,就需要暴露 API,这些 API 代表着一个一个的功能点。
如果两个系统中间通信,在系统之间加上一个中介者协助 API 的调用,这个中介者就是 API 网关。
对接两个系统的 API 网关
当然,API 网关可以放在两个系统之间,同时也可以放在客户端与服务端之间。
对接客户端和服务端的 API 网关
知道了 API 网关的基本定义,再来看看为什么我们要使用它。
为何要使用 API 网关
网关作为系统的唯一入口,也就是说,进入系统的所有请求都需要经过 API 网关。
当系统外部的应用或者客户端访问系统的时候,都会遇到这样的情况:
也就是说,只要是涉及到对系统的请求,并且能够从业务中抽离出来的功能,都有可能在网关上实现。
例如:协议转换,负载均衡,请求路由,流量控制等等。后面我们会一一给大家介绍这些功能。
在了解 API 网关有哪些基本功能以后,来看看它可以服务于哪些系统或者客户端。
API 网关服务定位
API 网关拥有处理请求的能力,从定位来看分为 5 类:
①面向 WebApp,这部分的系统以网站和 H5 应用为主。通过前后端分离的设计,将大部分的业务功能都放在了后端,前面的 Web App 只展示页面的内容。
②MobileApp,这里的 Mobile 指的是 iOS 和 Android,设计思路和 WebApp 基本相同。
区别是 API 网关需要做一些移动设备管理的工作(MDM)。例如:设备的注册,激活,使用,淘汰等,全生命周期的管理。
由于移动设备的特殊性,导致了我们在考虑移动设备请求的时候,需要考虑请求,设备,使用者之间的关系。
③面向合作伙伴的 OpenAPI,通常系统会给合作伙伴提供接口。这些接口会全部开放或者部分开发,在有条件限制(时间,流量)的情况下给合作伙伴访问。因此需要更多考虑 API 网关的流量和安全以及协议转换的管理。
④企业内部可扩展 API,给企业内部的其他部门或者项目使用,也可以作为中台输出的一部分,支持其他系统。这里需要更多地考虑划分功能边界,认证和授权问题。
⑤面向 IOT 设备,会接收来自 IOT 设备的请求,特别是工业传感器等设备。这里需要考虑协议转换和数据过滤。
API 网关架构
既然谈了 API 网关的功能和定位,接下来说说它的架构:
API 网关系统架构图
API 网关拆分成为 3 个系统:
Gateway-Core 核心网关,负责接收客户端请求,调度、加载和执行组件,将请求路由到上游服务端,并处理其返回的结果。
大多数的功能都在这一层完成,例如:验证,鉴权,负载均衡,协议转换,服务路由,数据缓存。如果没有其他两个子系统,它也是可以单独运行的。
Gateway-Admin 网关管理界面,可以进行 API、组件等系统基础信息的配置;例如:限流的策略,缓存配置,告警设置。
Gateway-Monitor 监控日志、生成各种运维管理报表、自动告警等;管理和监控系统主要是为核心系统服务的,起到支撑的作用。
API 网关技术原理
上面谈到了网关的架构思路,这里谈几点技术原理。平时我们在使用网关的时候,多注重其实现的功能。例如:路由,负载均衡,限流,缓存,日志,发布等等。
实际上这些功能的背后有一些原理我们可以了解,这样在应用功能的时候会更加笃定。下面是几个原理分享给大家。
协议转换
每个系统内部服务之间的调用,可以统一使用一种协议,例如:HTTP,GRPC。
假设每个系统使用的协议不同,那么系统之间的调用或者数据传输,就存在协议转换的问题了。如果解决这个问题呢?API 网关通过泛化调用的方式实现协议之间的转化。
实际上就是将不同的协议转换成“通用协议”,然后再将通用协议转化成本地系统能够识别的协议。
这一转化工作通常在 API 网关完成。通用协议用得比较多的有 JSON,当然也有使用 XML 或者自定义 JSON 文件的。
不同的协议需要转化成共同语言进行传输
链式处理
设计模式中有一种责任链模式,它将“处理请求”和“处理步骤”分开。每个处理步骤,只关心这个步骤上需要做的处理操作,处理步骤存在先后顺序。
消息从第一个“处理步骤”流入,从最后一个“处理步骤”流出,每个步骤对经过的消息进行处理,整个过程形成了一个链条。在 API 网关中也用到了类似的模式。
Zuul 网关过滤器链式处理
下面以 Zuul 为例,当消息出入网关需要经历一系列的过滤器。这些过滤器之间是有先后顺序的,并且在每个过滤器需要进行的工作也是各不一样:
异步请求
所有的请求通过 API 网关访问应用服务,一旦吞吐量上去了,如何高效地处理这些请求?
拿 Zuul 为例,Zuul1 采用:一个线程处理一个请求的方式。线程负责接受请求,然后调用应用返回结果。
如果把网络请求看成一次 IO 操作的话,处理请求的线程,从接受请求,到服务返回响应,都是阻塞状态。
同时,如果多个线程都处在这种状态,会导致系统缓慢。因为每个网关能够开启的线程数量是有限的,特别是在访问的高峰期。
每个线程处理一个请求
为了解决这个问题,Zuul2 启动了异步请求的机制。每个请求进入网关的时候,会被包装成一个事件,CPU 内核会维持一个监听器,不断轮询“请求事件”。
一旦,发现请求事件,就会调用对应的应用。获取应用返回的信息以后,按照请求的要求把数据/文件放到指定的缓冲区,同时发送一个通知事件,告诉请求端数据已经就绪,可以从这个缓冲获取数据/文件。
这个过程是异步的,请求的线程不用一直等待数据的返回。它在请求完毕以后,就直接返回了,这时它可以做其他的事情。
请求数据被 CPU 内核获取,并且发送到指定的数据缓冲区时,请求的线程会接到“数据返回”的通知,然后就直接使用数据,不用自己去做取数据的操作。
异步请求处理,CPU 处理数据以后通知请求端
实现异步处理请求有两种模式,分别是:
Reactor 工作原理流水图
Reactor:通过 handle_events 事件循环处理请求。用户线程注册事件处理器之后,可以继续执行其他的工作(异步),而 Reactor 线程负责调用内核的 Select 函数检查 Socket 状态。
当有 Socket 被激活时(获取网络数据),则通知相应的用户线程,执行 handle_event 进行数据读取、处理的工作。
Proactor 工作原理流水图
Proactor:用户线程使用 CPU 内核提供的异步 IO 发起请求,请求发起以后立即返回。CPU 内核继续执行用户请求线程代码。
此时用户线程已将 AsynchronousOperation(异步处理)和 CompletionHandler(完成获取资源)注册到内核。之后操作系统开启独立的内核线程去处理 IO 操作。
当请求的数据到达时,由内核负责读取 Socket(网络请求)中的数据,并写入用户指定的缓冲区中。
最后内核将数据和用户线程注册的 CompletionHandler 分发给内部 Proactor,Proactor 将 IO 完成的信息通知给用户线程(一般通过调用用户线程注册的完成事件处理函数),完成异步 IO。
API 网关实现功能
说起对 API 网关的使用,我们还是对具体功能更加感兴趣。让我们一起来看看它实现了哪些功能。
负载均衡
当网关后面挂接同一应用的多个副本时,每次用户的请求都会通过网关的负载均衡算法,路由到对应的服务上面。例如:随机算法,权重算法,Hash 算法等等。
如果上游服务采取微服务的架构中国移动网关user初始密码,也可以和注册中心合作实现动态的负载均衡。
当微服务动态挂载(动态扩容)的时候,可以通过服务注册中心获取微服务的注册信息,从而实现负载均衡。
Nginx+Lua+服务注册中心实现动态负载均衡
路由选择
这个不言而喻,网关可以根据请求的 URL 地址解析中国移动网关user初始密码,知道需要访问的服务。再通过路由表把请求路由到目标服务上去。
有时候因为网络原因,服务可能会暂时的不可用,这个时候我们希望可以再次对服务进行重试。
Zuul 作为 API 网关将请求路由到上游服务器
例如:Zuul 与 Spring Retry 合作完成路由重试。
流量控制
限流是 API 网关常用的功能之一,当上游服务超出请求承载范围,或者服务因为某种原因无法正常使用,都会导致服务处理能力下滑。
这个时候,API 网关作为“看门人”,就可以限制流入的请求,让应用服务器免受冲击。
限流实际上就是限制流入请求的数量,其算法不少,有令牌桶算法,漏桶算法,连接数限制等等。这里我们就介绍三个常用的,一般通过 Nginx+Lua 来实现。
令牌桶限流
统一鉴权
访问应用服务器的请求都需要拥有一定权限,如果说每访问一个服务都需要验证一次权限,这个对效率是很大的影响。可以把权限认证放到 API 网关来进行。
目前比较常见的做法是,用户通过登录服务获取 Token,把它存放到客户端,在每次请求的时候把这个 Token 放入请求头,一起发送给服务器。
API 网关要做的事情就是解析这个 Token,知道访问者是谁(鉴定),他能做什么/访问什么(权限)。
说白了就是看访问者能够访问哪些 URL,这里根据权限/角色定义一个访问列表。
如果要实现多个系统的 OSS(Single Sign On 单点登录),API 网关需要和 CAS(Central Authentication Service 中心鉴权服务)做连接,来确定请求者的身份和权限。
熔断降级
当应用服务出现异常,不能继续提供服务的时候,也就是说应用服务不可用了。作为 API 网关需要做出处理,把请求导入到其他服务上。
或者对服务进行降级处理,例如:用兜底的服务数据返回客户端,或者提示服务暂时不可用。
同时通过服务注册中心,监听存在问题的服务,一旦服务恢复,随即恢复路由请求到该服务。
例如:Zuul 中提供了 ZuulFallbackProvider 接口来实现熔断,它提供两个方法,一个指明熔断拦截的服务 getRoute,一个指定返回内容 ClientHttpResponse。
我们通过自定义的 Fallback 方法,并且将其指定给某个 Route 来实现该 Route 访问出问题的熔断处理。
主要继承 ZuulFallbackProvider 接口来实现,ZuulFallbackProvider 默认有两个方法,一个用来指明熔断拦截哪个服务,一个定制返回内容。
API 网关熔断降级
发布测试
在发布版本的时候会采用:金丝雀发布和蓝绿发布。作为 API 网关可以使用路由选择和流量切换来协助上述行为。这里以金丝雀发布为例,看看 API 网关如何做路由转换的。
假设将 4 个服务从 V1 更新到 V2 版本,这 4 个服务的流量请求由 1 个 API 网关管理。
那么先将一台服务与 API 网关断开,部署 V2 版本的服务,然后 API 网关再将流量导入到 V2 版本的服务上。
这里流量的导入可以是逐步进行的,一旦 V2 版本的服务趋于稳定。再如法炮制,将其他服务替换成 V2 版本。
金丝雀发布一般先发 1 台,或者一个小比例,例如 2% 的服务器,主要做流量验证用,也称为金丝雀(Canary)测试(灰度测试)
其来历是,旷工下矿洞前,先放一只金丝雀探查是否有毒气,金丝雀发布由此得名。
金丝雀测试需要完善的监控设施配合,通过监控指标反馈,观察金丝雀的健康状况,作为后续发布或回滚的依据。
如果金丝测试通过,则把剩余的 V1 版本全部升级为 V2 版本。如果金丝雀测试失败,则直接回退金丝雀,发布失败。
缓存数据
我们可以在 API 网关缓存一些修改频率不高的数据。例如:用户信息,配置信息,通过服务定期刷新这个缓存就行了:
日志记录
通过 API 网关上的过滤器我们可以加入日志服务,记录请求和返回信息。同时可以建立一个管理员的界面去监控这些数据。
日志服务简图
日志记录了以后,可以做很多功能扩展。我们整理了以下几点供大家参考:
日志记录衍生的功能
流行 API 网关对比
在介绍了 API 网关的功能以后,再来看看目前几个流行的 API 网关项目。看看他们各自的特点,并且把他们做一个简单的比较。这些网关目前都是开源的,大家可以有选择地在项目中使用。
Kong
Kong 是 Mash ape 公司的开源项目,它是一个在 Nginx 中运行的 Lua 应用程序,并且可以通过 Lua-Nginx 模块实现扩展。
所以,可以通过插件集合的方式定制功能,例如:HTTP 基本认证、密钥认证、CORS(Cross-origin Resource Sharing,跨域资源共享)、TCP、UDP、日志、API 限流、请求转发以及监控,都是目前已有的插件。
由于是基于 Nginx 的,所以可以对网关进行水平扩展,来应对大批量的网络请求。
Kong 架构图
Kong 主要有三个组件:
Traefik
Traefik 架构图
限时特惠:本站每日持续更新海量各大内部网赚创业教程,会员可以下载全站资源点击查看详情
站长微信: