API网关实战总结
Posted 码不禁言
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了API网关实战总结相关的知识,希望对你有一定的参考价值。
背景
公司的API网关已经上线运行了一段时间,这里做个总结,API网关相关的文章很多,本文更多的是笔者实战过程遇到的问题和思考,欢迎大家交流。
API网关的必要性
API网关在微服务中有着重要的作用,这里不再赘述前人的总结,从实际需求出发讨论。我们先看下在没有API网关的情况下,需要对外暴露内部服务接口,传统的做法是怎么样的?
如上图所示:这是一个典型的互联网架构,我们看到接入层所做的事情就是将内部服务对外进行暴露,基本每个CGI都要做鉴权、限流、协议转换等操作,CGI这一层重复冗余,写起来缺乏成就感,尤其是鹅厂的同学,用C++写CGI是件多么痛苦的事情。
通过API网关完全可以替代CGI这一层,以配置化的方式实现内部服务对外暴露接口。API网关带来的好处简单总结两点:
收拢:收拢对外接口,规范对外行为
统一:对流量进行统一管控,减少重复开发
API网关选型
一个组件的选择无非是云产品、开源、自研这三种,如之前的文章所述,建议有一定开发能力的团队可以根据自身技术栈,参考现有的开源产品做二次开发或完全自研。
现有开源的网关更多是通用流量控制的实现,如频率限制,IP限制,熔断等。但作为企业级的网关,需要更多生产应用层面的考虑,比如API的规范化、权限控制、发布管理、与内部RPC通信等。这方面无论是云产品还是开源产品都很难满足企业个性化的需求。
因此我们公司的API网关最终通过完全自研的方式实现,当然其中参考了阿里云API网关的部分产品形态及部分开源网关的设计思路。
总体设计
API网关主要有三个模块:
Proxy:接收外部请求,对流量进行管控和转发。
Meta:API信息由Meta服务提供,Proxy会定期查询API的更新信息。
Dashboard:管理后台,API的变更会写到存储并通知Meta更新。
在API的基础上可以做文档管理系统和对外的OpenAPI。
网关核心功能
APPID管理
各个业务成千上万的API需要进行统一管理和约定,否则后期的维护将是灾难。这里我们用到了APPID的概念,一个APPID对应一个应用对象,某个API必须归属具体的APPID。APPID约定为三级:业务.模块.对象,比如pay.user.info,表示支付业务下的user模块的info对象。引入APPID带来如下的好处:
权限管理:appid的分级约定天然可以用来做层级的权限管理
API隔离:可以针对appid的层级进行api的隔离部署,这样对外的多个proxy互不影响
分组管理:流量的管控可以针对appid的层级进行分配,比如对某个二级下的appid进行统一的IP白名单配置。
API路径约定
在统一了appid的管理之后,我们还需要统一对外提供的api路径,我们的路径约定如下:
https://www.xxx.com/api/pany.user.info/v1/create
https://域名/api/appid/version/method
域名:网关的域名,可以根据业务实际需求申请。可以统一一个,也可以按业务区分。
appid:公司内部约定的appid。
version:相同的api根据version提供不同版本的实现。
method:应用提供的方法名,这里暂不限制层级,可以支持多层级比如/create/xxx,甚至可以考虑支持通配符的形式如/create/order*,/create/order[:id]等形式。
多域名,模块化部署
网关的部署结构支持一套dashboard,多套proxy的模式,由于API具有appid,环境,TAG标签等属性,可以在这些属性的基础上做多环境、模块化的Proxy部署。比如线上环境可以指定ENV=Pro的API,可以针对APPID一级为pay即支付类的api做单独的域名部署,这样的好处是各个模块在对外提供服务的时候可以相互独立互不影响。
一处编辑,多处发布
API的发布区分测试、预发布和线上环境,api的编辑无需区分多环境,只要一处编辑之后发布到多个环境即可
API的发布流程有历史记录,并且可以对历史版本进行回滚
插件化管理
网关是一个充满定制化的项目,在实际应用过程,业务可能会有各种特殊的需求,这需要网关具有一定的扩展性。我们参考业界的实现,将API的执行过程通过插件进行组合,一个api的执行流本质上是插件的顺序执行流,如下是一个插件的典型接口:
type Plugin interface {
// Process
Process(context.Context, *Context) int
// Name
Name() string
// Type
Type() int
// Order
Order() int
// Close 释放资源
Close()
}
插件分成两类,一类是网关内部的通用实现,比如流量控制插件、鉴权插件、白名单插件,RPC转发等插件,用户只要做配置即可。还有一类插件是定制化的,通过javascript脚本的方式提供,业务可以通过脚本来实现自己的业务逻辑,比如对请求做内部校验,给请求指定标签等。
注意对于业务自己实现的插件需要做管控,比如运行超时强制退出等,否则可能存在质量较差的插件把网关资源耗尽的情况。
鉴权方式
对于外部请求需要进行鉴权管理,这里涉及到合作方的管理,每个合作方用户拥有唯一的ParternerCode和ParternerKey,在需要RSA鉴权的时候需要合作方提供PublicKey。可以给合作方授权访问API列表,同时可以对合作方做流控管理配置。针对不同的API敏感级别,可以提供多种不同的鉴权方式,如下:
无需认证
Header传递ParternerCode
Header传递ParternerCode + 参数签名认证
JWT Token认证
RSA认证
多测试环境支持
目前我们对外提供的测试网关域名就一个,但不同的业务或不同的特性可能所在的测试集群环境是不同的,因此需要网关支持多测试集群的场景。如下图所示,这里通过在请求头里指定TestCluster字段来区分不同的测试环境,不指定该header则会走默认的测试集群。
协议转换
协议转换是api网关的一个附加功能,公司部分服务是以protobuf协议提供的,而对外提供的协议一般是http+json,如果api网关能够实现协议转换,则业务无需额外且重复地去做协议转换层。protobuf支持动态转换为json,因此这不是什么难事,关键的问题是如何和公司的协议平台关联起来,在协议变更的时候如何实现网关的动态更新。
其他一些问题
文档和监控
对于一个完整的API网关必需提供详细的文档和联调工具;对于一个线上运行的服务,相应的监控和告警也是必不可少的,监控涉及的点包括了API、合作方、后端服务等监控项。
API聚合
在《微服务架构设计模式》一书里提到API聚合的概念,但在网关实现API聚合是一个值得商榷的问题,API聚合的背景是这样的:后端多个服务各司其职实现自己的接口功能,但对外的时候需要将多个服务之间的数据进行整合再提供。笔者认为服务间的聚合功能非常复杂,存在各种逻辑判断和数据整理,网关不太适合这类复杂的接口整合,更建议将聚合功能由业务自行实现提供给网关调用。
以上是关于API网关实战总结的主要内容,如果未能解决你的问题,请参考以下文章
Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段
API网关spring cloud gateway和负载均衡框架ribbon实战
从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析
从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析