04.03 「架构设计」之如何进行自建API网关?

阅读对象

传统企业正在做微服务架构转型的开发人员或者架构师,希望本文对您能起到一定的引导作用。

API网关介绍

网关一词较早出现在网络设备里面,比如两个相互独立的局域网段之间通过路由器或者桥接设备进行通信, 这中间的路由或者桥接设备我们称之为网关。

相应的API网关将各系统对外暴露的服务聚合起来,所有要调用这些服务的系统都需要通过API网关进行访问,基于这种方式网关可以对API进行统一管控,例如:认证、鉴权、流量控制、协议转换、监控等等。

API网关的流行得益于近几年微服务架构的兴起,原本一个庞大的业务系统被拆分成许多粒度更小的系统进行独立部署和维护,这种模式势必会带来更多的跨系统交互,企业API的规模也会成倍增加,API网关(或者微服务网关)就逐渐成为了微服务架构的标配组件。

如下是我们整理的API网关的几种典型应用场景:

1、面向Web或者移动App

这类场景,在物理形态上类似前后端分离,前端应用通过API调用后端服务,需要网关具有认证、鉴权、缓存、服务编排、监控告警等功能。

2、面向合作伙伴开放API

这类场景,主要为了满足业务形态对外开放,与企业外部合作伙伴建立生态圈,此时的API 网关注重安全认证、权限分级、流量管控、缓存等功能的建设。

3、企业内部系统互联互通

对于中大型的企业内部往往有几十、甚至上百个系统,尤其是微服务架构的兴起系统数量更是急剧增加。系统之间相互依赖,逐渐形成网状调用关系不便于管理和维护,需要API网关进行统一的认证、鉴权、流量管控、超时熔断、监控告警管理,从而提高系统的稳定性、降低重复建设、运维管理等成本。

设计目标

纯Java实现;

支持插件化,方便开发人员自定义组件;

支持横向扩展,高性能;

避免单点故障,稳定性要高,不能因为某个API故障导致整个网关停止服务;

管理控制台配置更新可自动生效,不需要重启网关;

应用架构设计

说明:

1、网关核心子系统通过HAProxy或者Nginx进行负载均衡,为避免正好路由的LB节点服务不可用,可以考虑在此基础上增加Keepalived来实现LB的失效备援,当LB Node1停止服务,Keepalived会将虚拟IP自动飘移到LB Node2,从而避免因为负载均衡器导致单点故障。DNS可以直接指向Keepalived的虚拟IP。

2、网关除了对性能要求很高外,对稳定性也有很高的要求,引入Zookeeper及时将Admin对API的配置更改同步刷新到各网关节点。

3、管理中心和监控中心可以采用类似网关子系统的高可用策略,如果嫌麻烦管理中心可以省去Keepalived,相对来说管理中心没有这么高的可用性要求。

4、理论上监控中心需要承载很大的数据量,比如有1000个API,平均每个API一天调用10万次,对于很多互联网公司单个API的量远远大于10万,如果将每次调用的信息都存储起来太浪费,也没有太大的必要。可以考虑将API每分钟的调用情况汇总后进行存储,比如1分钟的平均响应时间、调用次数、流量、正确率等等。

5、数据库选型可以灵活考虑,原则上网关在运行时要尽可能减少对DB的依赖,否则IO延时会严重影响网关性能。可以考虑首次访问后将API配置信息缓存,Admin对API配置更改后通过Zookeeper通知网关刷新,这样一来DB的访问量可以忽略不计,团队可根据自身偏好灵活选型。

非阻塞式HTTP服务

管理和监控中心可以根据团队的情况采用自己熟悉的Servlet容器部署,网关核心子系统对性能的要求非常高,考虑采用NIO的网络模型,实现纯HTTP服务即可,不需要实现Servlet容器,推荐Netty框架(设计优雅,大名鼎鼎的Spring Webflux默认都是使用的Netty,更多的优势就不在此详述了),内部测试在相同的机器上分别通过Tomcat和Netty生成UUID,Netty的性能大约有20%的提升,如果后端服务响应耗时较高的话吞吐量还有更大的提升。(补充:Netty4.x的版本即可,不要采用5以上的版本,有严重的缺陷没有解决)

采用Netty作为Http容器首先需要解决的是Http协议的解析和封装,好在Netty本身提供了这样的Handler