开放API网关实践(一) ——设计一个API网关

如何设计实现一个轻量的开放API网关.redis

文章地址: blog.piaoruiqing.com/blog/2019/0…算法

前言

随着业务的发展, 所对接的第三方愈来愈多, 各个业务系统面临着一样一个问题: 如何让第三方安全快速接入. 此时有一个集验签、鉴权、限流、降级等功能于一身的API网关服务变得尤其重要.数据库

接下来将分享如何设计实现一个轻量级的API开放网关, 包括接口设计、数据库设计、签名验签方案、鉴权等. 本文侧重于整体设计, 具体实现细节将陆续在后续的文章中分享.编程

API网关简介

API网关在微服务中尤其重要, 其抽象了鉴权、限流、降级等各个业务系统通用的功能. 做为众多内部业务系统外的一层屏障.api

基本需求

  1. 签名及验签
  2. 鉴权
  3. 路由
  4. 权限及资源管理

整体设计

验签、鉴权等功能以职责链的方式进行处理, 网关根据配置进行路由并附加参数用以配合业务系统进行处理(如数据过滤等). 简要请求处理流程以下:缓存

接口设计

网关最基本的功能是转发请求, 常见的方式是根据配置中的路由规则将请求转发给内部服务, 如:安全

/order/*的请求转发给内部的订单系统、/user/*的请求转发给内部的用户系统, 这种作法经常使用于对整个业务系统负责的基础网关.app

而本文所设计的是服务于第三方的开放API网关, 并未使用上述作法, 而是将请求的资源做为参数放到请求体中, 其缘由以下:框架

  1. 开放API服务于第三方, 屏蔽内部路径, 有利于提供命名统一且规范的接口.
  2. 请求接口的映射由网关的路由表维护, 内部接口升级甚至切换到新服务对外接口不变.
  3. 可以更细粒度地针对接口进行权限控制、限流、统计等.

地址

开放API网关对外提供惟一入口, 具体请求的资源做为参数传入.数据库设计

公共参数

为了简化签名和验签的操做, 同时也提升灵活度, 惟一入口的约定了固定的公共参数和返回值, 以下:

公共请求参数

参数名称 是否必须 类型 示例 备注
app_id string 应用ID
method string aaa.bbb.ccc 请求方法
charset string UTF-8 编码
format string JSON 业务参数格式
sign_type string RSA2 签名类型
sign string 签名
timestamp number 1564929661796 时间戳, 单位: 毫秒
nonce string 63DCB93D270E44D49499F9E5D55705FE 随机字串(建议使用UUID)
version string 1.0 接口版本
biz_content string {"start_time":"1564929661796", ...} 请求业务参数
  • app_id: 应用ID, 应用ID是受权的主体, 是调用方的身份标识
  • method: 请求方法, 与内部URL对应, 由网关的路由表维护.
  • timestampnonce用来防重放攻击.
  • biz_content: 业务参数, 这个参数将转发给内部业务系统.

公共返回参数

参数名称 是否必须 类型 示例 备注
code number 0 错误码
message string 错误信息
charset string UTF-8 编码
format string JSON 返回参数格式
sign_type string RSA2 签名类型
sign string 签名
timestamp number 时间戳, 单位: 毫秒
biz_content string {"id":"1564929661796", ...} 返回业务参数
  • biz_content: 返回业务参数, 网关转发业务系统的返回值.
[版权声明]
本文发布于 朴瑞卿的博客, 容许非商业用途转载, 但转载必须保留原做者 朴瑞卿 及连接: blog.piaoruiqing.com. 若有受权方面的协商或合做, 请联系邮箱: piaoruiqing@gmail.com.

签名方案

调用方和服务方均生成2048RSA秘钥, 交换公钥. 私钥用于签名, 公钥用于验签, 开放API网关对外接口使用https, 故暂不需额外作加密处理.

签名算法

签名算法名称 标准签名算法名称 备注
RSA2 SHA256WithRSA 强制要求 RSA 密钥的长度至少为 2048

签名规则

签名参数内容

剔除sign以后的所有参数.

签名参数排序

按照参数名的ASCII码递增排序(字母升序排序).

签名生成方式

排序后的参数列表组合成参数名a=参数值a&参数名b=参数值b&...&参数名z=参数值z的字符串, 并使用私钥生成sign.

数据库设计

数据库用于存储秘钥权限等配置, 程序和数据库之间有多级缓存用以提升访问速度. 简要ER图以下:

  • app: 调用方主体, 用于标识请求方身份.
  • group: 组, app分组, 可经过group统一进行受权.
  • subject: 主体(app/group).
  • resource: 资源, 维护请求资源与内部接口的映射关系, url+http_method 对应惟一的resource_id.

技术选型

网关除了知足功能上的需求外, 性能上的需求也须要着重考虑, 毕竟做为各个业务系统对外的惟一入口, 网关的性能可能会成为整个业务系统的瓶颈. 业务并不复杂, 性能要求高, 响应式编程正是一个不错的选择.

  • Spring WebFlux + netty: 响应式Web框架.
  • Spring Data Reactive Redis + Lettuce: 响应式redis客户端.
  • Guava: Google工具包, 使用LoadingCache做为进程内缓存.

结语

网关做为内部系统外面的一层屏障和入口, 除基本功能和性能上的需求外, 监控、统计、日志等都是须要考虑到的问题, 网关方面开源产品众多, 但选择时必定要考虑自身业务, 适合自身的前提下参考各个成熟的方案进行实践.

若是这篇文章对您有帮助,请点个赞吧 ( ̄▽ ̄)"

系列文章:

欢迎关注公众号:

[版权声明]
本文发布于 朴瑞卿的博客, 容许非商业用途转载, 但转载必须保留原做者 朴瑞卿 及连接: blog.piaoruiqing.com. 若有受权方面的协商或合做, 请联系邮箱: piaoruiqing@gmail.com.
相关文章
相关标签/搜索