SockShop系统服务划分与设计

我们已经熟悉了ServiceComb以及ServiceStage。从本章开始,我们将基于Weaveworks开源的SockShop,虚构一个SockWorks公司服务化的案例。同时,在这个过程中,使用ServiceComb进行微服务的开发,并基于ServiceStage完成服务的部署和维护。

本章将聚焦SockShop系统的需求分析以及主要的设计。同时,也完成持续集成、预生产环境、生产环境的搭建。

9.1 系统综述

SockWorks是一家专业从事袜子设计、生产与销售的传统公司,每年会有1000余款时尚经典花型的袜子不断更新并上市,产品远销海内外。公司在线下的袜子销售业务发展稳定,但是随着网上购物的普及和消费观念的转变,以及来自于竞争对手的压力,SockWorks在线下的销售逐渐趋于饱和。公司的CEO决定利用现有的线上系统,快速推出新特性,吸引更多客户,并增加用户黏度,拓展业务。

然而在和CTO沟通后,CEO发现存在一些问题:

SockWorks公司的在线袜子商店系统SockShop是基于SpringMVC开发的单体应用,代码库庞大,变更困难。

SockWorks公司的软件开发的过程还是瀑布式,交付周期超过30天。

SockWorks公司的IT组织结构属于矩阵型,开发、测试、运维分属不同的部门,沟通成本高。

SockWorks公司的IT部门自建了相关的基础设施,但是运维自动化水平不高,运维人员大多数的时间都花费在解决生产环境问题上。

这些问题导致现有的SockShop系统无法满足CEO的期望。SockWorks的CTO认为,要实现CEO的想法,可能需要对系统架构进行改造。但是他们不确定以下几个问题:

当前的SockShop系统是否适应于微服务架构。

如果适用,是选择对原有系统解耦还是重新实现。

如果SockWorks的IT组织所处的阶段需要做哪些事情可以助力推行微服务。

