京东服务市场是为第三方软件服务商和京东开放商家提供的交易服务平台,为第三方服务商赋能,并为其搭建起与商家间交易合做的桥梁。前端
服务市场团队在2018年完成了云平台京东服务市场的交接与POP平台京麦插件市场的系统融合,并承载着京东自营与三方愈来愈多服务进行商业变现的业务诉求。相对于传统的电商系统,服务市场面对着的是更复杂的业务领域,更灵活多变的交易组合场景,如何让系统具有积木式赋能的能力,经过松耦合架构设计具备系统高内聚性,把耦合度降到最低,进一步实现较为合理的微服务架构风格的应用系统,期间遇到了很大的挑战也总结了不少经验。本次分享和你们回顾这个艰辛却有收获的过程。sql
2017年末,京东云平台京东服务市场交接到POP平台京麦插件市场进行系统融合,咱们称之为两市融合。两市融合是为了实现对外统一的服务入口,实现两个系统变成一个系统,但当时这两个市场倒是两套完整的系统闭环。数据库
融合项目是对两个市场进行深度的融合改造,融合不只是进行流程融合和数据融合,其中最难的就是同时支持双边业务的并行运行,因此,整个融合过程在服务发布、服务审核、服务展现、服务订购和服务使用等环节对两个系统原业务进行了大量的兼容处理,形成了极高的系统复杂度和极差的稳定性。后端
融合方案并无采起单边市场下线的方案,而是采起了将两个市场裁取缝合的处理方式,交易流程使用了京麦插件市场的流程,商品流程使用了服务市场的流程,这种融合方案如今看来的确不明智。缓存
并行业务的难度在于双边读业务与写业务的同时支持,由于不能简单的下线一边的业务,但当时对数据的读写入口不能彻底梳理清晰,因此融合过程当中对上下游各类业务须要兼容支撑,所以在融合中的过渡阶段产生了三套流程并行的尴尬阶段,而且还须要同时双写三套数据库表及同步多个数据缓存,复杂度可见一斑。服务器
当时两个市场的两个数据库是独立对外提供数据服务的,如何将两个数据库变成一个数据库,是当时最大的难点。数据结构
并且服务市场做为一个交易系统,数据库是系统的核心,不只MySQL有不少从库,还有Redis、ES、Solr、HBase等做为数据缓存,因此在数据异构方面作了不少功夫。架构
流程融合包括服务发布审核流程融合、评价评分流程融合、服务搜索流程融合、订单订购流程融合、结算流程融合、退款流程融合、取消订单流程融合和发票流程融合等等。并发
以订单订购流程融合为例,因为服务市场和插件市场融合切换是无缝的(不能停服务),且两侧订购、订单数据结构又不彻底一致,同时数据切流又是逐步放量。因此订购、订单流程的融合采用数据库双写的方式,所谓双写方式,是在写原服务市场数据库和插件市场数据库时,经过订阅Binlog,使用BinLake框架订阅写入sql再整理数据写入新数据库。最终全部服务经过调用新库进行查询服务。框架
这种双写机制能够很好的进行回滚,当新流程出现问题的时候,能够切回到老数据库进行降级。当新订购流程出现问题时,也能够经过关闭切流控制影响范围,采用老流程进行订购订单处理流程。
这里补充说下,插件市场和服务市场的老流程都是写到各自的老数据库中,而新流程其实也是写到服务市场的老数据库中,新数据库的数据都是经过BinLake写入的,这样保证在流程融合过程当中的数据一致性。
而流程融合完成后,即读入口都切到新数据后,就能够逐步切换写入口了,把两套数据库变成一套数据库。切换的方式其实很简单,主要是经过配置中心进行逐步切换写流程,但要考虑切换失败如何处理异常流,假如遗漏了一个场景,还有业务读老数据库,但这时老数据库里是没有数据的,怎么办?
因此,准备了两套方案,一套回滚,另外一套补偿。考虑到回滚的操做难度很大,由于代码回退、流程回滚可能出现的风险会很高,由于那时数据已经不一致了,因此首选方式是补偿,当数据出现不一致时,启动后端校验Worker将数据补偿到老数据库中,并迅速修复线上问题。
随着融合的深刻,服务市场的架构逐步演进成为经典的三层架构,底部是外部依赖,归纳主要是京东商城和京东金融的中台服务;中间是服务市场的服务层,包括服务引擎、商品中台、订购履约中台和支付中心等系统;上部是服务市场的应用层,包括服务市场大前端、商家工做台、服务商后台等系统。
本着 SOA 微服务化的架构设计理念,将服务市场设计为模块化和层次化的架构风格,高层次模块调用低层次模块,低层次模块经过接口向上提供服务,以实现系统之间的解耦。可是对模块的设计粒度拆分的过细,这使得随着业务的发展,整个系统变得越发复杂,系统之间的业务调用关系也变得越发混乱。
复杂的调用链路,必然形成业务之间的相互影响,因此,经过对服务市场从部署、数据库访问、服务PRC调用、消息接收等进行了纵向垂直部署隔离,分为商智、京麦、服务市场等多套隔离部署层,实现即便任一垂直域不管由于服务器仍是数据库问题,影响不会扩散到其余业务上。
复杂的架构,不只形成新需求消化愈来愈慢,并且系统也越发的不稳定起来,这在将来的发展过程当中,效率和成本都将成为很大的问题。因此,痛定思痛,决定进行简化系统架构,将系统设计的越简单越好,链路越短越好,流程越简单越好。由于‘A调B’必定比‘A调B调C调D’的链路要简单,并且出现问题更易于排查。
因此,咱们进行了逆向微服务化的架构改造,即系统的整合,确立了三个中心和一个引擎的系统架构,且是多层次的服务对外提供服务,而不是由一个中心层统一对外,要去中心化,微服务化的架构设计思想也是去中心化,即每一个中心均可对外提供服务,由于层次下降和纬度下降以后,就很是容易定位问题。
系统复杂度等于系统个数加上系统之间的调用链路个数,相比简化以后的架构,可见系统复杂度下降了多少。并且还在业务侧逐步改造、迁移、下线一些老业务服务或功能,这至关于给系统作了瘦身,将无效代码都清理掉了。
通过改造后的服务市场,因为系统进行了整合,系统变少了,虽然系统的隔离防腐在部署上看似没有什么变化,但每一个系统横跨的业务层是变多了的,我我的认为这实际上是就是组件化的方式,就是一个系统能够复用给多个业务场景。
随着两市融合的终结,流程融合和数据融合的完毕,系统实现了统一的服务层,这使得对外提供服务的难度下降不少,不然一个服务在多个系统提供类似的功能,这出了问题是很难快速排查的,因此融合不完全是没法实现服务化的,服务化也要求必须统一入口、统一流程化。
所谓系统架构的终极思想,就是下降软件复杂度,不是把系统作的越来复杂,而是把系统复杂度作的愈来愈低。
当系统实现服务化以后,单品页就不会三千多行的代码的业务逻辑,还调用了不少接口,而是经过服务化在Action层进行服务接口的整合。同时,也能够灵活的实现各个服务的降级处理,以提升系统的稳定性。
MySQL做为当今主流的数据库,业务中若是使用的好的话,决定能扛住上百万,甚至上千万的量,可是如今大多数系统作不到,这种状况下就要考虑如何作到MySQL防护。服务市场是一个交易系统,若是把库打挂了,那将形成系统不能生产,业务不能收钱,这是很是严重的线上事故。
早期的缓存架构设计是Jvm-Redis做为热点缓存,可是在冷启动状况下,可能会出现缓存穿透,形成MySQL出现很大压力。因此,后期设计彻底避免这种穿透的可能,Redis彻底做为数据存储,与MySQL进行隔离,Redis查询不到数据,就直接返回,与MySQL的数据一致性经过数据异构来实现。
服务市场使用BinLake进行数据异构,即经过订阅MySQL的Binlog日志,经过接收JMQ进行数据异地构建存储。
数据异构主要有两种方式,一种是顺序消费、另外一种是并行消费。其中,在进行订单、订购的数据异构时是要求保证严格的顺序性的,由于并行消费是没法保证订单的前后顺序的,因此可能形成数据不一致。
但顺序消息的问题主要是单点消费效率慢的问题,以及消费出了问题就会形成阻塞,以前使用服务器进行消费,经过ip限制保证单点,后期切换到流式计算平台(strom/flink)进行处理,流式计算在并行写es和jimdb有自然的优点,但若是异常状况下出现写操做失败,对于JMQ的重试系统要作好幂等操做的处理。
而商品数据异构是使用并发消费的,由于商品数据不须要保证严格的顺序,但商品数据异构的问题,是一条商品数据在MySQL中是存在多张表中,而异构到ES或JimDB中就是一条记录,那对于商品数据是订阅那哪些表的Binlog呢?
因此,咱们的实践中商品数据异构是订阅商品的主表,其余信息经过反查数据库获取的。但这个场景下,并发消息虽然会提升处理效率,但因为反查数据库会形成额外的IO开销,并且反查数据库仍是主库,由于BinLake和数据库主从同步都是基于Binlog,这二者之间的速度是没法保证谁先谁后的。
最后,考虑系统谁也没法保证不出问题,因此还使用定时任务在天天一个时间点进行数据一致性的校验。
在过去的一年里,不只服务市场的系统架构发生了巨大的改变。在融合以后,思考的重心也逐渐变成了如何将愈来愈多的服务接入到服务市场上进行售卖,因此,工做上,一是对服务市场已售卖的服务进行搜索优化、对前后端类目进行解耦、优化排行等,二是丰富服务市场业务场景覆盖度,快速接入多样服务入驻服务市场。
并经过拆解业务、抽象规则、能力下沉,构建积木式的交易服务平台,实现快速接入官方&三方服务,赋能开普勒、无界零售、7Fresh、国际站等多个业务场景。
服务市场经过服务交易能力提高项目,实现了服务交易流程配置化,将早期入驻服务市场时间须要花费2~4周减小到0天。
所谓交易管道,简单说,就是当有一个订单来了,经过一个流程从订购、订单、支付、台帐、发票、退款等节点往下走,这就是一个管道。可是,若是每有一类服务,就作一个流程,如SAAS一套流程、质检一套流程、ERP一套流程等,那最终只能经过堆人的方式进行开发,而这种开发效率也是极低的。
其实,经过对业务不断的沉淀,你会发现大多数服务流程都是有不少类似性的,惟一不一样的就是之间的配置,那咱们把这个能够复用的功能提炼出来,称为配置中心,用工做流的方式驱动这些数据在管道中进行流转,这就是流程配置化。
配置中心采用多级缓存、数据库拖底的方式来保障交易参数获取效率和高可用,因此,在整个交易的全生命周期里,都会依赖于配置中心,基于配置中心的参数进行流转。
所谓商品模版化,就是对商品的属性进行纬度化和属性化。
参考京东商城的服务发布流程,一个实体商品的发布信息,主要包括商品信息、商品属性、图片、简介,及最重要的销售属性。一个商品能够认为是一个SPU,而SKU是经过多个销售属性组合而成的,一个SKU才会肯定惟一的价格和库存。
基于模版引擎,在规则上进行剥离,在服务属性低耦合下,能够经过模版的方式自定义一些服务的发布信息和规则,并实现属性与履约规则的配置关联,做用于交易和订购履约中。
服务市场发布的SAAS服务都是须要进行履约的,履约的方式主要有周期+版本、周期+模块、数量+模块等,其中版本与模块的区别在于订购时升级与续费的逻辑不一样。那发布服务的销售属性如何与履约规则进行配置关联,咱们比较了三套方案,最终使用的是方案三。
最后,但愿将京东服务市场打形成为精品的交易服务平台,作到服务市场更加稳定、交易流程更加便捷、接入服务更加高效。
同时,服务市场团队也在不断壮大,新思想的碰撞,有好的方面、也有坏的方面。我但愿用本身的行动,不断影响团队,让团队变得更有凝聚力、更有战斗力。
做者:张松然
京东服务市场应用架构负责人,京东集团商家研发部架构师。10年的软件开发和设计经验,丰富的构建高性能高可用大规模分布式系统的研发、架构经验。在京东的五年多时间,负责了京麦平台的升级改造及历次618和双11备战,最近负责了京东服务市场应用系统的总体架构设计工做,对松耦合平台系统和微服务架构进行了深刻而有益实战。