什么是API网关

共计 2649 个字符,预计需要花费 7 分钟才能阅读完成。

一、网关

微服务概念以来,对接口调用也提出了新的需求。比如众多API调用急需一个统一的入口来支持客户端的调用。在这种情况下,API GATEWAY诞生,我们将接入、路由、限流等功能统一由网关负责。

一个网关的基本功能:统一接入、安全维护、协议适配、流量管控、长短链接支持、容错能力。

1.1 单体应用

什么是API网关

​ 业务简单,团队组织很小的时候,我们常常把功能都集中于一个应用中,统一部署,统一测试,玩的不易乐乎。但随着业务迅速发展,组织成员日益增多。我们再将所有的功能集中到一个TOMCAT中去,每当更新一个功能模块的时候,势必要更新所有的程序。搞不好,还要牵一发动全身。实在难以维护。

1.2 微服务

什么是API网关

​ 单体应用满足不了我们逐渐增长的扩展需求之后,微服务就出现了,它将原来集中于一体的比如商品功能、订单功能、用户功能拆分出去,各自有各自的自成体系的发布、运维等。这样就解决了在单体应用下弊端。

1.3 API网关

什么是API网关

1.4 泛化调用

​ 普通的RPC调用,我要拿到服务端提供的class或者jar包。但这样实在太重,更不好维护。不过,成熟的RPC框架都支持泛化调用,我们的网关就是基于这种泛化调用来实现的。服务端开放出来他们的API文档,我们拿到接口、参数、参数类型通过泛化调用到服务端程序。

二、容错

2.1 抗量

​ 所谓抗量就是增大系统的吞吐量。容器使用的是 TOMCAT,在传统的BIO模型下,一请求一线程,在机器线程资源有限的情况下是没有办法来实现我们的目标。NIO给我们提供了这个机会,基于NIO的机制,利用较少的线程来处理更多的连接。连接多不可怕,通过调整机器的参数一台8c8g的机器,超过10w是不成问题的。

​ tomcat的conector修改成nio之后我们再从代码层面又引入了Servlet3,他是从tomcat7以后支持的,nio是tomcat6以后就支持了。利用Servlet3的特性,所有的request和response都有tomcat的工作线程来处理,我们将业务逻辑异步到别的业务线程中去。

​ 异步环境下,可以提高单位时间内的吞吐量。所有的Servlet请求都是有tomcat的Executor线程池的线程处理的,也就是tomcat的工作线程。这些线程处理的时间越短越好,就会迅速的将线程归还给Executor线程池。现在Servlet支持异步后就能将耗时的操作比如有RPC请求的交给业务线程池来处理,使得tomcat工作线程可以立即归还给tomcat工作线程池。

​ 另外将业务异步处理之后,我们可以对业务线程池进行线程池隔离,这样避免了因一个业务性能问题影响了其它的业务。

2.2 脱离DB

什么是API网关

通过数据异构的方式把数据重新转载的redis中,而且是将数据持久化到redis里面去。当然使用redis的过程中也需要注意大key,大访问量下也能让集群趴下。

还有一个很重要的原因,要说一下的,我们使用的DB是mysql,鉴于mysql的failover机制,生效时间总是要长于redis集群,还有就是因为DB切换的时候,常常伴随web应用服务器要重启,将原来的连接释放掉,以便使用新的数据库的连接。

2.3 多级缓存

什么是API网关

最简单的缓存就是查一次数据库然后将数据写入缓存比如redis中并设置过期时间。因为有过期失效因此我们要关注下缓存的穿透率,这个穿透率的计算公式,比如查询方法queryOrder(调用次数1000/1s)里面嵌套查询DB方法queryProductFromDb(调用次数300/s),那么redis的穿透率就是300/1000,在这种使用缓存的方式下,是要重视穿透率的,穿透率大了说明缓存的效果不好。

还有一种使用缓存的方式就是将缓存持久化,也就是不设置过期时间,这个就会面临一个数据更新的问题。

一般有两种办法,一个是利用时间戳,查询默认以redis为主,每次设置数据的时候放入一个时间戳,每次读取数据的时候用系统当前时间和上次设置的这个时间戳做对比,比如超过5分钟,那么就再查一次数据库。这样可以保证redis里面永远有数据,一般是对DB的一种容错方法。

还有一个就是真正的让redis做为DB使用。就是图里面画的通过订阅数据库的binlog通过数据异构系统将数据推送给缓存,同时将将缓存设置为多级。可以通过使用jvmcache作为应用内的一级缓存,一般是体积小,访问频率大的更适合这种jvmcache方式,将一套redis作为二级remote缓存,另外最外层三级redis作为持久化缓存。

2.4 超时与重试

2.5 熔断

熔断器的使用场景是调用可能失败的远程服务程序或者共享资源。如果是本地缓存本地私有资源,使用熔断器则会增加系统的额外开销。还要注意,熔断器不能作为应用程序中业务逻辑的异常处理替代品。

2.6 线程隔离

在抗量这个环节,Servlet3异步的时候,有提到过线程隔离。线程隔离的之间优势就是防止级联故障,甚至是雪崩。

当网关调用N多个接口服务的时候,我们要对每个接口进行线程隔离。比如,我们有调用订单、商品、用户。那么订单的业务不能够影响到商品和用户的请求处理。

2.7 降级、限流

关于降级限流的方法业界都已经有很成熟的方法了,比如FAILBACK机制,限流的方法令牌桶,漏桶,信号量等

这里谈一下我们的一些经验,降级一般都是由统一配置中心的降级开关来实现的,那么当有很多个接口来自同一个提供方,这个提供方的系统或这机器所在机房网络出现了问题,我们就要有一个统一的降级开关,不然就要一个接口一个接口的来降级。也就是要对业务类型有一个大闸刀。

还有就是 降级切记暴力降级,什么是暴力降级的,比如把论坛功能降调,结果用户显示一个大白板,我们要实现缓存住一些数据,也就是有托底数据。

限流一般分为分布式限流和单机限流,如果实现分布式限流的话就要一个公共的后端存储服务比如redis,在大nginx节点上利用lua读取redis配置信息。我们现在的限流都是单机限流,并没有实施分布式限流。

2.8 网关监控与统计

API网关是一个串行的调用,那么每一步发生的异常要记录下来,统一存储到一个地方比如elasticserach中,便于后续对调用异常的分析。鉴于公司docker申请都是统一分配,而且分配之前docker上已经存在3个agnet了,不再允许增加。我们自己实现了一个agnet程序,来负责采集服务器上面的日志输出,然后发送到kafka集群,再消费到elasticserach中,通过web查询。现在做的追踪功能还比较简单,这块还需要继续丰富。

正文完
 
Dustin
版权声明:本站原创文章,由 Dustin 2019-11-26发表,共计2649字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。