专栏名称: IT大咖说
大咖干货,不再错过。 让不在大会现场的程序猿、攻城狮也能体验现场的精彩瞬间。
目录
相关文章推荐
李楠或kkk  ·  其实,既然说 ai ... ·  昨天  
读嘉新闻  ·  突发!世间将再无松下电视 ·  昨天  
湖北生态环境  ·  “智慧手环”二十四小时守护一江清水东流 ·  昨天  
湖北生态环境  ·  “智慧手环”二十四小时守护一江清水东流 ·  昨天  
掌上铜山  ·  微信上新重大功能! ·  昨天  
掌上铜山  ·  微信上新重大功能! ·  昨天  
51好读  ›  专栏  ›  IT大咖说

打开API网关设计的一扇窗

IT大咖说  · 公众号  · 科技自媒体  · 2017-08-11 20:34

正文

内容来源: 2017年5月13日 一条架构师管凯强 在“Java开发者大会 | Java之美【上海站】”进行《API网关的设计思路及落地》演讲分享。IT大咖说作为独家视频合作方,经主办方和讲者审阅授权发布。

阅读字数:2640  | 4分钟阅读


摘要


API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。

背景


移动互联网时代的挑战

移动互联时代迭代速率对于后端开发带来了一些挑战。


在我们公司的商品详情页上,包含了商品信息、价格信息、促销信息和推荐列表四个部分。


在开发过程中,我们想要把这四个信息在一个接口访问中全部吐出来,尝试给出一个万能接口。


事实上,我们在第一次这样做的时候或许是靠谱的,但是当产品发生变更的时候,比如产品想把推荐列表换成热销榜,那么之前做的万能接口就已经不满足这个业务场景了,只能新开一个V2版本。


这样重复必然会导致接口的膨胀以及维护成本越来越高。


所以虽然我们都在追求一个万能的解,但这个“解”也许并不存在。


微服务时代的挑战

我们商品详情页的数据来自于商品系统、价格系统、推荐系统和营销系统。而对于客户端或用户而言,其实没有必要知道每个接口由哪个微服务提供的,只需得到数据即可。


所以我们面临的问题就是怎样避免让客户端感知微服务边界的存在,不同的后端、前端团队需要统一的接口设计、接入规范。


需求

使用API网关构建微服务

API网关是挡在所有微服务之前的一个透明层,是请求进入系统的唯一节点。基于这一点,一方面解决了对调用方隐藏微服务的系统边界问题,另一方面负责服务请求路由及协议转换。它可能还具有其它职责,如身份验证、权限控制、负载均衡、“请求整形”与管理。


实践落地

从HTTP到RPC

在我们的APP和WEB上,所有请求都基于HTTP,RPC服务是基于DUBBO的RPC框架来做。


API网关做的最简单的一件事就是能够让用户发起的请求通过API网关转成对RPC服务的调用,再回到用户的APP上。


主要解决了HTTP请求到RPC调用实例的映射,以及把无类型的参数转换为带类型的参数。


实现了一个轻量级的MVC框架,将请求转换为对RPC实例的调用。


从HTTP到RPC——定义好一个接口

我认为一个设计良好的接口一定包含了明确的异常编码,以及这个异常编码在什么业务场景上出现,这个异常编码怎样在客户端得到合适的处理。


还需要有一个明确的调用权限说明,和清晰的参数列表、返回结果。


示例


如图,这上面有一个ApiGroup,来描述业务模块的属性。


这是我们某个特定的方法,和control有些相似。包含了API的方案名、SecurityType是权限认证的level。


Designed ErrorCode是用来对客户端接口明确报出异常。


入参描述有ApiAutowired和ApiParameter两种类型。


从HTTP到RPC——API注册

在API注册流程中,我们首先做了ApiParser,用于解析API信息,解析完之后会得到接口的完备信息,包含了接口的描述及整个业务异常编码的描述。


第二步是要创建一个RPC调用实例,也就是RpcInvoker。


接下来需要创建一个服务的动态代理,来解决无类型参数到RPC接口上的有类型参数的转换。


最后是把proxy做一个缓存。


从HTTP到RPC——proxy实例

这是一个动态生成proxy的例子。


我们用ASM字节码框架在运行期动态生成proxy。图中函数是把string类型参数转换为强类型参数。


从HTTP到RPC——处理请求

第一步解析请求,在URL中需要描述清楚HTTP调用哪些接口,解析请求就是要pass出这些信息。


然后要做安全验证,以保证什么样的请求才可以被路由到微服务的请求。


第三步构建API调用的上下文。上下文里包含了用户ID等信息,这些信息来自于用户访问令牌解密之后。


接下来就是做代理的执行,最后对结果做序列化。


从HTTP到RPC——安全策略

做安全策略的大体上的处理方法就是设备识别、数字签名,也包括HTTPS。

设备识别主要是用于确认身份,依赖于一个叫token的访问令牌来做。


在APP上用户如果发起了登录,首先经过网关,然后到用户服务,登录完成后下发appSecret和token。


APP在调用API之前要做数字签名,需要一个签名的密钥,也就是下发的appSecret。


API到了网关,网关可以解析出用户身份对应的appSecret,所以它可以验证这个请求是不是正常的请求。验证通过后就到了业务系统。


中间人攻击是在APP发起请求离开设备以后,在网络传输过程中如果被第三方窃听,它会去尝试篡改请求。


中间人窃取到网络传输中的请求报文,虽然获得了token等关键信息,但由于签名密钥appSecret无法通过监听网络请求获得,所以中间人篡改请求却无法得到一个正确的数字签名。


组合式调用

虽然万能接口是不存在的,但我们尝试实现减轻一个接口中同时返回来自于不同微服务的信息的需求。基于这个需求,我们在API网关扩展出一个组合式调用的协议。


简单来说,这个协议是在一次HTTP请求中对RPC服务发起多次调用,在API网关做响应报文的整合,最后做返回。



组合式调用——Façade设计

用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,及时暴露违背“契约”的行为。



这是我们做的一些敏捷开发的工具。

这是在线文档工具和调试工具。







请到「今天看啥」查看全文