API网关(API Gatew)是一种架构模式,它是将一些服务共有的功能整合在一起,独立部署为单独的一层,用来解决一些服务治理的问题。可以把它看作系统的边界,它可以对出入系统的流量做统一的管控。
网关分类
入口网关
入口网关是我们经常使用的网关种类,它部署在负载均衡服务器和应用服务器之间,主要有几方面的作用:
-
提供统一的接入地址
API网关可以将用户的请求动态路由到不同的业务服务上,并且做一些必要的协议转换工作。系统内部部署的微服务对外暴露的协议可能不同:有些提供HTTP服务;有些对外暴露RPC服务;有些暴露的是Web Service服务。API网关可以对客户端屏蔽这些服务的部署地址,以及协议的细节,给客户端的调用带来很大的便捷 -
植入服务治理策略
在API网关中,可以植入服务治理策略,比如服务熔断、降级、限流控制和分流等等 -
客户端的认证&授权
不同的客户端使用的认证方式是不同的,例如:手机APP使用Oauth协议认证;HTML5和Web端使用Cookie认证;内部服务使用自研的Token认证等。这些认证方式在API网关上可以得到统一处理,应用服务不需要了解认证的细节 -
黑白名单
API网关可以做一些黑白名单相关事情,比如针对设备ID、用户IP、用户ID等维度的黑白名单 -
日志记录
API网关中可以记录HTTP请求的访问日志。在分布式链路追踪系统中,可以在网关中生成requestId
出口网关
系统可能依赖很多外部的第三方系统,比如:第三方账户登录、第三方工具支付等。我们可以在应用服务器和第三方系统之间,部署出口网关。在出口网关中,对调用外部的API做统一的认证、授权、审计以及访问控制等。
API网关关注点
-
性能
API入口网关承担客户端所有流量。假如业务服务器处理时间是10ms,API网关耗时1ms,那么相对每个接口的响应时间都要增加10%,这对性能的影响是巨大的。提升API网关性能的关键还是在I/O模型上。 -
扩展性
API网关中执行的动作有些是可以预先定义好的,比如黑白名单的设置,接口动态路由;有些则是需要业务方依据自身业务来定义,所以API网关的设计要注意扩展性,也就是你可以随时在网关的执行链路上增加一些逻辑,也可以随时下掉一些逻辑(热插拔技术)。
一般来说我们可以把每一个操作定义为一个filter(过滤器),然后使用“责任链模式”将这些filter串起来。责任链可以动态地组织这些filter,解耦filter之间的关系,无论是增加还是减少filter,都不会对其他的filter有任何的影响 -
并行处理能力
一般会使用线程池来并行的执行请求。不过这就来了一个问题:如果某一服务出现问题,造成响应缓慢,那么调用这一服务的线程都会被阻塞无法释放,久而久之线程池中的线程就会被此服务所占据,那么其他服务也会受到级联的影响。因此需要针对不同的服务做线程隔离或者保护。
思路一:如果服务拆分不多,可以针对不同服务,采用不同的线程池,这样某一服务的故障就不会影响到其他服务了
思路二:线程池内可以针对不同的服务甚至不同的接口做线程的保护,比如说线程池的最大线程数1000,那么可以给每个服务设置一个最多可以使用的配额
一般来说,服务的执行时间应该在毫秒级别,线程被使用后会很快被释放回线程池中供后续请求使用,同时处于执行中的线程数量不会很多,对服务或者接口设置线程的配额,不会影响到正常的执行。可是一旦发生故障,某个接口或者服务的响应时间变长,造成线程暴涨,但是因为有配额的限制,就不会影响到其他的接口或者服务了
实际应用中也可以将这两种方式结合,比如针对不同的服务使用不同的线程池,在线程池内部针对不同的接口设置配额
常用开源网关
-
Kong
Nginx中运行的Lua程序。得益于Nginx的性能优势,Kong相比于其他的开源API网关来说,性能方便是最好的。一般大中型公司对于Nginx运维能力都比较强,所以选择Kong作为API网关,无论是在性能还是在运维的把控力上,都是比较好的选择 -
Zuul
Spring Cloud全家桶的成员。Zuul1采用同步阻塞模型,在性能上并不是很高效,Zuul2推出时间不长,可能会有坑。但是Zuul的代码简单易懂,可以很好的把控,如果系统的量级达不到Netfix这样的级别,对于Java技术栈的团队,Zuul是个不错的选择 -
Tyk
一种go语言实现的轻量级API网关,有着丰富的插件资源,对于go语言栈的团队来说也是一种不错的选择
如何引入API网关
经过服务化改造之后,在服务层和客户端之间有一层薄薄的Web层,Web层主要做两方面的事情:
-
入口网关
Web层需要将HTTP请求转换为RPC请求,并且对前端的流量做一些限制,对于某一些请求添加设备ID的黑白名单等。这些事情从Web层中独立出来就形成了入口网关 -
服务层接口数据的聚合
比如电商系统的商品详情页的接口,可能会聚合服务层中,获取商品信息、用户信息、店铺信息以及用户评论等多个服务接口的数据。针对这方面一般有两种解决思路:
方案一:再独立出一组网关专门做服务聚合、超时控制方面的事情,我们把前一种网关叫做流量网关、后一种叫做业务网关
方案二:抽取独立的服务层,专门做接口聚合的操作。这样服务层就大概氛围原子服务和聚合服务层
方案二可能更优一些:因为接口数据聚合是业务操作,与其放在网关层实现,不如更贴近业务的服务层来实现
网友评论