京东到家开放平台网关系统设计实践

京东到家开放平台网关系统设计实践 https://mp.weixin.qq.com/s/aM_hue8CML9FXSSwv5wkXA

京东到家开放平台网关系统设计实践

 王多友 达达集团技术 2022-07-18 17:22 发表于北京

一、平台介绍

二、服务定义

三、服务发布

四、服务授权

五、状态管理

六、流量管控

七、总结

 

一、平台介绍

京东到家开放平台,是一个面向商家以及第三方开发者的开放服务集成平台。平台提供了京东到家全业务场景系统对接的解决方案,商家开发者在自助接入开放平台时,平台会根据商家类型以及配送方式, 自动适配出系统推荐的对接方案。为商家提供本地即时零售的能力,提高服务效率,降低运营成本。同时平台为消费者提供超市便利、生鲜果蔬、医药健康、烘焙蛋糕、鲜花绿植、家居时尚等海量商品1小时配送到家的极致服务体验。京东到家与多方业务合作伙伴一起协同,努力达成多快好省、降维增效的共赢愿景。
图片
开放平台作为商家与到家内部服务交互桥梁,连接商家和到家内部服务。

二、服务设计

从技术层面来看,平台的核心是服务,如何运营好整个服务集群是我们的核心。从服务的生命周期来看,过程分为:定义->实施->迭代->下线,几个流程节点。
关于服务的定义,我面临的挑战有:
稳定性:开放平台服务是给商家使用的,服务的稳定性显得至关重要;
易用性:服务设计要简洁,请求参数要见名知意,针对错误码的定义需要非常明确,让调用者可以一眼就能看到问题的所在;
安全性:服务实施阶段平台对服务质量(监控粒度,安全授权)也有着严格要求;
扩展性:在服务的整个生命周期中,迭代方案如何做到可持续,也需要重点关注,比如是否支持平滑升级、是否支持无感知切换等;
从实现角度来看,开发者方便对接的核心是文档的定义,即约束平台的开发人员,又可以方便调用者快速理解。如何将文档给到对应商家开发者?最简单的方案就是编写一个离线文档,每当文档更新将最新的离线文档发给对应的商家开发者,这种做法简单但是后续会带来很大的沟通成本。比如每次文档更新后需要通知每个对接商家开发者并给予最新文档,前期对接商家较少还好,对接商家一旦过多,就会为开放平台带来很大交互成本。开放平台为了方便商家的对接,我们为商家提供了一套开放平台门户系统。
门户系统的存在可以为开发者和平台运营带来很大便捷。对于平台运营来说,新增、修改服务自动生成文档并以邮件和公告形式通知到开发者,减少与商家沟通成本,并且平台针对服务修改做到新老功能兼容。对于对接开发者来说,只需要关注需要字段即可,一旦服务发生变化并不影响正常调用,想要使用新功能参照最新文档即可。

服务列表文档

图片

 

服务详情文档

图片

 

