内容来源:2017年5月13日,一条架构师管凯强在“Java开发者大会 | Java之美【上海站】”进行《API网关的设计思路及落地》演讲分享。IT大咖说做为独家视频合做方,经主办方和讲者审阅受权发布。
阅读字数:2640 | 4分钟阅读
API网关是一个服务器,是系统的惟一入口。从面向对象设计的角度看,它与外观模式相似。API网关封装了系统内部架构,为每一个客户端提供一个定制的API。html
嘉宾演讲视频和PPT地址:t.cn/R9DZZ0h前端
移动互联时代迭代速率对于后端开发带来了一些挑战。后端
在咱们公司的商品详情页上,包含了商品信息、价格信息、促销信息和推荐列表四个部分。设计模式
在开发过程当中,咱们想要把这四个信息在一个接口访问中所有吐出来,尝试给出一个万能接口。缓存
事实上,咱们在第一次这样作的时候或许是靠谱的,可是当产品发生变动的时候,好比产品想把推荐列表换成热销榜,那么以前作的万能接口就已经不知足这个业务场景了,只能新开一个V2版本。安全
这样重复必然会致使接口的膨胀以及维护成本愈来愈高。服务器
因此虽然咱们都在追求一个万能的解,但这个“解”也许并不存在。网络
咱们商品详情页的数据来自于商品系统、价格系统、推荐系统和营销系统。而对于客户端或用户而言,其实没有必要知道每一个接口由哪一个微服务提供的,只需获得数据便可。架构
因此咱们面临的问题就是怎样避免让客户端感知微服务边界的存在,不一样的后端、前端团队须要统一的接口设计、接入规范。app
API网关是挡在全部微服务以前的一个透明层,是请求进入系统的惟一节点。基于这一点,一方面解决了对调用方隐藏微服务的系统边界问题,另外一方面负责服务请求路由及协议转换。它可能还具备其它职责,如身份验证、权限控制、负载均衡、“请求整形”与管理。
在咱们的APP和WEB上,全部请求都基于HTTP,RPC服务是基于DUBBO的RPC框架来作。
API网关作的最简单的一件事就是可以让用户发起的请求经过API网关转成对RPC服务的调用,再回到用户的APP上。
主要解决了HTTP请求到RPC调用实例的映射,以及把无类型的参数转换为带类型的参数。
实现了一个轻量级的MVC框架,将请求转换为对RPC实例的调用。
我认为一个设计良好的接口必定包含了明确的异常编码,以及这个异常编码在什么业务场景上出现,这个异常编码怎样在客户端获得合适的处理。
还须要有一个明确的调用权限说明,和清晰的参数列表、返回结果。
如图,这上面有一个ApiGroup,来描述业务模块的属性。
这是咱们某个特定的方法,和control有些类似。包含了API的方案名、SecurityType是权限认证的level。
Designed ErrorCode是用来对客户端接口明确报出异常。
入参描述有ApiAutowired和ApiParameter两种类型。
在API注册流程中,咱们首先作了ApiParser,用于解析API信息,解析完以后会获得接口的完备信息,包含了接口的描述及整个业务异常编码的描述。
第二步是要建立一个RPC调用实例,也就是RpcInvoker。
接下来须要建立一个服务的动态代理,来解决无类型参数到RPC接口上的有类型参数的转换。
最后是把proxy作一个缓存。
这是一个动态生成proxy的例子。
咱们用ASM字节码框架在运行期动态生成proxy。图中函数是把string类型参数转换为强类型参数。
第一步解析请求,在URL中须要描述清楚HTTP调用哪些接口,解析请求就是要pass出这些信息。
而后要作安全验证,以保证什么样的请求才能够被路由到微服务的请求。
第三步构建API调用的上下文。上下文里包含了用户ID等信息,这些信息来自于用户访问令牌解密以后。
接下来就是作代理的执行,最后对结果作序列化。
作安全策略的大致上的处理方法就是设备识别、数字签名,也包括HTTPS。
设备识别主要是用于确认身份,依赖于一个叫token的访问令牌来作。
在APP上用户若是发起了登陆,首先通过网关,而后到用户服务,登陆完成后下发appSecret和token。
APP在调用API以前要作数字签名,须要一个签名的密钥,也就是下发的appSecret。
API到了网关,网关能够解析出用户身份对应的appSecret,因此它能够验证这个请求是否是正常的请求。验证经过后就到了业务系统。
中间人攻击是在APP发起请求离开设备之后,在网络传输过程当中若是被第三方窃听,它会去尝试篡改请求。
中间人窃取到网络传输中的请求报文,虽然得到了token等关键信息,但因为签名密钥appSecret没法经过监听网络请求得到,因此中间人篡改请求却没法获得一个正确的数字签名。
虽然万能接口是不存在的,但咱们尝试实现减轻一个接口中同时返回来自于不一样微服务的信息的需求。基于这个需求,咱们在API网关扩展出一个组合式调用的协议。
简单来讲,这个协议是在一次HTTP请求中对RPC服务发起屡次调用,在API网关作响应报文的整合,最后作返回。
用Façade设计模式为多个RPC服务的接口作了Façade,在Façade上把API作组装,统一暴露给客户端,让API网关成为API的Façade。
但咱们以前尝试作的万能接口跟不上需求的变化,最终它带来的恶果就是代码难以维护。若是在API网关上去不停地为接口作Façade,API网关的代码必然也是很难维护的。
为了解决这个问题,咱们让客户端去定义Façade,API网关只负责组装。
使用异步并行方式,将组合式调用串行变并行。
首先是请求前置处理,实际调用则采用了dubbo async调用,是dubbo原生的调用方式。最后作请求后置处理。
可是Dubbo异步调用标识会经过attachment向下传递,污染调用链,致使后续调用链路都变成了异步方式。并且dubbo filter链机制在异步调用中具备局限性。
这两个问题都是最后改了dubbo的源码来解决的。
提供在线API文档和接入SDK。
可是变化老是存在,咱们该如何解放生产力呢?
扩大API的影响力,基于API信息生成敏捷开发工具;强类型约束的SDK,及时暴露违背“契约”的行为。
这是咱们作的一些敏捷开发的工具。
这是在线文档工具和调试工具。
Dubbo attachment是一种隐式传参机制,具备传递性。
基于这个机制能够把请求标识在调用链路上一直作传递,调用链路上增长AOP、向日志上下文中传递traceid。
在API网关落下的全部请求日志都会有相应的错误编码,能够作zabbix基于这个服务的远程报错。
从技术设计的角度上来讲,API是一种抽象,它隔离了咱们的使用以及实现;从开发管理的角度上来讲,API是一种契约。
API网关是一种微服务的架构解决方案,服务于API“契约”精神,并尽量的扩大这种契约的影响力,构建一种围绕API开发的“生态”。
API网关前面是HTTP的传输,在这过程当中不必定须要中心化的存储,能够尝试用CDN来作边界缓存。
热发布服务于全部微服务,微服务接口的变动怎样作到热重启,是一个比较有挑战性的事情。
咱们以前作的事情只是日志定位,谈不上调用链路跟踪,调用链路跟踪有更专业的解决方案。
API网关目前作的只是权限验证,尚未和风控系统结合起来。
限流降级也尚未作。
在网关上作ab测试会是比较有意义的。
我今天的分享就到这里,感谢聆听!
推荐文章
近期活动