京东7Fresh新零售架构设计分析
7fresh是京东第一个线上线下融合落地的零售创新业务模式,店内有大量设备的集成,设备供应商达50多家,针对线下业务的特点,团队独立规划和设计pos收银系统、店内生产系统、加工系统、货架陈列系统、魔镜系统、餐饮系统、自助收银系统等共60多个系统,对接电子价签、电子秤、包装机、无人购物车、门店客流检测等几十种设备。
第一期上线40多个系统,后续又高效上线了其他新增20个系统,短时间内完成了别人口中不可能完成的神话。今天我就带您一同回顾7fresh系统从0到1的快速构建之路!
01 系统构建历程
7fresh与京东商城一样拥有一整套的交易系统、一键结算系统,但和线上不一样的是,我们还有很多线下系统,店内的生产、加工、库存管理、餐饮等等。
整个项目从产品调研、架构设计,到第一期上线经过了2个半月的开发。第一期就有40多个系统同时上线,基本能把所有的业务系统运行跑通,之后又增加了很多餐饮类,地推类和线下有关的新需求,现在也依然在落地新的需求中。
02 快速开发的主要原因
1、用ddd进行战略设计
•分治
•界限上下文内的技术无关的通用语言
•薄薄的技术集成层隔离业务变化
2、虚拟组织保障设计落地
•早期组成虚拟的架构师组织,后期产品也加入
•不断摸索方法论和原则
3、其他因素
•多团队协同包括成都、武汉、技术拓展等部门
•框架和组件积累,之前积累的pop-spring-boot和popdesign及脚手架
•业务团队的大量参与,与业务开展同步进行
03 我们对ddd的理解
1、首先是战略部分,这也是我们认为实施比较好的部分:
(1)划分和集成界限上下文。
这个虽然不是技术上的问题,但是最关键的还是对业务的理解,跟部门业务专家一起工作很重要,另外是参考了京东现有的情报,做了很多的改进。怎么把系统进行解耦,这个领域边界界定以后,首先上下文最重要的是界定通用语言,就是在一个上下文里边有一套完整明确的概念:一个店就相当于一个仓,wms开始设计的时候概念方式是管理统一sku。而我们线下店有做蛋糕、做餐饮这些场景,加工的原材料也应该在系统里,wms如果强绑定销售商品的sku的话,那我们线下店就没法管理了。
所以,经验就是不能把一个概念应用超出上下文界定的领域,这样做的好处就是,通过这种方式隔离一些变化,适应更多的场景,实现解耦。
(2)面向服务集成而不要面向数据集成。
如果这样的话就能解耦了吗?
随着一些新需求的推进,还是发现里边有些耦合存在。总结的经验就是:下游的系统应该对需求做抽象,提出自己的标准,这样才能实现解耦。做ddd领域设计的时候,不应该受到具体架构风格、模式的影响,不管是微服务的还是单体加模块化的风格,最终的效果应该都是一样的,界限分明。
(3)技术无关地考虑领域模型,比如使用类图,定义和功能场景甚至状态图和对象快照。
2、使用ddd进行战略设计相对容易落地,收益明显。在使用ddd进行战术设计却遇到了重重困难。
战术部分在落实到代码层面遇到了困难。看过业内关于ddd的分享,发现其实大家能把战术层面把ddd落地的,其实都做的不理想。以下是我们对战术层面上的理解:
(1)代码即设计
代码即设计,在代码中尽量表现出想要的设计意图和领域意图,但是像性能这类的属性很难表现出来,能够实现但却不能表现意图。而领域设计是比较能在代码层面表现出来的。
难点一:聚合根识别困难
难点二:贫血模式。基本我们的框架和思路,很机械式的编码和设计,很难实现上述的目标;
难点三:按ddd的理论,聚合根之间不赞成使用数据库事务,成本很高。
(2)用包来体现实体概念
左图中间的部分就是领域模型,这也是现在比较通用的方式,领域模型包括领域对象、领域服务,领域对象总是要被存储的,这就需要依赖于仓库,仓库在领域下应该是个接口,我们认为领域应该依赖于技术实现,存储的实现应该在另外一个包下,通过依赖倒置的方式,把领域模型包含的东西和基础设施层分隔。
(3)订单状态变更的例子
现在有很多不同类型不同场景产生的订单,它们之间的状态变更是不同的,从未支付到已支付再到在拣货,当中有很多状态是不一样的。如下:
从设计层面可以划分不同的状态设计,但是最后状态无非是当前状态,编码实现上就目前来看,写在service层到处都是判断……,来一个新业务就要改一次新判断,但是我们现在从构思想,简单来说先把它放在order对象里,因为这只跟order的数据有关系。
从集成的角度来说,如果支付系统接收到支付完成的消息,我们把消息payevent变成一个事件,传给了orderservice-changestate,orderservice里边非常简单,把order从仓库里边加载出来,然后调动方法即可。
大部分业务里的规则还是在orderchangestate方法里。这么做的好处就是,它能够表达出我想要的设计意图,如果分散在其中的话,可能只与设计文档不一致。
第二个就是说,把领域规则识别出来放在对象中会带来额外的好处是,领域规则往往跟外部是没有关系的,很容易做纯粹的自动化的单元测试。
(4)数据一致性和领域事件
一个微服务内部的多个聚合根,可以使用数据库事务保证数据一致性,虽然不完美,但还算实用。用领域事件去做最终一致性成本太高。
两个上下文之间用mq做最终一致性
本文转载自:http://www.dalbll.com/group/topic/architectureddesign/5011