在线形式的服务文档可以保障实时性,但是如何保证准确性是我们面临的另外一个问题。如果每回发布或修改服务需要人工同步维护文档内容,就很难保证文档的准确性,对于开放平台来说,实现发布服务自动生成在线文档,是十分必要的。
到家开放平台已经对外提供了成百上千个功能服务,有时候为了支持商家接入,一天需要对外发布多个服务,如果参照常规的业务系统,那么可能每天都需要多次上线,上线频率如此高,无论对运营人员还是系统稳定性方面都是一场严峻考验。
到家网关开发方式分为两种,一种是通过集成RPC服务SDK包进行业务代码开发;另一种是泛化调用,显示传入需要调用的RPC服务相关信息调用。无论哪种方式RPC框架都为我们屏蔽调用细节。在到家两种方式应用场景主要区别是,集成SDK方式,适合业务聚合类功能开发,将多种服务组成自己的业务;而泛化调用方式,适合桥接类的服务,比如商家与到家底层服务的打通,只负责返回信息规则限制,不负责生产服务,甚至新的服务接入可以不用上线自动适配。
开放平台API网关采用泛化调用实现,实现思想是调用RPC不再局限于写“死代码”,而是在服务调用的时候动态获取相应的调用协议,由获取的动态调用协议与RPC自动适配调用,这样只需要通过管理服务的方式新增对应的协议,我们就可以完成新服务发布,不需要再集成SDK,避免项目高频发布上线。
整体实现方式是通过服务发布系统编写服务协议,编写完成后动态发布服务。在使用API网关调用时,先从服务发布系统中获取相应的服务协议,经由网关系统协议适配器将服务协议转换成服务泛化调用需要的数据,并以泛化调用形式调用服务,调用结束后适配器将结果数据返回,完成RPC服务调用。在门户系统展示服务文档是同样原理,只不过适配器适配数据不同,一个是适配泛化调用需要数据,一个是适配文档展示需要数据。
无论哪种实现方式都是RPC框架为我们提供的功能,并且屏蔽了其中交互细节。其实了解一下RPC底层原理就可以知道,本质就是将远程服务的方法名、服务名、入参等信息通过网络传递给远程服务端,并在远程服务端本地执行,待远程服务端执行完成后将调用结果再通过网络返回给调用方。这在使用方式上,实现调用远程服务就像是调用本地方法一样。

图片

以dubbo为例,泛化调用实现代码如下。

图片

三、服务发布

到家开放平台所有对外服务的创建都是在服务发布系统完成的,其中发布服务信息的主要内容是供API网关系统使用的服务报文协议,报文协议内容由出入参字段信息、通讯协议等信息组成。服务发布系统中的报文协议同样应用在门户文档展示使用。新的服务发布只需要编辑好报文后点击服务发布,完成整个服务上线。这时候商家就可以在到家门户系统看到这个服务对应的文档。服务迭代的过程中避免不了升级或替换,迭代操作在开放平台操作很方便,可以在服务管理平台进行无缝迁移,只需要调整对应服务发布协议即可完成。
服务发布列表

图片

 

服务协议

图片

 

服务发布

图片

四、服务授权

开放平台将服务根据对接方案进行分组,每组对接方案中包含相关业务所需的服务。平台默认是以方案维度进行服务授权,方案授权给商家后,这个商家的开发者可以访问该方案下的所有服务。新的服务发布后,商家是没有调用权限的,需要为商家进行授权,需要将该服务添加至相应方案中,已经对接该方案的商家将自动授予访问权限。

行业方案列表

图片

 

行业方案服务

图片

五、状态管理

在开放平台每一个对外服务都有一个状态与之对应,每种状态都有对应使用的场景,分别是:开发、测试、发布、隐藏、停用。开发、测试和发布状态,分别对应服务发布的开发、测试、上线阶段。重点说明一下隐藏状态的用法,它主要用于标识服务处于停止支持状态,即标记服务不再支持新商家的接入,但已接入的老商家保持兼容,可继续使用。
服务状态

图片

六、流量管控

到家开放平台日常服务总调用量每分钟可达百万级,如果不做任何的限制,就有可能在一段时间涌入大量的请求从而将系统压垮。为了保证系统不被巨大的流量压垮,会在系统流量到达一定阈值时进行限流,拒绝掉一部分流量从而保证服务的可用率。但是限流会导致用户在短时间内系统服务不可用,如何提高用户单位时间的可用率,是我们接下来要进行探讨的。

6.1 多维度流控

商家在使用开放平台服务时候,平台会根据商家+服务维度进行限频,来应对一些突发流量频繁调用的情况,从而来保障底层服务的稳定性,这种流控的方式就是全局流量控制。

开放平台在实现全局流量管控使用redis中间件,通过固定窗口计数器算法(算法在后续小节中讲解),使用redis的incrby对外API功能做全局计数器累加,在窗口时间内超过商家服务预估阈值进行限制并返回指定错误信息。

 

