DDD领域驱动设计指导思想

微服务是一种软件架构模式,其中软件是由通过明确定义的轻量级API(通常是HTTP资源API)进行通信的独立服务组成。这些服务由小型独立团队维护。

2014年Martin Fowler提出微服务概念,具有服务组件化去中心化基础设施自动化单一的业务职责以及可灵活调整的技术栈实现,微服务架构使应用程序更易于扩展和和快速交付。

单体架构到微服务架构演变

微服务不是“银弹”。随着从单体架构过渡到微服务架构软件,将原有系统拆分后,增加了系统不稳定性。

单体架构:

单体架构把所有程序紧密耦合,作为单个服务运行。这样存在问题,如果应用程序增加新需求,则要扩展整个架构。也增加了代码结构的复杂性,复杂性限制了试验的可行性,同时增加了可用性的风险。因为许多紧密耦合的程序会扩大单个进程的故障的影响。维护成本越来越高

微服务架构:

通过把应用程序构建成独立的组件,将每个应用程序作为一个独立的服务运行。这些服务通过明确定义的轻量级API进行通信。微服务是围绕着业务能力构建,每个服务执行一个功能。由于每个服务独立运行,因此可以针对各自的服务进行更新、部署和扩展,以满足应用程序特定的功能需求。

微服务架构的新挑战

  1. 微服务通信方式

进程内通信变成进程间通信,进程间通信是架构复杂系统的基石。分布式系统中会存在网络三态和异构系统集成等因素导致远程调用发生异常,微服务作为分布式系统延伸也存在这样的问题,架构设计时必须考虑上下游系统因为网络因素导致无法通信的情况,假设服务和网络是不可靠的,并设计实现服务调用者在网络异常时的处理策略。比如订单交易依赖消息中心,消息中心服务提供者或者网络不可靠时不会影响订单业务的正常运行。

  1. 服务间响应延迟

网络传输和消息序列化带来的延迟很大。

  1. 微服务运维

原来只需要部署单个应用程序,现在变成同时要部署多个服务多个实例情况。需要考虑如何持续集成,持续发布。

  1. 微服务组织

微服务不仅是架构模式,也是一种软件组织模型。微服务实施过程中,是按业务模块,进而团队划分,团队是高内聚的。在基于微服务设计的团队里,一个很好的理念是自管理。团队内部对于自己所负责的模块高度负责,进行端对端的开发以及运维。

  1. 微服务拆分

业务由简单到复杂转变过程中,需要对原有应用打撒,拆分多个微服务。如何合理拆分,真正发挥微服务的价值,参考推荐DDD领域驱动来指导程序设计。

  1. 微服务集成测试

对于微服务的测试,必须搭建完整微服务环境。因为微服务是跨网络通信,网络延迟、超时、带宽、数据量等因素都将影响最终测试结果,易产生偏差。

微服务特性

专一性:每个服务都是根据业务功能构建,并且专注于解决特定的问题。如果每次需求变更,在原有服务结构中增加代码,会变得复杂难以维护,需要拆分多项更小的服务

自主性:可以对微服务架构中的组件进行独立设计、开发、测试、部署到运维完整的生命周期,不影响其它服务的功能。服务之间不需要共享代码,各个组件之间的通信通过明确定义的API进行。

  1. 敏捷性:

微服务促进小型独立团队形成组织,这些团队负责自己的服务。团队更熟悉的环境中工作,可独立,快速工作,缩短了开发周期。

  1. 灵活性

第一:通过微服务,团队可以独立适当调整基础设施需求,弹性扩容,保持服务可用性

第二:技术栈实现自由,构建微服务的团队可以为每项作业选择最佳工具。

第三:整体式架构中,如果某个组件出现问题,会导致整个应用程序无法运行。对任何单个模块的更改都会导致不得不重新部署整个应用程序。通过微服务,应用程序可以通过熔断而不导致总体服务故障。降低故障成本。

  1. 可复用性: 

软件被划分为小而专的模块,通过组件化的服务,可以用作其他服务的支撑服务,无需从头开始编写代码。通过插接组件来构建系统。

  1. 部署自动化

服务实现组件化,服务是可独立部署。微服务支持持续集成和持续交付,程序无法正常运行时可以快速回滚。

微服务架构使用场景

单体应用程序对于UU跑腿平台期初是成功的,随着软件有简单到复杂的变化发展规律,软件趋向更客观真实逻辑,需要更大规模的应用部署到云上支撑业务。对应用程序的局部更改,都需要重新部署整个项目。我们应该保持一个良好的项目结构,只影响程序的某个模块。于是使用领域驱动设计(Domain Driven Design,DDD)方法,通过识别领域中的各个子域,明确子域之间的关系,划分如下业务架构:

微服务拆分过程中,从业务场景、团队能力、组织架构多种因素综合考虑。比如前期只有订单域,由于订单需要对接第三方运力平台,原来订单需要拆分订单域和配送域,需要更细粒度拆分订单,然后有专门的团队负责维护。

微服务业务划分根据以下原则:

单一职责原则:

单一职责原则是软件设计非常重要的原则,这个术语由 罗伯特·C·马丁(Robert Cecil Martin)在他的《敏捷软件开发,原则,模式和实践》一书中的一篇名为〈面向对象设计原则〉的文章中给出。

马丁把功能(职责)定义为:“改变的原因”,并且总结出一个类或者模块应该有且只有一个改变的原因。在微服务中每个服务只完成自己职责范围内的事,而将其他事教给别人去做,然后我只要通过接口调用。 

一个具体的例子就是,用户等级和用户管理两个服务,用户等级管理新增、修改等级信息。用户管理负责信息编辑。等级变更时,用户不需要变更。用户变更时,等级不需要变更,它们是软件变更的不同原因。于是把它们划分成用户等级服务和用户管理服务两个服务,每个服务只负责自己职责范围的事,遵循微服务内高内聚,微服务间低耦合原则。

DDD中的限界上下文,是高质量软件设计单一职责的要求体现,每个限界上下文中实现的都是软件变化的同一个原因。当用户提出一个需求变更时,设计修改的模块越少,软件设计质量就越高。如果实现一个需求需要改动多个模块,那么需要测试多个模块,把业务相关性的业务归类,提炼共同特征划分在同一模块上下文维护,这样就降低了维护成本。  

两个比萨原则:

所谓两个比萨原则是指团队成员的人数相当于可以吃掉两个披萨。人数太多,不利于项目会议决策。适当职责更容易让团队达成共识,保持敏捷和创新。微服务应该涵盖从需求分析到运维完整生命周期。对于复杂的,需要协作完成的系统开发,沟通是必须要持续提升的问题。 每个团队由5-10人组成(沟通成本 = n(n-1)/2) ——《人月神话》,在团队内部进行频繁的、细粒度的沟通。对于团队外部,定义好接口,契约,只进行粗粒度的沟通。这样可以降低沟通成本,同时也符合高内聚,低耦合原则。

微服务架构技术体系

实现微服务技术体系结构非常困难,需要解决8大问题。NetFlix开发了一个微服务框架SpringCloud生态系统来支持应用程序。

服务通信:

服务是与诸如web服务请求或远程过程调用等机制通信的进程外组件。基于TCP协议的网络连接有两种基本方式:长链接和短连接。通俗点讲:短连接就是一次TCP请求得到结果,链接立马结束。而张连杰并不马上断开,而是一致保持着,直到长链接TIMEOUT,长链接避免不断的进行三次握手和四次挥手。长链接和短连接产生在于客户端和服务端采取的关闭策略。SpringCloud采用的是短连接,Dubbo框架采用的是长链接。

配置管理:

微服务应用程序的配置需要从代码中进行外部化,使用动态配置服务中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。下图是配置服务常见功能:

  1. 在线编辑
  2. 历史版本
  3. 一键回滚
  4. 灰度发布
  5. 推送轨迹

服务发现:

维护微服务域中可用于工作的服务实例列表。通过服务治理实现服务自动化注册和发现。服务注册中心是一个服务。它可以管理是咧和微服务可以有多个实例服务实例在启动时注册到服务注册表,并在关闭时注销。

负载均衡

扩展分布式系统的关键是能够运行一个组件的多个实例。然后要通过负载均衡器将负载分配到这些实例上。

API网关

微服务提供的API的粒度通常与服务客户端需要的粒度不同。API网关实现表层,并提供其他服务,如代理、协议转换和其他管理功能。

在微服务架构中,需要再服务提供者和消费者之间架设API网关,屏蔽内部系统实现,来满足服务路由和控制的各种场景。

服务容错:

分布式系统必须能够围绕故障进行自动路由,并且能够将请求路由到提供最佳响应的服务实例。

服务在自身失败发生错误的同时,还会因依赖其他服务而导致失败,由此引发服务雪崩。一般会从超时、重试、异步解耦手段处理,还需要各种场景的容错机制。

服务安全

许多安全问题推给API网关来实现。对于分布式微服务应用程序,不重新造安全方面的轮子,允许在所有服务共享的组件中进行策略定义和实现是有意义的。

服务监控

拥有一个ELK集中化的日志收集和分析基础设施来管理大量的服务非常重要——其中许多服务是以分布式方式运行的。

一个可以监控单个服务和整个系统的健康和性能的集中区域对于正确的操作是必不可少的。

打包、部署和调度: 大规模系统需要健壮的包管理和部署系统来管理滚动部署或蓝绿色部署,并在必要时进行回滚。调度程序帮助确定可以根据当前条件将一组新服务部署到哪个特定的执行节点。

微服务架构研发过程

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注