于是,SockWorks公司基于第二部分提到的适应性评估以及微服务参考模型,利用微服务在线评估系统(http://tinyurl.com/cse-evaluator)快速进行了适应性评估和微服务成熟度评估,发现虽然SockShop系统适于微服务架构,但是SockWorks公司的IT组织在全功能团队、部署管理、运维管理、测试管理等维度都处于较早阶段。随后ServiceStage的顾问深入SockWorks公司,通过和团队中不同角色,架构师、开发人员、测试人员、产品经理的沟通,梳理清楚了产品的价值流映射图。SockWorks原有产品的价值流映射图,如图9-1所示。

图9-1 SockWorks原有产品的价值流映射图

从价值流图中发现产品在开发、测试、部署阶段存在的问题。

开发:从需求规划到开发完成周期为13天。造成这一问题的原因是应用代码量庞大,模块间耦合大,需求的分解粒度比较粗,每个Story的工作量有800行以上的代码。同时,受开发流程制约,需要统一Story的开发计划。

测试:测试周期为8天。矩阵型组织结构导致开发团队和测试团队分离,反馈周期长。自动化测试覆盖率不足10%,只有少量单元测试、组件测试,无集成化测试,端到端测试以手工为主。

部署:部署周期长达13.5天。原因包括开发人员和运维人员分属不同团队,版本发布整体规划、部署的区域较多,过程为手动。

并从中发现导致产品发布周期长的主要原因如下:

产品主体为单体应用、代码庞大、服务耦合性要求严重、技术落后、拆分成本太高、变更困难。

交付过程缺乏自动化测试、部署,没有建立交付流水线,效率低。

根据当前所处的状况,基于微服务实施参考模型,顾问为SockWorks制定了两个阶段的演进计划。

第一阶段主要包括:

应用微服务架构,通过领域驱动设计的方式,重新设计整个SockShop系统。

采用 ServiceComb 微服务开发框架实现第一个SockShop系统的微服务。

在实现第一个微服务时,尝试自动化测试、持续交付部署等,提升团队在这些维度的能力。

将微服务部署在 ServiceStage 集群中,实现自动化的部署。

第二阶段主要包括:

复制第一个阶段的实践,采用相同方式实现SockShop系统剩余的微服务。

在ServiceStage集群上实现对整个SockShop系统的编排。

利用ServiceStage的服务治理、监控、运维能力对SockShop系统进行高效运维。

在本章中,笔者将基于这两个阶段的计划,分别实现SockShop系统的不同服务,并利用ServiceStage的运维能力实现自动化运维。主要内容包括:

以持续交付的方式,使用Java Chassis实现SockShop系统的第一个服务。

使用Go Chassis、Nodejs实现其他服务,并通过Mesher来接入Nodejs应用。编排部署和运维SockShop系统。

接下来让我们看看如何实现全新的SockShop系统。

本书为了方便起见,在实战篇中使用了ServiceComb作为微服务开发框架,华为云的ServiceStage作为持续集成、部署、运行的平台。实际上,微服务的实现也可以使用其他框架(如SpringBoot、Spring Cloud、Finagle、Nodejs、Golang等),持续集成也不局限于任何工具(Jenkins 2.0、Travisci、ConcourseCI、Buildkite等),读者可以基于具体的需求进行修改。

SockWorks公司是笔者虚构的,是为了展示利用参考模型进行微服务演进的过程。SockShop系统的实现是在weaveworks已有的SockShop Demo的基础上进行改造的。

9.2 需求理解与分析

9.2.1 总体需求

SockWorks的产品经理认为SockShop系统需支持用户完成注册、登录,并支持商品的信息进行浏览、加入商品到购物车,以及结算、支付和订单查询的等功能。具体功能如下表所示。

除了表中所列的基本功能之外,在系统首个版本上线后,根据线上销售业务的情况,公司会进一步考虑推出购物卡、丰富会员机制,并实现商铺加盟、在线交流等高级功能。

9.2.2 其他非功能性需求

在与产品经理进一步的沟通中了解到,由于袜子是快消品,普遍以薄利多销为主,这意味着订单数量巨大,用户访问量较高,尤其是在活动促销期,线上袜子商店需要应对比平时高出许多倍的流量,产品经理希望SockShop也能够应对这种突发情况。因此,为了能够给用户流畅的购物体验,系统的核心功能应该能够快速伸缩,避免资源不足和浪费。在公司业务发展、用户急剧增长的过程当中,需要通过可靠性措施来避免出现系统不堪重压而崩溃等问题。

同时,对于SockShop这种传统企业来说,希望能够降低运维成本,因此在系统上线之后,出现故障时需要能够让运维人员快速定位故障问题,解决故障,减少人力成本、减少系统故障带来的商业损失。同时在当系统发布新功能时也不能引起业务中断。为了能够让SockShop系统尽快上线提供销售服务,以应对来自竞争对手的压力,又能够满足将来公司的扩张诉求,从而减轻公司库存压力和运营成本,需要开发团队能够快速开发出核心功能交付上线运行。

以上便是SockShop系统的功能和非功能性需求,公司希望技术团队能够聚焦业务,降低开发成本,使系统快速上线,并能利用自动化的监控运维机制,应对瞬息万变的销售市场。

9.3 服务划分与设计

SockWorks公司不仅希望新的SockShop系统能够快速稳定上线新特性,同时也希望在活动促销期间系统流量增加时系统能够伸缩,在系统不堪重负时核心功能依然能够提供服务。在第1章“微服务架构综述”中,笔者提出了创新软件的四个“S”,即Speed、Safety、Scale、Sharing,这也正是SockShop系统所需要具备的。

通过微服务的适用性评估,团队一致认为该业务可以采取微服务架构实现。同时,IT团队希望能发挥微服务架构的优势,采用异构技术来实现不同的服务,提高团队成员的技术储备与开发效率。

另外,有效拆分业务逻辑是微服务化架构设计的一个重点。SockWorks的IT团队在设计新的SockShop系统时,采用了领域驱动设计的方式,对SockShop系统进行业务梳理以及划分。

9.3.1 建立统一语言

建立统一语言是领域驱动设计的核心,它一方面帮助技术人员快速理解业务,另一方面保证设计的持续演进。在SockShop系统中,架构师、软件开发人员首先与领域专家沟通,了解到系统需要提供以下核心功能:用户注册、登录、浏览商品信息、购物车、下单、支付以及历史订单查询功能,通过对这些需求的梳理,提取出核心业务名词,作为该系统的统一语言,如图9-2所示。

图9-2 SockShop系统的统一语言

在后续的实现过程中,领域专家与开发人员、开发人员内部之间,将使用上述术语进行讨论,比如在SockShop系统中,提到“商品”就代表袜子。在开发人员的代码实现中,也会使用上述术语实现业务逻辑。

9.3.2 业务流程梳理

通过领域专家与开发人员的沟通,团队在理解了业务的基础上,梳理出了用户的购物流程,如图9-3所示。

首先用户在完成注册或登录后,可以进行历史订单查看或者浏览商品,如果对某商品感兴趣,可以查看商品的详细情况。将商品加入购物车后,用户可以继续浏览商品,也可以进入到购物车内查看并下单。在下单过程中,分别需要填写收货地址信息和支付信息,在确认订单后选择提交订单。当物流到达后,用户确认收货。

图9-3 用户购物流程

9.3.3 采用事件风暴进行领域建模

在梳理出业务流程后,SockWorks的IT团队采用事件风暴进行领域建模。事件风暴(Event Storming)是由Alberto Brandolini提出的一项团队活动,旨在通过领域事件识别出聚合根,进而识别出限界的上下文,指导团队进行服务划分。关于事件风暴的更多内容,请读者参考《Introducing Event Storming》。

首先,团队根据业务流程识别出领域事件,并按照时间序列进行组织,其结果如图9-4所示。领域事件是领域驱动设计中的一个概念,以数据的形式来记录业务事件,用于捕获所建模的领域中所发生过的事情,通常用“已发生”时态来表达。

图9-4 领域事件

接下来团队对产生事件的命令进行建模,输出的命令如图9-5所示。命令是触发领域事件的源头,它可以是用户通过界面进行的操作,可以由外部系统触发,也可以是定时任务。

图9-5 命令模型

最后,团队基于命令与领域事件,识别聚合。聚合是领域驱动设计中的概念,它由一组相关的领域对象构成,目的是确保业务规则在领域对象的各个生命周期中都得以执行。聚合接收命令并产生领域事件,处于聚合内的对象,只能通过聚合根对其修改。

系统地梳理出用户、商品、购物车、物流、订单各个聚合,由于这几个聚合较为独立,可以分别形成用户子域、商品子域、购物车子域、物流子域以及订单子域,至此,系统的限界上下文整理完毕。识别聚合的结果,如图9-6所示。

图9-6 识别聚合的结果

9.3.4 服务划分

根据上面梳理出的限界上下文,将系统拆分为用户服务、商品服务、购物车服务、物流服务以及订单服务。

图9-6中的领域模型没有涵盖支付功能,针对这种情况,一种方式是将支付功能放在订单服务内部;另一种方式是将其作为独立的服务。

如果在业务梳理的过程中抽象出交易模型(Transaction),用于记录每次支付或退款过程,便可划分独立的交易服务或支付服务。此处由于简化了购物的处理流程,因此没有抽象出独立的支付服务。

对于物流相关逻辑,也可以抽象出独立的物流服务,对接第三方物流公司的接口,并与实际的物流解耦。对于上述的各个服务,需要一个用户界面服务将整个流程贯穿起来,负责用户的接入。通过定义用户界面服务,既可以用来接入用户请求,又可以起到聚合的作用。

此外,在用户界面服务后面需要一个认证授权服务,用来验证对后台服务的请求是否合法,即用户是否是已登录的合法用户。由于后台服务都是无状态的,用户的登录信息包含在请求所携带的Token中,因此认证授权功能主要通过对Token的校验来完成,认证授权服务将主要负责用户登录注册后Token的生成与校验。如果把用户界面服务本身看作一个网关,那么认证授权功能也可以位于用户界面服务中。

本书中主要为了演示基于ServiceComb的业务功实现,因此并未考虑复杂的认证授权功能。最终,SockShop系统将包含以下服务:

用户界面服务(Frontend Service)

用户服务(Users Service)

购物车服务(Carts Service)

订单服务(Orders Service)

商品列表服务(Catalogue Service)

支付服务(Payment Service)

物流服务(Shipping Service)

来都来了,走啥走,留个言呗~

IT大咖说 |关于版权

感谢您对IT大咖说的热心支持!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190903A0NI1100?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券