如果说全局流量管控主要保障底层服务的稳定,那么单机流量管控是为了保障开放平台系统自身的稳定。同样是采用固定窗口计数器算法,不同点是单机流控是基于本地内存实现的。

6.2 流控算法

开放平台的流量管控算法使用的固定窗口计数器,除了固定窗口计数器外常用的还有滑动窗口计数器算法。开放平台流控维度比较多,其中一个维度就是商家+服务维度,商家服务维度会产生大量的限流key,并且每一个key都需要产生相应的统计数据。假如有10万个商家,每个商家调用100个服务,窗口大小设置1分钟,以固定窗口计算,在1分钟内将产生1000万(10万 * 100)个限流key,以滑动窗口计算,窗口滑动幅度为1秒,在1分钟内将产生6亿(10万 * 100 * 60)个限流key。

6.2.1 固定窗口计数法

固定窗口计数法的思路是将时间划分为固定的窗口大小,例如1分钟。在窗口时间段内,每来一个请求,对计数器加1。当计数器达到设定限制后,该窗口时间内的之后的请求都被丢弃处理。该窗口时间结束后,计数器清零,重新开始计数。

图片

 

固定窗口计数器法特点是实现简单,并且内存占用小,我们只需要存储时间窗口中的计数即可,缺点是流量曲线可能不够平滑,有极限场景可能产生突刺现象。突刺现象如图所示,假如当前限流为每分钟3次,时间窗口2和时间窗口3虽然单个窗口都没问题,但是由时间窗口2后半部分与窗口3前半部分组成的1分钟内流量超过限定阀值,相当于存在1分钟内限流超过阀值情况。

6.2.2 滑动窗口计数法

刚才说到固定窗口计数法缺点是流量曲线可能不够平滑,有极限场景可能产生突刺现象,而滑动窗口在一定程度上解决这个问题。滑动窗口算法是计数器算法的一种改进,将原来的一个时间窗口划分成多个时间窗口,并且不断向右滑动该窗口。流量经过滑动时间窗口算法计算之后,可以保证任意时间窗口内,都不会超过最大允许的限流值,从流量曲线上来看会更加平滑,可以部分解决上面提到的临界突发流量问题。对比固定时间窗口限流算法,滑动时间窗口限流算法的时间窗口是持续滑动的,并且除了需要一个计数器来记录时间窗口内服务请求次数之外,还需要记录在时间窗口内每个服务请求到达的时间点,对内存的占用会比较多。在临界位置的突发请求都会被算到时间窗口内,因此可以解决计数器算法的临界问题。

图片

 

在上图中,整个大括号标记一个时间窗口,一个时间窗口就是一分钟。然后我们将时间窗口进行划分,比如图中,我们就将滑动窗口划分成6格,所以每格代表的是10秒钟。每过10秒钟,我们的时间窗口就会往右滑动一格。每一个格子都有自己独立的计数器counter,比如当一个请求 在00:05秒的时候到达,那么00:00~00:10对应的counter就会加1。当统计时间窗口内的格子counter总值超过阈值就会触发限流。计数器算法其实就是滑动窗口算法。只是它没有对时间窗口做进一步划分,所以只有1格。由此可见,当滑动窗口的格子划分越多,滑动窗口的滚动就会越平滑,限流统计随之就越精确。

两种算法的主要区别是固定窗口限流占用内存较少,但是会有突刺现象,而滑动窗口限流随着滑动幅度增加占用内存越来越多,但是突刺曲线随之平缓。开放平台对内存占用越少越好,相对于内存占用突刺带来的影响显得不是那么重要,因此选取固定窗口计数法。

七、总结

本文对京东到家开放平台系统的设计做了整体介绍,其核心是围绕着平台服务的整个生命周期展开,从服务设计规范,服务的发布,服务授权,以及状态管理等各个维度进行较为详细的阐述,为了保证服务的稳定性,同时也提到了平台流控管理的算法选型。希望我们的实践经验能够对读者有所帮助。

 

posted @ 2022-07-26 10:18  papering  阅读(375)  评论(0编辑  收藏  举报