精华内容
下载资源
问答
  • TanZu Spring Runtime构建企业 微服务应用架构 提供企业核心应用构建过程中最常用基础软件包和技术专家服务的组合 VMwares Java&Spring Experts Support 24/7 Simple Pricing 2 VMware Tanzu Spring Runtime 解决...
  • ;...VMWare Spring Runtime助力现代化应用开发;VMware SpringRuntime 软件包以及技术支持 微服务构建的兵器库;VMWare Spring Runtime持续创新推动企业级软件开发;VMWare Spring的项目和技术趋势;Sp
  • 微服务企业中可以带来积极的影响。 因此,如何处理微服务体系架构(MSA)和一些微服务设计模式以及微服务体系架构的一般目标或原则是很有必要的。 以下是微服务架构实现中要考虑的四个目标。降低成本 — MSA将降低...

    微服务在企业中可以带来积极的影响。 因此,如何处理微服务体系架构(MSA)和一些微服务设计模式以及微服务体系架构的一般目标或原则是很有必要的。 以下是微服务架构实现中要考虑的四个目标。

    1. 降低成本 — MSA将降低设计,实施和维护IT服务的整体成本
    2. 提高发布速度 — MSA将提高项目从构建到部署的速度
    3. 提升弹性 — MSA将提升我们服务网络的弹性
    4. 有可见性 — MSA为您的服务和网络上提供更好的可见性。

    MSA是建立在哪些原则基础之上是需要你去了解的

    1. 可扩展性
    2. 可用性
    3. 弹性扩展
    4. 灵活性
    5. 独立性,自主性
    6. 去中心化治理
    7. 故障隔离
    8. 自动配置
    9. 通过DevOps持续交付

    在坚持这些原则基础上推广自己的解决方案或者系统会带来一些挑战和问题,这些问题在许多解决方案中都很常见,而且可以通过使用正确的设计模式来解决, 这些就是微服务的设计模式,这些模式可以分为五个大类,而每一类又包含了许多设计模式。具体如下图所示:

    7d187ba8b1bab2a4ac2d6ecdfcb10365.png

    Design Patterns for Micoservices

    解耦模式(Decomposition Patterns)

    按业务能力解耦

    通过运用单一职责原则,微服务总是会把服务之间的耦合变为松耦合,微服务通过业务能力解耦,而且服务的定义是对应于业务能力。业务能力这个概念来自于业务架构模型,某种程度上来说,业务确实是可以产生价值,业务能力经常是对应于一个业务实体对象。例如:

    • 订单管理对应于订单
    • 客户管理对应于客户

    按照子域解耦

    按照业务能力解耦一个应用可能是一个好的开始,但是你可能会遇到所谓的“神类”(God Classes),就是哪些不容易解耦的类,而且这些类在多个服务之间很常见。领域驱动设计(DDD) 参考应用问题空间–业务–做为一个域(domain)。一个域由多个子域组成,而每一个子域对应于业务的不同的部分。

    子域可以分类如下:

    • 核心(Core) — 区分业务的关键 和 应用中最有价值的部分
    • 支撑(Supporting ) — 与业务相关,但是不是关键部分,可以内部实现,也可以外部实现
    • 泛化(Generic ) — 不针对特定的业务,理想情况下使用现成的软件实施

    订单管理的子域包括:

    • 产品目录服务
    • 库存管理服务
    • 订单管理服务
    • 交付管理服务

    按事务解耦/两阶段提交(2PC)模式

    可以通过事务分解服务,然后系统中将会有多个事务。 分布式事务处理的重要参与者之一是事务处理协调器[3]。分布式事务包括两个步骤:

    • 准备阶段 — 在此阶段中,事务的所有参与者都准备提交并通知协调器他们已准备好完成事务
    • 提交或者回滚阶段 — 在此阶段中,事务协调器向所有参与者发出提交或回滚命令

    2PC的问题是和单个微服务执行时间来对比耗时长。即使微服务在相同的网段中,协调微服务之间的事务依旧会拖慢整个系统。因此这个解决方案一般不适用高负载的场景中

    扼杀模式

    以上三种设计模式用于对未开发的应用(greenfield apps)的解耦, 但是我们80%的工作都是和庞大而僵化的应用(遗留代码库)打交道。扼杀模式(Strangler Pattern)就是为了解决这个问题而来的。在相同的URI空间中创建两个独立共存的应用,随着时间的推移,重构过的新应用将“扼杀”或者替代原来的应用,直到最终把庞大而僵化的应用关闭掉。扼杀应用(Strangler Application)的步骤分为转换,共存和消灭三步[4]:

    • 转换(Transform ) —  用现代方式创建一个新的平行的站点
    • 共存(Coexist ) —  将已有的站点重定向到新的站点,新站点逐步实现老站点的功能
    • 消灭(Eliminate ) —  移除已有的站点的旧的功能

    隔板模式

    将应用程序的元素隔离到池中,以便如果其中一个失败,其他应用程序将继续运行提供服务,这个设计模式称为隔板模式(Bulkhead), 因为他类似于船体中一个个被隔离的分区。根据使用者负载和可用性要求,这些分区服务实例被分割到不同的组里面。这种设计模式有助于隔离故障(isolate failures), 并允许即使在故障期间仍可为某些使用者维持服务功能.

    边车模式(Sidecar Pattern)

    将应用程序的组件部署到单独的容器中以来提供隔离和封装,这个模式允许应用可以由多种多样的组件和技术组合而成,这种模式称为边车(Sidecar ), 因为类似摩托车旁边所附的边车。再这个模式中,sidecar 附在父应用上,并提供应用的支持特征。sidecar 和父应用共享相同的生命周期,随着父应用创建而创建,销毁而销毁。边车模式有时称为“边踢模式(sidekick pattern)”。

    微服务的集成模式 (Integration Patterns for Microservices)

    API网关模式 (API Gateway Pattern)

    当把一个应用分解为多个小的微服务时,有一些问题需要我们考虑并处理:

    • 不同的微服务不同的通道上有多次调用
    • 需要处理不同的协议类型
    • 不同的消费者可能需要不同格式的响应

    聚合模式(Aggregator Pattern)

    在将业务功能分解为几个较小的逻辑代码段时,有必要考虑如何对每个服务返回的数据进行协同操作,消费者不负责处理这个事情。

    聚合模式有助于解决此问题,它讨论了我们如何聚合来自不同服务的数据,然后将最终响应发送给消费者。 这可以通过两种方法来完成[6]:

    1. 组合的微服务将调用所有必须的微服务,组合数据,转换数据,然后返回给调用者。
    2. API网关还可以分发请求到多个微服务上,再聚合数据,然后发送消费者。

    代理模式(Proxy Pattern)

    我们只是通过API网关来暴露微服务。 我们允许获取API的特征,例如安全和GW中API的分类。 这个例子中,API网关具有三个API模块:

    • 移动API – 为FTGO移动客户端实现API
    • 浏览器API-实现浏览器中运行的JavaScript应用程序的API
    • 公用API-为第三方开发人员实现API

    网关路由模式 (Gateway Routing Pattern)

    API网关负责请求路由。 API网关通过将请求路由到相应的服务来实现一些API操作。 当API网关接收到请求时,它会查询路由映射,该路由映射指定将请求路由到的服务。 路由映射例如可以将HTTP方法和路径映射到服务的HTTP的URL上。 此功能与Web服务器(如NGINX)提供的反向代理功能相同。

    微服务链模式 (Chained Microservice Pattern)

    单个服务或微服务将可能会有多个依赖关系, 例如:销售微服务依赖产品微服务和订单微服务。微服务链模式将根据你的请求提供合并的结果。microservice-1 接收请求,然后和microservice-2通信,并且可能和microservice-3通信。 所有的这些服务都是同步调用。

    分支模式(Branch Pattern)

    微服务可能需要从包括其他微服务在内的多个来源获取数据,分支微服务模式是聚合器和链设计模式的混合,并允许来自两个或多个微服务的同时请求/响应处理。调用的微服务可以是微服务链。根据您的业务需求,分支模式还可用于调用不同的微服务链或单个链。

    客户端UI组合模式(Client-Side UI Composition Pattern)

    当通过分解业务功能/子域来开发服务时,负责用户体验的服务必须从多个微服务中提取数据。在单机世界中,从UI到后端服务只有一次调用来查询数据并且刷新/提交UI页面。不过,现在不一样了。 在微服务中,UI必须设计为屏幕/页面上具有多个部分/区域的框架。每个部分都将调用单独的后端微服务以提取数据。诸如AngularJS和ReactJS 之类的框架可以轻松地做到这一点,这些屏幕称为单页应用程序(SPA)。每个团队都开发一个客户端UI组件,例如AngularJS指令,该组件实现针对该页面/屏幕区域的微服务调用。一个UI团队负责实现页面的框架,这个框架通过组合多个特定服务UI (service-specific UI) 组件来构建页面/屏幕。

    数据库模式(Database Patterns)

    为微服务定义数据库架构时,我们需要考虑以下几点:

    • 服务之间必须是松散耦合的, 它们可以独立开发,部署和扩展。
    • 业务事务在跨越多个微服务的时候保证不变
    • 一些业务事务跨越多个微服务来查询数据
    • 有时数据库必须可以复制,并且可以弹性共享
    • 不同的服务有不同的数据存储要求

    每一个服务对应一个数据库(Database per Service)

    为了解决上述问题,必须为每个微服务设计一个数据库. 该数据库只能是该服务私有的,并且只能通过微服务的API访问,不能被其他的微服务直接访问。例如,对关系型数据库,我们可以使用 每个服务有私有化的表(private-tables-per-service), 每个服务有自己的schema (schema-per-service), 或者每个服务有私有的数据库服务器 (database-server-per-service)

    每一个服务共享数据库 (Shared Database per Service)

    我们已经讨论了每个服务一个数据库是微服务的理想选择,但它是微服务的反模式(anti-pattern)。如果一个单一而又庞大的应用,并试图把它拆分为微服务,那么数据库的反范式化(denormalization )就不那么容易。将每个微服务共享数据库不是理想的情况,但是是可行的解决方案。大多数人认为这是微服务的反模式,但对于brownfield 应用,这是将应用程序分解成较小逻辑部分的一个很好的开始。但是对于greenfield 应用不太适用。

    命令查询的责任分离 (Command Query Responsibility Segregation,CQRS)

    一旦我们实现了每个服务对应一个数据库,就需要将从多个微服务查询返回的数据连接起来。显然这是不可能的。CQRS建议将应用分为两个部分 — 命令端 (command side)和查询端 (query side):

    • 命令端处理创建,更新和删除请求
    • 查询端通过使用物化视图来处理查询部分

    通常 事件溯源模式(event sourcing pattern)和它一起用来为任何数据更改创建事件。通过订阅事件流,可以使物化视图保持不断的更新

    事件溯源模式(event sourcing pattern)

    大多数应用程序都使用数据,一个典型的途径就是应用保持当前的状态。例如,传统的创建,读取,更新和删除(CRUD)中,典型的数据处理是从存储中读取数据,它包含经常使用事务锁定数据的限制。

    事件溯源模式定义了一系列事件驱动的数据的处理操作,每一个事件处理操作都会记录在仅追加存储中(append-only store)。应用程序代码发送一系列 命令式的描述了数据上发生的动作的事件到事件持久化存储的地方。每个事件代表一组数据更改(例如,AddedItemToOrder)

    这些事件持久化存储在充当系统记录系统的事件存储中。事件存储系统中事件发布的典型应用场景是:在应用中保持实体的物化视图和事件的动作一样来改变他们,以及集成的外部系统。例如系统可以维护一个针对所有用户的物化视图,用来填充UI部分的数据。当应用程序添加新订单,添加或删除订单上的项目以及添加运输信息时,这些事件描述了这些数据变化可以被处理并且可以更新到物化视图上。下面是这个模式的纵览:

    c5a9a37ecff0c487e83476519e3d3d04.png

    事件履历模式(Saga Pattern)

    当每一个微服务都有自己的数据库,并且一个业务事务跨越多个微服务的时候,我们是如何确保各个服务之间的数据一致性?每个请求都有一个补偿请求,该请求将在请求失败时执行。 它可以通过两种方式实现:

    • Choreography  — 如果没有中央协调,则每个服务都会产生并侦听另一个服务的事件,并决定是否应采取措施。Choreography  是指定两个或两个以上参与者的方式。 每一个参与者都无法控制对方的流程,或者任意可见的流程,这些可见的流程可以协调他们的活动和流程以共享信息和数值。当需要跨控制/可见性域进行协调时,请使用choreography 。你可以在简单的情况下将编排视为网络协议,它规定了各参与者之间可接受的请求和响应模式。
    66373855268a1d82809e5fe16b9882c0.png
    • Orchestration —  一个Orchestration (对象)负责Saga的决策和业务逻辑顺序。当你已经控制流程中的所有参与者时,当它们全部处于一个控制范围内时,你可以控制活动的流程。当然,通常情况下,当你制定一个组织内的业务流程时,你已经控制了它
    605f68d439fe97fe802ca74c131dc0ee.png

    观察者模式(Observability Patterns)

    日志聚合

    考虑这样一种情况:一个应用包含多个微服务实例,每个请求经常在横跨多个微服务实例,那么每一个微服务实例都产生一个表转化格式的日志文件。 因此我们需要一个中心化的日志服务来将每个服务实例的日志收集起来。用户可以搜索分析并分析日志,并且配置一些当日志中出现特定信息的报警规则。例如:PCF确实有一个日志聚合器(Log aggregator), 用来收集PCF平台上各个应用的各个组件(router, controller, Diego, 等等…)的日志。AWS Cloud Watch也这样做。

    性能指标

    因为微服务架构导致服务的数量增加时,密切注意事务变得十分关键,以便监控微服务模式并且在问题发生的时候发出警告。

    一个指标服务用来收集每个单独操作的统计信息。它应该聚合一个应用服务的所有指标,以便提供报告和警报。 聚合指标应该包含两个模块:

    • 推送 — 服务推送指标给指标服务 例如:NewRelic, AppDynamics
    • 拉取 — 指标服务可以从每个服务中拉取指标 例如:Prometheus

    分布式跟踪

    在微服务架构中,请求通常跨越多个微服务。 每个服务通过跨多个服务执行一个或多个操作来处理一个请求。 在进行故障排除时,有一个跟踪ID是非常值得的,这样我们可以端对端的跟踪请求

    解决方案是引入一个事务ID,可以使用以下方法:

    • 为每个外部请求分配唯一的外部请求ID
    • 将外部请求ID传递给所有服务
    • 在所有日志消息中包括外部请求ID

    健康检查

    实施微服务架构后,有一种可能是:服务可能会启动但无法处理事务。每个服务都需要具有一个端点用来检查应用的健康程度,例如health。这个API应该检查主机的状态, 与其他服务/基础结构的连接以及其他任意特定的逻辑。

    交叉关注模式(Cross-Cutting Concern Patterns)

    外部配置(External Configuration)

    一个典型的服务通常还会调用其他服务和数据库,对于每一个环境,例如dev, QA, UAT, prod,这些环境的端点URL或某些配置属性可能不同,这些属性中的任何一项更改都可能需要重新构建或重新部署服务。

    为了避免代码修改,我们可以使用配置,将所有的配置信息都外部化,包括端点URL和认证信息。应用程序应该在启动时或运行时加载这些配置。这些配置可以在应用启动的时候访问到,或者这些配置在不需要重启服务的情况下可以更新。

    服务发现模式

    当遇见如图所示的微服务架构时,在微服务调用方面我们需要关注一些问题。

    使用容器技术,IP地址可以动态分配给每个微服务实例, 每次地址更改时,消费者服务的调用都会中断,需要手动更改才能恢复。

    消费者必须记住每个服务URL,并使其紧密耦合。

    因此需要创建服务注册,该服务注册将保存每个生产型服务的元数据和每个服务的说明规范。服务实例在启动时应注册到注册中心,而在实例关闭时应注销。服务发现有两种类型:

    • 客户端,例如:Netflix Eureka
    • 服务端:例如: AWS ALB
    ce0e9ffafefe7fd87e822a57a033dc48.png

    断路器模式

    一个服务通常会调用其他服务来查询数据,有一种可能性是下游的服务会关闭,这将会带来两个问题:第一个是:上游服务继续请求关闭的网络服务,直到耗尽网络资源,并且降低系统性能。第二个是:用户体验将是糟糕的且不可预测的。

    消费者应通过代理来调用远程服务,该代理的行为类似于电路中的断路器。当连续的请求失败的次数超过阈值时,断路器将跳闸一段时间,并且在跳闸的这段时间内,所有的调用远程服务的尝试都将立即失败。当超过了断路器跳闸时间之后,断路器将允许有限数量的测试请求通过。如果这些请求成功,则断路器将恢复正常操作。否则,如果有一个请求失败,则断路器再次跳闸。对于 一个应用试图尝试调用一个远程服务或者获取共享资源,并且该操作很容易的失败的情况来说, 这个模式非常适用

    aeec45023666731e86ce2bbef1b0910c.png

    蓝绿发布模式

    在微服务架构中,一个应用程序可以具有许多微服务。 如果我们在停止所有服务之后然后部署增强版本,则停机时间将是巨大的,并且可能影响业务。同样,回滚将是一场噩梦。蓝绿发布模式可以避免这种情况。

    实施蓝绿发布模式可以减少或消除停机时间,它通过运行两个相同的生产环境:Blue和Green,来实现这一目标。这里我们假设绿色是已存在的工作实例,蓝色是该应用程序的新版本。在任何时候,只有一个环境处于活动状态,该活动环境为所有生产流量提供服务。 所有云平台均提供用于实施蓝绿色部署的选项。

    9b4982dedcaf3c5217b323935e1289f7.png
    展开全文
  • 那当微服务应用运行在容器中的时候,我们会遇到哪些常见问题?我们又该如何解决呢?企业应用在向微服务架构转型的过程中,微服务如何划分是最基本的问题。我们可以通过业务架构的梳理来理解业务,并同时使用领域设计...
  • 近些年企业应用开发架构发生了细微的变化,根据康威定律,由于企业组织架构的变化,导致微服务应用体系开始在企业应用开发过程中流行起来。微服务是最近几年企业数字化转型过程中,在技术团队技术选型中比较常见的...

    近些年企业应用开发架构发生了细微的变化,根据康威定律,由于企业组织架构的变化,导致微服务应用体系开始在企业应用开发过程中流行起来。微服务是最近几年企业数字化转型过程中,在技术团队技术选型中比较常见的架构升级方案之一。在这个背景下,DevOps 团队为了应对企业架构的变化,迫切需要使用一套统一的基础设施来维护微服务应用的整个生命周期,这就给我们带来了新的挑战——如何应对微服务应用场景,平稳快速的落地 Kubernetes 集群系统。

    基于 Kubernetes 下的微服务注册中心的部署问题

    经典的微服务体系都是以注册中心为核心,通过 CS 模式让客户端注册到注册中心服务端,其它微服务组件才能互相发现和调用。当我们引入 Kubernetes 之后,因为 Kubernetes 提供了基于 DNS 的名字服务发现,并且提供 Pod 级别的网格,直接打破了原有物理网络的单层结构,让传统的微服务应用和 Kubernetes 集群中的微服务应用无法直接互联互通。为了解决这个问题,很多技术团队会采用如下两种方式来打破解决这种困境。

    创建大二层网络,让 Pod 和物理网络互联互通

    这个思路主要的目的是不要改变现有网络结构,让 Kubernetes 的网络适应经典网络。每一个 Pod 分配一个可控的网络段 IP。常用的方法有 macvlan、Calico BGP、Contiv 等。这样的做法直接打破了 Kubernetes 的应用架构哲学,让 Kubernetes 成为了一个运行 Pod 的资源池,而上面的更多高级特性 Service,Ingress、DNS 都无法配合使用。随着 Kubernetes 版本迭代,这种阉割功能的 Kubernetes 架构就越来越食之无味弃之可惜了。

    注册中心部署到 Kubernetes 集群中,外网服务直接使用 IP 注册

    这种思路是当前最流行的方式,也是兼顾历史遗留系统的可以走通的网络部署结构。采用 StatefulSet 和 Headless Service,我们可以轻松地搭建 AP 类型的注册中心集群。当 Client 端连接 Server 端时,如果在 Kubernetes 内部可以采用域名的方式。例如:

    eureka:
      client:
        serviceUrl:
          defaultZone: http://eureka-0.eureka.default.svc.cluster.local:8761/eureka,http://eureka-1.eureka.default.svc.cluster.local:8761/eureka,http://eureka-2.eureka.default.svc.cluster.local:8761/eureka
    

    对于集群外部的微服务,可以直接采用 IP 直连 Servicer 端的 NodeIP,例如:

    eureka:
      client:
        serviceUrl:
          defaultZone: http://<node-ip>:30030/eureka
    

    大家通过上面两种方案肯定都会得出一个结论,如果考虑和传统网络耦合在一起,怎么部署都不是很理想。我们如何解决这样的困局呢?

    我们回顾 Kubernetes 设计之初就会发现,它是为数据中心设计的应用基础设施,并没有设计能兼容传统网络的架构,所以才导致我们部署起来感觉怎么操作都不对劲。但是企业内部的业务逻辑复杂,技术团队一般都是小心谨慎地把业务系统慢慢迁移到新的云原生的集群中,所以我们势必又会遇到这样的混合架构的场景。这个时候我们可以借鉴业界实践过的单元化设计,按照网关为边界,划分应用单元,把完整的一套微服务上架到 Kubernetes 中。这样,Kubernetes 集群和外部的服务之间的调用可以采用 RPC/HTTP API 的方式进行异构调用,从而规避打破 Kubernetes 云原生体系。

    微服务核心能力的优化设计问题

    经典微服务架构的内部,服务和服务之间的函数调用,我们通常见过的有 Spring Feign/Dubbo RPC/gRPC ProtoBuf 等。为了能知道服务的所在位置,我们必须有一个注册中心才能获得对方的 IP 调用关系。然后你在结合 Kubernetes 集群的 CoreDNS 的实现,你会自然想到一个问题,如果所有服务组件都在一个 Namespace 之下,它们直接的关系直接可以在配置文件里面写入名字,CoreDNS 是帮助我们实现在集群之下的服务发现的。也就是说,当你把微服务部署到 Kubernetes 之后,像 Eureka 这样的服务基本就是鸡肋了。

    很多有经验的架构师会说,道理是这样的,但是例如 Spring Cloud 的微服务体系就是以 Eureka 为中心的,可能不用它不行。这个问题我觉得是历史遗留问题,以 Spring Boot 框架做为基础,我们完全可以基于 Kubernetes 的服务发现能力构建微服务体系。

    另外,因为 Kubernetes 的 Pod 设计包含了 SideCar 模型,所以我们可以把通用的微服务关心的限流、熔断、安全 mTLS、灰度发布等特性都放在一个独立的 Sidecar proxy 容器中,代理所有这些通用的容器治理需求。这样就可以极大的解放开发人员的心智模型,专心写业务代码就可以了。大家已经看出来,这不就是服务网格吗?是的,确实融入到服务网格的设计模式中了,但是当前的服务网格参考 Istio 并没有在业界大量落地使用,我们仍需要利用现有的微服务框架自建这样的体系。

    另外,微服务体系的业务观测能力,通过 Kubernetes 的生态图,我们可以采用 ELK 收集业务日志,通过 Prometheus 监控加上 Grafana 构建可视化业务模型,更进一步完善微服务的能力设计体系。

    微服务应用的部署策略痛点

    很多微服务应用在部署 Kubernetes 集群时,多采用 Deployment 对象。其实当前 Kubernetes 还提供了 StatefulSet 对象。这个 Workload 对象一般开发者望文生义,以为就是有状态的,需要挂盘才用这个。其实 StatefulSet 还提供了强劲的滚动更新的策略,因为 StatefulSet 对每一个 Pod 都提供了唯一有编号的名字,所以更新的时候可以按照业务需要一个一个地更新容器 Pod。这个其实对业务系统来说特别重要,我甚至认为,微服务的容器服务都应该用上 StatefulSet 而不是 Deployment。Deployment 其实更适合 Node.js、Nginx 这样的无状态需求的应用场景。

    另外,微服务部署在 Kubernetes,并不是说你的微服务就是高可用了。你仍然需要提供亲和性/反亲和性策略让 Kubernetes 调度应用到不同的主机上,让业务容器能合理地分布,不至于当出现宕机时直接导致“血崩”现象,并直接影响你的业务系统。示例:

    affinity:
     podAntiAffinity:
       requiredDuringSchedulingIgnoredDuringExecution:
       - weight: 100
         labelSelector:
           matchExpressions:
           - key: k8s-app
             operator: In
             values:
             - kube-dns
         topologyKey: kubernetes.io/hostname
    

    微服务应用在更新过程中,肯定需要更新 Endpoint 和转发规则,这个一直是 Kubernetes 集群的性能瓶颈点,我们可以采用 readinessProbe 和 preStop 让业务更平滑地升级,示例如下:

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          component: nginx
      template:
        metadata:
          labels:
            component: nginx
        spec:
          containers:
          - name: nginx
            image: "nginx"
            ports:
            - name: http
              hostPort: 80
              containerPort: 80
              protocol: TCP
            readinessProbe:
              httpGet:
                path: /healthz
                port: 80
                httpHeaders:
                - name: X-Custom-Header
                  value: Awesome
              initialDelaySeconds: 15
              timeoutSeconds: 1
            lifecycle:
              preStop:
                exec:
                  command: ["/bin/bash", "-c", "sleep 30"]
    

    最后,运维团队因为要处理的微服务容器会越来越多,可以给应用容器加上 PodDisruptionBudget 限制,保证在运维过程中不会影响到现有业务,示例如下:

    apiVersion: policy/v1beta1
    kind: PodDisruptionBudget
    metadata:
      name: zk-pdb
    spec:
      minAvailable: 2
      selector:
        matchLabels:
          app: zookeeper
    

    总结

    在 Kubernetes 中有一个 Service 对象,翻译成中文就是服务对象,很容易和微服务中的服务对上关系,其实它们之间没有任何关系。我们不应该把微服务架构直接生搬硬套地落地到容器集群中,更科学的办法就是熟悉并统筹微服务体系和 Kubernetes 体系中各自的特性,在设计自己的微服务架构时,能详细思考 CI/CD 过程中、发布过程中到底我们需要那些业务需求,然后在分析应该用哪种方案更合适自己的团队,只有这样才能彻底拜托历史包袱,让 Kubernetes 技术能在合适的位置发挥应有的作用。

    展开全文
  • 基于微服务企业应用架构设计,基于微服务企业应用架构设计,基于微服务企业应用架构设计
  • 溯源微服务企业分布式应用的一次回顾原创:刘尚奇ThoughtWorks洞见微服务作为架构风格几乎成为云时代企业应用的事实标准,构成微服务的技术元素本身却并非革命性。跨平台的分布式通信框架、地址无关的服务注册与...

    溯源微服务:企业分布式应用的一次回顾

    原创: 刘尚奇 ThoughtWorks洞见 

    微服务作为架构风格几乎成为云时代企业级应用的事实标准,构成微服务的技术元素本身却并非革命性。跨平台的分布式通信框架、地址无关的服务注册与发现、智能路由与编排等技术早已在CORBA、SOA时代实现了一遍又一遍,我们不禁好奇,微服务有什么不同?本文是对企业分布式应用的一次回顾,与前微服务时代相比,我们究竟在哪些领域吸取了教训,哪些方面持续搞砸。

    我们在重新界定抽象边界上取得了进展...

    架构的关键在于构造合理的封装抽象。良好的抽象构造如进程,由操作系统接管CPU调度、内存地址空间分配和I/O,程序员的心智从此解放,得以聚焦在业务逻辑上。糟糕的抽象往往引向万丈深渊,大量精力被浪费在抽象泄露带来的问题上。

    在分布式系统中我们关注组件、组件间的通信以及伴随的工程实践,微服务在企业应用的上下文中就技术约束和业务价值间达成了更好的平衡点。


    RPC?不,是API!

    让我们从组件间的通信开始,最初人们认为这只是需要被解决的技术要素。

    72c2eae049ed503cc9e414328919ce1c.png

    (图片来自:维基百科)

    关于如何实现跨平台的分布式通信,30年前诞生的CORBA架构在今天来看仍然非常漂亮:通过定义IDL/ORB/API我们可以将内存对象任意分布于网络中。只要共享IDL,对象可以由C++/Java等不同的语言实现,其互相调用就像本地方法一样简单。然而实践经验告诉我们,分布式系统总是会出现本地调用不会发生的各种问题:网络的开销、传输的延迟、消息的超时和丢包、远端系统的崩溃……物理世界的技术约束是无法被忽略的,我们没有办法把分布式调用抽象成简单的本地方法。因此Martin Fowler在他的里提出了著名分布式对象第一定律:“不要分布式你的对象”。相反,你应该把尽可能多的操作置于进程之内,通过replicate整个应用的方式来实现系统的scale。

    由分析师们发起的SOA运动从另一个角度看待这个问题,Web Service应该是对企业资产和业务能力的封装。我们开始站在更高的维度,远过程调用不再只是技术意义上的集成。WSDL不仅是通信调用的接口,更是服务间的契约;UDDI不仅是服务描述、发现、集成的中心,更是企业业务与服务的黄页。WS-*在厂商的裹挟下发展成包罗万象,却也没几个人能掌握。开发者们抱怨花了太多时间写冗余的XML制定所谓的规范,WSDL生成的客户端也将不同服务耦合在一起。是否有更加轻量敏捷的方式,让我们快点开始写第一行生产代码?

    于是我们看到REST的兴起。起初是作为反叛,用更加轻量级的方式(http+json)使用Web。然后我们发现"企业级"应用并非需要ESB这样昂贵的专有中间件,由"消费级"技术组成的万维网是世界上最大规模的分布式网络,我们应该向其学习如何构建健壮、可演化的系统。Roy Fielding那篇论文所提出的无状态、可缓存等特征已经深入人心,而狭义上的REST API(基于资源的URI、HTTP动词和状态码的标准接口)也成为API设计的最佳实践。

    既然API和网站一样都是基于通用Web技术,API是否可以像网站一样作为产品提供呢(APIs as product)?于是越来越多的企业开始将自己的业务能力封装成API,提供给消费者,随之而来的是更弹性的商业应用和更灵活的计费方式。很多组织也着手构建自己的API市场,把内部IT能力整合、复用,并为孵化外部产品做准备。API已经成为商业价值主张的一部分。

    我们从聚焦实现细节的rpc出发,来到了更具价值导向的REST API。即使构建内部系统,以消费者驱动的方式,也总是能帮助我们设计出更加松耦合和易于演进的API。


    技术组件?不,是业务服务!

    编程语言中的组件构造(如Java中的jar, C#中的dll)是软件架构师们封装可复用单元的最常用武器。组件作为理论上的最小部署单元,在工程实践中却并不容易独立变更。一般应用程序需要讲多个组件打包成一个部署单元(如war包),链接在内存地址中进行调用。对单个组件的热更新往往对组件间耦合和对象状态管理有很高的要求,重新部署整个应用一般是默认选项。以进程为边界构建可独立部署的服务成为架构师的另一项选择。

    早期的服务只是单纯的技术构件,大多数组织从纯粹的技术实现角度考虑服务的划分。SOA的推动者们指出企业的信息资产应该被复用,信息孤岛应该被打通。通过将不同的服务编排组合,我们应该能够实现IT对业务更加灵活的支撑。

    1a54116297077447e4f5675294461126.png

    (图片来自:0SOA in practice, Nicolai Josuttism, 2009)

    SOA的服务建模一般采用业务流程驱动的方式。一个典型的SOA设计是由业务分析师自顶向下地对企业现有业务流程进行分析,通过BPM引擎对流程进行建模,向下分解成组合服务,并进一步拆分成数据访问服务(很多可怜的SOA实现中数据的访问被拆分成不同的读服务和写服务)。然而这带来的问题是,服务跟服务间的耦合非常严重。当我的业务发生了变化,可能会需要修改很多不同的服务,涉及到多个团队的沟通和协调。在运行时层面,服务器间的通信非常频繁,用户在界面上的一次点击按钮,对应的后台多层服务间的级联通信。这给系统性能和稳定性也带来了巨大的挑战。SOA式的服务建模从分析型思维出发,却往往低估了分布式系统和跨团队协调的复杂度,导致服务拆分粒度过细。

    微服务的名字常常让人误解,但实施正确的微服务粒度可能并不"微"。Martin Fowler与James Lewis在开创微服务定义的一文中已经指出微服务应该围绕完整的业务能力。今天我们在做微服务设计时,常常利用领域驱动设计中的Bounded Context来进行服务边界的划分。假设你的库存管理是一个独立的业务子域,针对库存的维护和操作应该被放到通过一个上下文和微服务中,由一个团队进行开发维护。多数业务变更都发生在上下文内部,不涉及跨团队协调。单个codebase内的重构和部署让发布更加容易。维护库存所需要的信息查询的调用多发生在进程内,更好的性能,同时无需处理额外的一致性问题。

    08e6ecfc28aa256e462f50e960c327dc.png

    微服务的另一个特点在于Product over Project,这需要不同于传统投资组合的预算管理与团队组建。传统的项目制将预算分配在相对短期的服务开发过程中,项目团队关注的是如何将业务范围(scope)实现,开发结束后服务转交运维团队进行维护,项目团队则被解散进行其他项目的开发。将微服务作为产品运营则需要建立业务结果导向的稳定产品团队。服务的设计不只聚焦于当下需求,更需要考虑价值定位和产品愿景。工程团队则需要思考如何用有限成本支撑非线性的业务接入增长。

    846eae9338f75f099d853a974f147cee.png

    (图片来自:Enterprise Architecture as Strategy, Ross et al, 2006)

    如今我们对服务的定义已经超越了技术组件,领先的组织已经在尝试将design thinking, business operating model应用到微服务设计中。


    解耦服务就足够了吗?我们需要去中心化一切!

    即使有了设计合理的服务于API,我们仍然需要与之匹配的工程实践才能将其顺利实施。

    今天仍有很多企业使用集中式的应用服务器部署应用:开发团队将软件包构建出来,再统一安装到应用服务器中。对应用团队来说,这往往意味着漫长的反馈周期和痛苦的自动化。我们很早就推荐用Jetty这样内嵌式的应用容器部署软件,启动更快,测试环境更接近生产。one Tomcat per VM的部署方式虽然运行时开销较大,却是前容器时代隔离性最好的服务部署模式。Docker将这个实践更进一步,除了更轻量级的隔离,我们第一次可以将软件和所依赖的环境本身打包成版本化的artifact,彻底统一开发和生产环境。容器技术的成熟让我们可以将部署去中心化,开发团队可以独立部署一个服务。

    数据库耦合是影响服务独立变更的另一重要因素。相比代码构成的应用软件,数据库schema更加难以变动。因为难以测试、难以兼顾性能优化和耦合的发布周期等因素,服务间以数据库集成成为臭名昭著的反模式。服务间的集成应该依赖封装好的显示接口,而不是数据库这种实现细节。我们应该在兼顾数据一致性的情况下,为每个微服务分配独立的db schema甚至db instance。如果说十年前数据几乎等同于关系数据库。如今数 据则可能呈现出各种形态:键值、文档、时间序列、图...我们完全可以采用更加合适的技术,以去中心化的方式进行微服务的数据治理。

    即使将这一切都解耦,如果将交给一个集中的团队去实施,很有可能最终还是得到一个耦合的架构。这就是是著名的康威定律。康威定律告诉我们“设计系统的架构受制于产生这些设计的组织的沟通结构”。但同样我们可以将康威定律反转应用:如果你想达成一个目标架构,则必须对团队结构进行调整,使之和目标架构对齐。相比单体系统,微服务在运行时监控和运维所带来的挑战更大。"you build it, you run it"的DevOps文化成为必须。监控运维不再是Ops部门的事情,产品团队必须对微服务的整个生命周期负责。授权的去中心化自治团队是实施微服务的必要条件。


    我们干得还不错,但也在持续搞砸一些事情...

    我们在很多方向的确取得了进展。但即使在微服务时代,很多问题仍然在轮回发生着,似乎我们总是无法吸取历史的教训。让我们看一看那些挥之不去的反模式阴云。

    一个例子是开发者对强类型RPC代码生成的依恋。尽管历史经验已经证明同步的rpc无法为分布式通信提供足够好的封装,伪装成本地方法调用的客户端往往鼓励程序员做出糟糕的接口设计:细粒度的频繁调用、缺少缓存和容错处理。IDL生成客户端也会导致服务间耦合,每次变更接口都需要升级数个相关服务。如果用可演进的REST API(如HATEOS)和tolerant reader模式,则可以优雅地解决这个问题。然而新一代的开发者们还是经常“重新”发现rpc的这些能力并陷入依赖——更快的序列化反序列化、类型安全和来自IDE的智能提示、通过spec反向生成代码...分布式计算先驱Vinoski不禁感叹“开发人员的便利性是否真的胜过正确性,可扩展性,性能,关注点分离,可扩展性和意外复杂性?”

    另一个挥之不去的阴影是ESB。ESB在将异构的应用wire在一起有着关键的作用。然而当越来越多的职责被加入:数据报文的裁剪转换、难以测试和版本控制的编排(orchection)逻辑、服务发现智能路由监控治理分布式事务等All in One的solution将ESB变成了一个可怕的单点梦魇。所以微服务发出了“智能终端哑管道”的呐喊:我们只是需要一个不那么智能的代理处理可靠消息传输,将灵活的逻辑交给服务本身去编配(choreography)吧。

    于是在典型的微服务架构里,负载均衡、服务注册发现、分布式追踪等组件以Unix way的方式各司其职。然而在利益诱惑和特性竞争压力之下,很多厂商不断将更多的功能放进他们的中间件,其中为代表的Overambitious API gateways俨然要重新实现占据中心的ESB。如果API gateway只是处理鉴权、限流等横切层逻辑没有问题,如果API gateway开始处理数据转换和业务逻辑编排,你应该提高警惕!

    尽管行业在不断发展,但很多时候人们仍然沿用旧的思维,用新的技术去一遍遍重新实现这些旧的反模式。


    如何更进一步

    你总是可以在技术雷达里追踪微服务的state of art,如今这个领域的前沿方向是什么,Service Mesh, Chaos Engineering, 还是Observability as Code?然而历史告诉我们,新的技术在解决一些问题的同时,也可能会产生新的问题。更糟糕的是,我们永远无法记住历史,用新的工具更高效地重现旧日问题。

    Technologies come and go, Principles stay forever。好在那些架构和实践背后的原则是经久不变的。从操作系统到移动应用都会需要高内聚低耦合的架构,任何软件开发都需要版本控制、自动化构建等实践。谨记这些核心原则、谨记软件被创造出来是为了解决有价值的问题,可以帮我们更好的借鉴历史的经验,理解和采纳新的技术。


    微服务架构下的质量迷思——混沌工程

    原创: 梁真 ThoughtWorks洞见 

    从2005年Peter Rodgers博士提出微web服务,到2014年ThoughtWorks首席科学家Martin Fowler与James Lewis共同提出微服务概念至今已多年,这期间也是互联网及互联网+发展的高速期,消费市场变化莫测,消费者也变得越来越挑剔,很多公司和产品由于无法跟上市场的快速变化而纷纷倒下。越来越多的互联网巨头甚至传统行业都开始对自己的遗留系统进行微服务改造,通过把系统拆分为更加灵活、有业务边界上下文、松散耦合、可独立部署的服务来应对快速变化的消费市场。


    微服务架构面临的挑战

    通常情况下,对于复杂业务或遗留系统,我们可以通过领域驱动设计(DDD:Domain-Driven Design)有效的解决限界上下文划分、服务边界定义以及组织结构调整等问题。除了这些,我们的开发团队还面临着其他的挑战:复杂的分布式系统、数据一致性、容错设计、限流设计、舱壁设计等问题。那么如此复杂的系统如何来保证系统“质量”呢?

    长久以来,“测试金字塔”都是敏捷开发团队保证项目交付质量的守则,而“测试金字塔”也确实从不同的维度涵盖了方法调用、业务逻辑、用户行为等方面。为了确保在进行复杂的调用和被调用时,服务之间能有一定程度上的一致性和快速反馈,我们会第一时间想到“契约测试”,“测试金字塔”也演化成了另一个样子。

    fe631dbd67a56e86bed4d2bd0fbf9c37.png

    下图,我们聚焦于微服务架构的业务服务层,在API测试之外在基础服务的调用方和提供方之间增加了契约测试:

    fbb2b63178786ca35a07790042e89341.png

    在微服务和前后端分离日趋流行的今天,契约测试的确可以在系统频繁演进、重构的情况下保证服务间调用的可用性,而在“聚合服务层”通过API测试,可以暴露服务的组合过程中的问题。“尽早测试”可以让团队在初期发现更多的问题,降低后期修复成本,同时让服务与服务之间具有“感知力”,任何与契约不符的业务变更都能被测试所感知。但是,既然契约测试是保证服务调用方和提供方的一致性,更直接说,是另一种对API的验证,那么契约测试只能覆盖到业务逻辑维度,如果想更好开发或改造微服务系统,就需要相对深入的了解微服务有哪些特性:

    050eb75f5bade3593f2c7bf1239d8833.png

    我们可以看到,这个简单的图中提到了一些微服务的特性(基于Spring Boot):客户端负载均衡、微服务容错保护、API服务网关、分布式链路跟踪等,我们不对这些进行解释,但毫无疑问,契约测试无法覆盖和测试到这些特性,同时也无法模拟例如网络延迟、CPU满载、请求异常、依赖故障、硬件故障等场景。对于一个不具备容错能力的脆弱系统,即使我们可以对服务解耦、独立部署,可对于用户来说,体验到的可能是一次又一次的“灾难”。我们在质量活动中,总会听到这样的声音:“不要动这个功能,会弄坏其他功能”、“客户根本不会这么操作“、”这个缺陷没有意义,你这样会把系统弄挂”。我们总是担心系统某些脆弱的环节挂掉,担心某次操作让整个系统宕机。遗憾的是,墨菲定律告诉我们,“如果事情有变坏的可能,不管这种可能性有多小,它总会发生。

    之前一个发生在身边的项目经历大概是这样的:一个团队提供基础服务,并承诺服务的功能、性能、弹性都没有问题。在集成联调时,由于对认证服务的调用超过负荷,对整个服务系统造成阻塞,导致雪崩效应,几乎所有客户端应用大面积瘫痪;另一个案例,由于没有对一个内容服务进行熔断保护,导致整个网站首页无法加载。而发生在世界各地的IT灾难也不少,某航空公司,由于调度和跟踪系统出现问题,导致去年6月份七天内将近3000个航班取消,损失3500万美金;“信息灾难总是普遍而没有偏见地发生在各个领域和任何时候”。

    既然我们没有办法避免灾难的发生,最好的办法就是“探索系统故障边界,验证系统灾难恢复能力”。以往的“机房”时代的一些故障演练一般通过断网、断电模拟单点故障,来测试系统的恢复能力,而新型的分布式服务时代消除了单点故障,但也引入了更多复杂的问题,我们需要可靠性更强、容错性和扩容性更高的系统。一种解决方案就是,我们需要一种有策略的、有方法的实践方案对系统进行一定程度的“随机破坏”,通过让系统”感染“,来提升系统的”免疫力“。Netflix开发出Chaos Monkey来对系统进行随机试验来了解系统是否具有高可用性和容错性,而由此便诞生出”混沌工程“。


    什么是混沌工程?混沌工程原则是什么?

    混沌工程是一种可试验的、基于系统的方法来处理大规模分布式系统中的混乱问题。通过不断试验,了解系统的实际能承受的韧性边界并建立信心,通过不同的试验方法和目的,观察分布式系统的行为和反应。一句话——以试验的方法尽早揭露系统弱点

    混沌工程类似于“故障演练”,不局限于测试,而更像是工程实践。为什么这么说,通常的测试用例会有“期望结果”和“实际结果”,通过将两个结果比较,或者对用户行为的预期,来判断测试通过或失败。而混沌试验类似于”探索性测试“,试验本身没有明确是输入和预期结果,通过对系统和服务的干预,来观察系统的”反应“。我们将混沌工程原则融入在试验过程中:在生产环境小规模模拟系统故障并定期自动化执行试验,通过试验结果与正常结果进行比对,观察系统”边界“。

    dc84c9921227596c589c1a00b2dba865.png

    通过“测试金字塔”和混沌试验,从业务逻辑和系统高可用性两个维度对微服务系统进行观察和测试,两种方案结合形成了一种更全面的实践,我称之为“服务级质量内建实践”(BQIS——Build Qualify in Services)。不论企业是在微服务改造期还是中台战略部署期,混沌实践能够有效避免生产环境灾难,提升系统的容错率和可用性。


    如何引入混沌工程?

    在众多服务化改造案例中,Netflix无疑是最成功的公司之一,该公司的很多试验工具也都集成在Spring Cloud中,成为微服务框架的标准。而Chaos Monkey就是Netflix进行混沌试验一个重要工具。作为国内的电商巨头,服务化和中台战略的先行者阿里,近期也开源了他们自己的混沌试验注入工具ChaosBlade。

    “混沌工程”的引入受限于组织文化的接受程度,任何一种工程实践和方法论的落地都无法一蹴而就。但是我们依然可以通过裁剪,在组织的安全范围内进行逐步尝试。不管是在线上环境还是测试环境,我们都需要先搞清楚,目前的混沌工具都为我们提供了哪些方法。

    Spring Cloud是时下最流行的分布式微服务架构下的一站式解决方案之一,它方便快速的将Spring Boot的微服务有效的管理起来,并提供了包括负载均衡、全链路监控、服务网关以及众多基于Netflix的开源工具。除此之外,鉴于Netflix在服务化演进中的成功案例,我们来了解下Netflix开源的混沌工程试验框架Chaos Monkey究竟是什么?

    在Spring Boot工程中,对需要进行试验的服务application.yml文件的Chaos Monkey进行配置:

    5d055a346de29407da2924c7ba0b216a.png

    从配置文件中我们可以很容易看到,Chaos Monkey的三种袭击方式——延时、异常和进程终止,同时我们也可以设置一个数值范围,在对服务进行延时攻击时生成随机延时。默认攻击方式为延时攻击,当同时开启异常攻击时,进程攻击则不会发生。Level:N表示第N个请求将被攻击,N=1时,表示每个请求都会被攻击,当同时开启异常攻击时,与N值无关,表示每个请求都将被攻击。

    ChaosBlade提供的攻击也很丰富,使用方式对开发人员来说更友好:

    f4d9a4970111ffd81de655e07d2f17f0.png

    通过命令行对CPU、硬盘、网络进行试验,也可以对相应的服务进行类似的例如延时攻击试验:

    449888a68e4ed574f7c8e43d97df3830.png

    利用性能测试工具例如Jmeter或Gatling,对于API进行测试,例如POST /product?des=phone,通过性能测试报告对比API性能指标以及Hystrix监控分析相关服务“反应”,同时也可以通过Grafana和CloudWatch监控各个系统参数来和“稳定基线数据”进行比较和观察。


    混沌试验示例

    试验一:

    1.确定目标和范围,观察CPU利用率基线(CPU平均利用率低于20%)

    932140ce3ca7c6b01ddaee0fd2acb8e3.png

    观察API延时基线:(可以看到API-1和API-2平均延时低于300ms,API-3在300ms-700ms之间)

    cf01d984c6e6dabdab6cc60df3bc08ec.png

    2.设计实验数据和方案,我们对几个实例进行CPU满载攻击:

    48f5ad56beefeeef9d7d9ce33d98d33f.png

    观察CPU利用率:

    d7f8177aae9996dbdc425db8b24643d8.png

    观察API延时:(API请求延时变化明显,API-3延时更加严重)

    d29d32d940232624e4b769be943ee2ac.png

    试验二:测试服务熔断机制

    示例项目架构:Eureka服务发现注册,一个PROVIDER-SERVICE且有两个实例,一个CONSUMER-SERVICE,也可以通过zipkin之类的分布式跟踪系统也可以看到服务调用关系。

    d27fc9a49bebf9de3f23eb4ad227be9a.png

    1.对PROVIDER-SERVICE的实例2进行延时攻击

    a29dfe61ee2489b50582aff0260b7ce6.png

    2.查看PROVIDER-SERVICE instance 2的延时是否生效通过postman测试,可以看到API响应为30s:

    b23498b7d8adc4294dbb68658ba7f6af.png

    3.客户端请求相同的API

    60c47934caca34ac334d7fafaf2c1167.png

    观察结果:负载均衡生效,请求成功,熔断器关闭

    4.杀掉instance 1之后请求相同API

    a6baa3b065f9bf176697322cf46eff96.png

    观察结果:请求超时,熔断器关闭

    5.连续且请求相同API

    2dd496b8590f4b0c12a6cdc8337d7dd9.png

    观察结果:部分请求被立刻拒绝,加速服务失败的判定,熔断器开启

    6.杀掉instance 2请求API:

    773d9bf5782e22093de117751aa5b6d0.png

    观察结果:fallback机制生效,返回相应逻辑。

    这些只是混沌工程的简单使用方法,在实际项目中需要根据项目架构、业务复杂度、调用场景等设计试验细节。


    总结

    从业务的横切面到对微服务系统的纵切面观察,“契约测试”固然重要,但并不能代表微服务质量保证的全部。“蛮力”可以从某种意义上解决很多问题,但并不能催化出更高阶解决方案。同样,也只有了解到微服务的实现方式和原理才能够更好的理解系统并实施更有效的质量解决方案。

    Netflix对混沌工程的成熟度从“复杂度”和“接受度”两个方面给出了定义,可以看到,混沌工程或试验不单单是方法论的引入,更是实践上的渗透。用“Immersion”解释更加确切,与敏捷实践类似,这样的“服务级质量内建试验”对团队来说开始无疑是一种挑战,但随着越来越多的问题更快、更早的可视化给团队,使组织和客户对我们构建和改造中的系统越来越有信心。通过小规模实践到大规模改造,混沌工程不是为了测试,更不是为了引入工具, 混沌工程会像一种文化,将扩散于范围更广的团队和组织。

    0e159a71b155b8393532a5ea7a363f63.png

    先进制造业+工业互联网


    产业智能官  AI-CPS

    加入知识星球“产业智能研究院”:先进制造业OT(自动化+机器人+工艺+精益)和工业互联网IT(云计算+大数据+物联网+区块链+人工智能)产业智能化技术深度融合,在场景中构建“状态感知-实时分析-自主决策-精准执行-学习提升”的产业智能化平台;实现产业转型升级、DT驱动业务、价值创新创造的产业互联生态链。

    产业智能化平台作为第四次工业革命的核心驱动力,将进一步释放历次科技革命和产业变革积蓄的巨大能量,并创造新的强大引擎;重构设计、生产、物流、服务等经济活动各环节,形成从宏观到微观各领域的智能化新需求,催生新技术、新产品、新产业、新业态和新模式;引发经济结构重大变革,深刻改变人类生产生活方式和思维模式,实现社会生产力的整体跃升。产业智能化技术分支用来的今天,制造业者必须了解如何将“智能技术”全面渗入整个公司、产品、业务等商业场景中,利用工业互联网形成数字化、网络化和智能化力量,实现行业的重新布局、企业的重新构建和焕然新生。

    3d1db9e2448ba57fb13ccf1b5b0b00f8.png

    版权声明产业智能官(ID:AI-CPS)推荐的文章,除非确实无法确认,我们都会注明作者和来源,涉权烦请联系协商解决,联系、投稿邮箱:erp_vip@hotmail.com。

    展开全文
  • 假设你正在开发一个大型服务端企业应用,有如下需求: 必须支持多种客户端,包括:WEB 端浏览器、WAP 端浏览器以及原生移动 APP。 对外暴露公共 API 用于调用 处理 HTTP 请求,或者消息,执行对应的业务逻辑。 访问...

    原文地址:https://microservices.io/patterns/microservices.html

    场景描述

    假设你正在开发一个大型服务端企业应用,有如下需求:

    • 必须支持多种客户端,包括:WEB 端浏览器、WAP 端浏览器以及原生移动 APP。
    • 对外暴露公共 API 用于调用
    • 处理 HTTP 请求,或者消息,执行对应的业务逻辑。
    • 访问数据库,缓存或者持久化响应的数据
    • 与其他系统进行通信,交换所需的信息
    • 返回 HTTP 响应,指定好特定的序列化方式,例如 JSON、 XML 等等
    • 根据业务逻辑与功能,设计并划分出不同逻辑模块

    这样的一个应用,你会如何设计架构并部署呢?

    考虑因素

    • 这是一个团队开发的项目,有一个独立团队负责
    • 团队成员会发生变化,新加入的成员必须快速上手项目
    • 应用程序必须易于理解并修改
    • 期望能实现应用的持续集成与部署
    • 必须可以多实例部署应用程序,以满足可伸缩性和可用性要求。
    • 想用比较新的技术(框架、编程语言等)

    解决方案

    定义一个将应用程序构造为一组松散耦合的微服务协作架构,每个微服务满足:

    • 高度可维护和可测试:支持快速和频繁的开发和部署。
    • 与其他微服务松耦合:使团队能够在大部分时间独立地工作在他们自己的微服务上,而不受其他微服务更改导致的影响,同时也不会影响其他微服务。
    • 独立部署:使团队能够部署他们的服务,而不必与其他团队进行协调。
    • 减少沟通成本:可以拆分成小团队专注于各自的微服务,减少大团队内部沟通成本。

    服务使用同步协议(如 HTTP/REST )或异步协议(如 AMQP )进行通信。服务可以彼此独立开发和部署。每项服务都有其自有数据库以便与其他服务分离。服务之间的数据一致性使用 SAGA 模式

    举例

    假设现在正在设计一个电商应用,功能包括接收来自客户的订单(StoreFrontUI),验证并维护库存余额(Inventory Service),验证并维护用户可用余额(Accounting Service),下单成功并发货(Shipping Service)。这个应用被设计成一个微服务架构应用,如图中所示:

    image

    分析

    好处

    • 支持大型复杂应用程序的持续交付和部署
      • 可维护性增高:每个服务相对较小,因此更容易理解和更改。
      • 更容易被测试:服务更小,测试速度更快。
      • 更好的可部署性:服务之间可以独立部署。
      • 工作分工与模块业务边界更加明确,可以将某个微服务交付与一个或者多个团队维护。每个团队都可以独立于所有其他团队开发、测试、部署和扩展他们的服务。
    • 每个微服务相对更小:
      • 开发人员更容易理解
      • IDE 负载更低,更快,提高开发效率
      • 应用程序启动得更快,提高了 Debug 效率,也提高了部署速度。
    • 故障隔离。例如,如果一个微服务中存在内存泄漏,那么只有该微服务会受到影响。其他服务可以继续处理请求。
    • 更容易更新技术栈。当开发新的微服务模块可以采用新的技术栈进行试验开发并使用,稳定后,可以逐步推广到其他微服务。

    坏处

    • 开发人员必须面对分布式系统带来的额外复杂性
      • 开发人员必须熟悉 RPC 通信,并且写好故障处理逻辑。
      • 实现跨多个服务的请求更加困难。
      • 测试服务之间的交互更加困难。单元测试不能覆盖全部场景,集成测试部署起来更加麻烦。
      • 实现跨多个服务的请求需要团队之间的仔细联调。
      • IDE 大多面向构建单块应用程序,不提供对开发分布式应用程序的明确支持。
    • 部署复杂性。在生产中,部署和管理由许多不同服务组成的系统也具有操作复杂性。目前的容器化以及容器编排方案就是为了解决这一问题。
    • 增加内存等资源消耗。假设每个微服务都独占一个 JVM,那么相比与单体应用,JVM 本身占用的资源(例如 GC 占用的 CPU 和内存,还有元空间,代码高速缓存等等)比原来是更多了的。如果是一个微服务占用一个容器,乃至一个虚拟机,一个机器,这个资源浪费会更多。

    需要考虑的问题

    什么时候使用微服务架构?

    使用微服务架构的一个挑战是决定到底什么时候使用它。在开发应用程序的第一个版本时,通常不会遇到需要这种方法解决的问题。此外,使用更为精细的分布式体系结构设计将减缓开发速度。对于初创企业来说,这可能是一个重大问题,它们面临的最大挑战往往是如何快速发展业务和快速迭代应用程序。但是,随着产品不断迭代,这个单体应用程序将会变得越来越大,团队的规模也越来越大,需要使用功能分解为微服务架构时,复杂的依赖关系可能会让应用程序很难分解成一组服务。

    如何将应用程序分解为服务?

    另一个挑战是决定如何将系统划分为微服务。这在很大程度上是一门艺术,但有许多策略可以参考:

    • 按业务分解并定义与业务功能相对应的微服务。
    • 领域驱动的设计的子域分解
    • 用户行为与用例分解,并定义负责特定操作的微服务。例如 Shipping Service 负责运送完整的订单。
    • 定义一个负责对某个类型的实体/资源进行操作的微服务。例如 Account Service 负责管理用户帐户。

    理想情况下,每个服务应该只有一小部分责任。Bob Martin 谈到应该使用单一职责原则。就一个类而言,应该仅有一个引起它变化的原因。将单一责任原则应用于服务设计也是有意义的。

    另一个有助于服务设计的类推是 Unix 实用程序的设计。Unix提供了大量实用程序,如 grep、cat 和 find。每个实用程序只做一件事情,并且复杂的任务是通过使用shell脚本与其他实用程序组合来实现的。

    如何保持数据的一致性?

    为了确保松散耦合,每个服务都有自己的数据库。保持服务之间的数据一致性是一个挑战,因为对于许多应用程序来说,两阶段提交(2PC)或者分布式事务并不是一种很好的选择。应用程序必须使用 SAGA 模式,服务在其数据更改时发布事件,其他服务使用该事件并更新其数据。有几种可靠更新数据和发布事件的方法,包括事件溯源(Event Sourcing)和事务日志跟踪(Transaction Log Tailing).

    如何实现查询?

    另一个挑战是实现需要检索多个服务拥有的数据的查询。

    相关的设计模式

    image

    • 微服务拆解模式
    • 每个微服务数据库独立设计模式:每个服务如何拥有自己的数据库,以确保松散耦合。
    • 统一 API 网关模式:定义客户端如何访问微服务体系结构中的服务。
    • 客户端服务发现服务器端服务发现模式用于将客户端的请求路由到可用的服务实例。
    • 每个主机的单一服务每个主机多个服务模式,是关于部署策略的设计模式
    • 横切关注点设计模式(cross-cutting concerns):例如面向切面的设计,两个非常不一样的组件存在一些类似的功能,这时候我们需要切面设计来统一这些类似的功能。
    • 断路器
    • 存取令牌
    • 可观测模式
    • UI 相关模式
    • 测试相关设计模式:服务组件测试和服务集成契约测试(Contract Testing)
    展开全文
  • 以官方文档的说法,Dapr是一个可移植、事件驱动的运行时,让企业开发者更容易利用各种语言和框架构建柔性、无状态和有状态的微服务应用,并运行在云端和边缘。 Dapr的核心由Go语言写成,开发团队一开始有计划使用...
  • 近年来,微服务架构已成为最流行的分布式系统类型之一,但在微服务应用落地中,还存在软件资产复用效率较低、微服务应用能力对企业级持续交付的支撑不足、分布式架构下体验聚合度不够等问题,这些痛点有待全新的...
  • 本文将介绍微服务架构的演进、优缺点和微服务应用的设计原则,然后着重介绍作为一个“微服务应用平台”需要提供哪些能力、解决哪些问题才能更好的支撑企业应用架构。 微服务平台也是我目前正在参与的,还...
  • 微服务的概念在2005年被首次提出,随后的十年互联网爆发式增长。业务需求越来越复杂、用户习惯和...同时借助合适的微服务框架去逐步构建整个微服务体系是企业数字化转型一条快捷途径。 现在,Linux 基金会和TARS..
  • 微服务技术由于天生支持...当前,云服务商纷纷试水微服务产品,最为典型的,当属推出轻舟微服务平台、剑指整个微服务应用生命周期的网易云。 那么,在技术不断进步的趋势下,微服务又将何去何从?企业需要如何把握...
  • 当下最流行的设计架构便是微服务架构,越来越多的企业将老的服务拆分成微服务模式、在新的业务中采用微服务架构的设计理念进行技术架构设计。 其中实践的最好的莫过于阿里了,早期淘宝的架构是一个单体式架构,即...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,183
精华内容 1,273
关键字:

企业微服务应用