当前位置: 首页 > 科技观察

微服务架构与设计模式

时间:2023-03-16 00:42:11 科技观察

本文介绍了主流和常见的微服务模式。微服务可以对企业产生积极影响。因此,了解如何处理微服务架构(MSA)和一些微服务设计模式、微服务架构的一些总体目标或设计原则是很有价值的。以下是微服务架构场景中值得考虑的四个目标。1.降低成本:MSA将降低IT服务设计、实施和维护的整体成本2.加快发布速度:MSA将加快服务从构思到部署的落地速度3.增强弹性:MSA将提高我们的效率服务网络弹性4.开启可见性:MSA支持更好的服务和网络可见性。你需要了解构建微服务架构背后的几个设计原则:可扩展性、可用性、弹性、灵活性、独立性、自主性、自治性和去中心化治理。隔离自动装配通过DevOps持续交付听到上述原则,这也带来了一些挑战和问题,同时您实施的解决方案或系统付诸实践。这些问题在许多解决方案中也很常见。这些问题可以通过使用正确且匹配的设计模式来克服。微服务有几种设计模式,大致可分为五类。每个类别都包含一些特定的设计模式。下图说明了这些设计模式。分解方式按照业务功能进行分解。说白了,微服务就是应用单一职责原则,将服务转变为松耦合的服务。它可以按业务功能进行细分。定义业务功能对应的服务。业务能力是源自业务架构建模的概念。这是企业为了创造价值所做的事情。一个业务功能往往对应一个业务对象,例如:订单管理负责订单客户管理负责客户按问题子域分解按业务功能分解应用程序可能是一个好的开始,但你最终会遇到当它谈到所谓的“神明”,就很难分解了。这些类将在多个服务中通用。可以定义一些与域驱动设计(DDD)中的子域相对应的服务。DDD将应用程序的问题空间(即业务)称为域。一个域由多个子域组成。每个子域对应于业务的不同部分。子域可以分为以下几类:核心-业务的核心能力和应用程序基础中最有价值的部分-与业务相关但不是核心能力。这些可以在内部或外包实施通用-不特定于业务,最好使用现成的软件实施订单管理的子域包括:产品目录服务库存管理服务订单管理服务运输管理服务按交易/两个-phasecommit(2pc)分解模式您可以按事务分解服务。那么,这样一来,系统中就会出现多笔交易。事务协调器是分布式事务处理的重要参与者之一。一个分布式事务包括两个步骤:PreparePhase-在这个阶段,事务中的所有参与者都准备好提交并通知协调器他们已经准备好完成事务CommitorRollbackPhase-在这个阶段,事务协调器发送一个向所有发出提交或回滚命令的Actors发送消息2PC的问题在于,与单个微服务的运行时间相比,它非常慢。即使这些微服务运行在同一个网络上,它们之间的事务协调也确实会拖慢系统,所以这种方式通常不适合高负载的情况。StranglerPattern以上我们看到的三种设计模式都是用来分解绿地(Greenfield)应用的,但往往我们所做的80%的工作都是针对灰场(brownfield)应用,即大型单体应用(legacycodebases)。扼杀者模式可以解决这类问题。它创建两个独立的应用程序,它们在同一个URI空间中并排运行。随着时间的推移,直到最终,新重构的应用程序“杀死”或替换了原始应用程序,此时旧的单体应用程序可以关闭。扼杀应用程序的步骤是转换、共存和消除:转换——使用现代方法创建一个并行的新站点。共存-保留现有站点一段时间。将对现有站点的访问重定向到新站点以逐步实现所需的功能。消除-从现有站点中删除旧功能。隔板模式使应用程序的元素与池相对隔离,以便其他应用程序继续正常工作。这种模式被称为“隔间”,因为它类似于船体的分段分隔。服务实例根据消费者负载和可用性要求分为不同的组。这种设计有助于隔离故障,并允许用户即使在故障期间也能为某些消费者维护服务。Sidecar模式此模式将应用程序的组件部署到单个处理器容器中以提供隔离和封装。它还允许应用程序由异构组件和技术组成。这种模式被称为边车模式(Sidecar),因为它类似于附加在摩托车上的边车。在这种模式下,sidecar附加到父应用程序并为该应用程序提供功能支持。Sidecars也与父应用程序共享相同的生命周期,并与父应用程序一起创建和退出。sidecar模式,有时称为sidekick模式,是我们在本文中列出的最后一种分解模式。IntegrationPatternsAPIGatewayPatterns当一个应用程序被分解成多个更小的微服务时,这里有一些需要解决的问题:从不同的渠道多次调用多个微服务需要处理不同类型的协议消费者可能需要不同的响应格式API网关可以帮助解决微服务实现带来的很多问题,不仅限于上面提到的那些。API网关是任何微服务调用的单一入口点它可以充当将请求路由到相关微服务的代理服务它可以聚合结果并发回给消费者解决方案可以为每种特定类型的客户端创建一个细粒度的它也可以转换协议请求和响应API。它还可以承担微服务的认证/授权责任。AggregatorPattern将业务功能分解为若干个更小的逻辑代码段后,需要考虑如何协调各个服务返回的数据。这个责任不能留给消费者。聚合器模式对此有所帮助。它讨论了如何聚合来自不同服务的数据,然后将最终响应发送给消费者。这里有两种实现方式:1.一个复合微服务会调用所有需要的微服务,组合数据,在传回之前进行转换2.API网关也可以将请求分成多个微服务,然后聚合在将数据发送给消费者之前。如果要应用一些业务逻辑,建议选择复合微服务。除此之外,API网关已经成为解决这个问题的既定事实标准。代理模式是针对API网关的,我们只是用它来将我们的微服务暴露给外界。通过引入API网关,我们能够获得一些API级别的功能,例如安全性和API分类。本例中API网关有3个API模块:1.MobileAPI,实现了FTGO移动客户端的API2.BrowserAPI,实现了运行在浏览器中的JavaScript应用程序的API3.PublicAPI,实现了该API一些第三方开发者需要的网关路由模式。API网关负责路由请求。API网关通过将请求路由到适当的服务来实现一些API操作。当API网关收到请求时,它会查询一个路由映射,该路由映射指定将请求路由到哪个服务。路由映射可以将HTTP方法和路径映射到服务的HTTPURL。这与NGINX等Web服务器提供的反向代理功能相同。链式微服务模式(ChainedMicroservicePattern)单个服务或微服务将具有多级依赖关系。例如:销售微服务依赖于产品微服务和订单微服务。链式微服务设计模式将帮助您提供合并的请求结果。微服务1收到请求后,该请求将传递给微服务2,微服务2也可能正在与微服务3进行通信。所有这些服务都是同步调用的。分支模式微服务可能需要从多个来源获取数据,包括其他微服务。分支微服务模式是聚合器和链接设计模式的混合体,允许同时处理来自两个或多个微服务的请求/响应。调用的微服务可以是微服务链。分支模式也可以根据你的业务需求调用不同的微服务链或者单条链。客户端UI组合模式在通过分解业务功能/子域来开发服务时,负责用户体验的服务必须从多个微服务中提取数据。在单体世界中,它曾经只是从UI到后端服务的一次调用,它会检索所有数据,然后刷新/提交UI页面。然而,现在不同了。对于微服务,我们必须将UI设计为具有屏幕/页面的多个部分/区域的框架。每个磁贴将调用一个单独的后端微服务来获取数据。AngularJS和ReactJS等框架可以帮助我们轻松实现这一目标。这些屏幕称为单页应用程序(SPA)。每个团队开发一个客户端UI组件,例如AngularJS指令,用于实现它所服务的页面/屏幕区域。UI团队负责通过组合多个特定于服务的UI组件来实现用于构建页面/屏幕的页面框架。数据库模式在为微服务定义数据库架构时,我们需要考虑以下几点:1.服务必须是松耦合的。通过这种方式,它们可以独立开发、部署和扩展2.业务事务可能会在多个服务之间强制实施不变量3.一些业务事务需要从多个服务查询数据4.出于可扩展性的原因,数据库有时必须是可复制的5.不同的服务具有不同的数据存储,每个服务都需要一组数据库。为了解决上述问题,必须为每个微服务设计一个数据库。它必须专用于该服务。它应该只能通过微服务的API访问。其他服务无法直接访问它。例如,对于关系数据库,我们可以为每个服务使用单独的专用表(private-tables-per-service),为每个服务使用单独的数据库模式(schema-per-service)或为每个服务使用单独的数据库服务器(每个服务的数据库服务器)。服务之间共享数据库我们已经说过,在微服务中,为每个服务分配一个单独的数据库是最理想的。使用共享数据库是微服务中的一种反模式。但是,如果应用程序是一个整体,而您正试图将其拆分为微服务,那么非规范化就不那么容易了。在稍后的阶段,我们可以转向每个服务一个数据库的模式,直到我们完全做到这一点。在服务之间共享数据库并不理想,但它是针对上述情况的实用解决方案。大多数人认为这是微服务的反模式,但对于灰域应用程序,这是将应用程序分解为更小的逻辑部分的良好开端。值得一提的是,这不适用于未开发的应用程序。命令和查询责任分离(CQRS)一旦为每个服务分配了一组单独的数据库(每个服务一个数据库),查询需求自然会出现,这需要组合来自多个服务的数据。然而,这是不可能的。CQRS建议将应用程序拆分为两部分-命令端和查询端。命令端处理创建、更新和删除请求。查询端使用物化视图处理查询部分。这通常与事件驱动模式(事件溯源模式)一起使用,每当有任何数据更改时都会创建相应的事件。通过订阅事件流,我们可以保持物化视图的更新。事件驱动大多数应用程序都需要使用数据,典型的做法是应用程序维护当前状态。例如,在传统的创建、读取、更新和删除(CRUD)模型中,典型的数据流是从存储中读取数据。它还包括经常使用事务来锁定数据的限制。事件驱动模式定义了一种处理由一系列事件驱动的数据操作的方法,每个事件都记录在一个只能追加的存储中。应用程序代码将一系列事件发送到事件存储。这些事件强制性地描述了对数据执行的每个操作,并将它们持久保存到事件存储中。每个事件代表一组数据更改(例如,AddedItemToOrder)。这些事件将保存在充当记录系统的事件存储中。事件存储发布的事件的典型用途是在实体被应用程序触发的某些操作更改时维护实体的物化视图,并与外部系统集成。例如,系统可以维护填充UI部分的所有客户订单的物化视图。当应用程序添加新订单、从订单中添加或删除项目以及添加运输信息时,描述这些更改的事件将被处理并用于更新物化视图。下图显示了该模式的概览。Saga模式当每个服务都有自己的数据库,一个业务事务跨越多个服务时,我们如何保证服务之间的数据一致性呢?每个请求都有一个补偿请求,如果请求失败,将执行补偿请求。这可以通过两种方式实现:编排——在没有中央协调的情况下,每个服务生成并监听另一个服务的事件,并决定它是否应该采取行动。编排是一种方案,其中指定了两方或多方。任何一方都无法控制另一方的流程,或对这些流程有任何可见性,也无法协调他们的活动和流程以共享信息和价值。当需要跨控制/可见性域进行协调时,使用编排。参考一个简单的场景,你可以把编排想象成类似于网络协议。它指定各方之间可接受的请求和响应模式。sage模式编排(Orchestration)——编排器(对象)将负责saga的决策和业务逻辑排序。此时您可以控制流程中的所有参与者。当它们都在一个控制域中时,您可以控制活动的流程。当然,这通常是指您被指派在您可以控制的组织中开发业务流程。saga-pattern-orchestration可观察性模式日志聚合考虑应用程序包含多个服务的用例。请求通常跨越多个服务实例。每个服务实例都以标准格式生成日志文件。我们需要一个集中的日志服务,可以聚合每个服务实例的日志。用户可以搜索和分析日志。它们可以配置为在某些消息出现在日志中时触发警报。例如,PCF有一个日志聚合器,它从应用程序端的PCF平台的每个组件(路由器、控制器、diego等)收集日志。AWSCloudWatch也是如此。性能指标由于微服务架构的引入导致服务组合增加,跟踪事务变得更加重要,以便可以监控这些模式并在出现问题时发送警报。此外,还需要一个度量服务来收集有关各个操作的统计信息。它应该聚合应用程序服务的指标数据,这些数据将用于报告和警报。这里有两种用于聚合指标的模型:推送——服务将指标推送到指标服务,例如NewRelic,以及AppDynamicsExtraction——指标服务从服务中拉取指标,例如Prometheus分布式链接跟踪在微服务架构中,经常请求跨越多个服务。每个服务通过跨多个服务执行一个或多个操作来处??理请求。在故障排除时,拥有TraceID非常有帮助,我们可以端到端地跟踪请求。解决方案是引入交易ID。可以采用以下方法:为每个外部请求分配一个唯一的外部请求ID,将外部请求ID传递给所有处理该请求链接的服务,将外部请求ID添加到所有日志消息中进行健康检查实现微服务架构后,服务可能会发生事务启动但无法处理的情况。每个服务都需要有一个API端点,例如/health,可用于检查应用程序的健康状况。API应检查主机的状态、与其他服务/基础设施的连接以及任何其他特定逻辑。Cross-CuttingConcernPatterns一个服务的外部配置通常也会调用其他服务和数据库。对于dev、QA、UAT、Prod等每个环境,API端点的URL或一些配置属性可能不同。这些属性中的任何一个发生变化都可能需要重建和重新部署服务。为了避免代码修改,可以使用配置。将所有配置放在外面,包括端点URL和证书。应用程序应该在启动时或运行时加载它们。这些可以在启动时被应用程序访问,也可以在不重启服务器的情况下刷新。当服务发现模式出现在微服务中时,我们需要解决一些调用服务的问题。借助容器技术,可以将IP地址动态分配给服务实例。每次地址变化都会中断消费者服务,需要手动修改。对于消费者服务,他们必须记住每个上游服务的URL,这变得紧密耦合。为此,需要创建一个服务注册表来保存每个生产者服务的元数据和每个服务的配置。服务实例应该在启动时向注册表注册,并在关闭时注销。服务发现有两种类型:Client:比如:NetflixEurekaServer:比如:AWSALBfusemode一个服务通常通过调用其他服务来获取数据,此时下游服务可能已经挂了。在这种情况下,存在两个问题:第一,请求会不断到达宕机的服务,耗尽网络资源,降低性能。其次,用户体验会很差且不可预测。消费者服务应通过行为类似于断路器的代理调用远程服务。当连续失败次数超过阈值时,断路器跳闸,在超时时间内所有调用远程服务的尝试立即失败。超时到期后,断路器将允许有限数量的测试请求通过。如果这些请求成功,断路器将恢复正常运行。否则,如果发生故障,超时时间将重新开始。如果某些操作很可能失败,采用此模式有助于防止应用程序在发生故障后继续尝试调用远程服务或访问共享资源。当蓝绿部署模式采用微服务架构时,一个应用可以拆分成很多微服务。如果我们采取停止所有服务然后部署改进版本的方法,则停机时间将很长并且会影响业务。此外,回滚将是一场噩梦。蓝绿部署模式避免了这种情况。实施蓝绿部署策略可用于减少或消除停机时间。它通过运行两个相同的生产环境(蓝色和绿色)来实现这一点。假设绿色是现有的活动实例,蓝色是应用程序的新版本。在任何时候,只有一个环境处于活动状态,并且该活动环境为所有生产流量提供服务。所有云平台都提供了实施蓝绿部署的选项。