14、Dapr助力云原生应用开发:架构、模式与实践

Dapr助力云原生应用开发:架构、模式与实践

1. 云原生应用概述

云原生应用是专门为云环境设计的应用程序。就像攀登珠穆朗玛峰的登山者需要额外的氧气和专业装备来应对恶劣环境一样,将应用迁移到云环境也需要确保其具备在新环境中生存的能力。基础设施即服务(IaaS)为应用提供了模拟的本地环境,使其能在云端运行,但要充分利用云的优势,如按秒计费、动态扩展和无缝故障转移,应用必须能够适应云环境。

1.1 云环境与本地环境的差异

云环境与本地环境在管理服务器方面有着相同的使命,即保持基础设施对应用的可用性,但它们存在两个显著差异:
- 拥抱错误 :在本地数据中心,服务器崩溃对IT人员来说是糟糕的一天,但对开发人员来说可能是意外的休息。由于故障服务器的平均恢复时间(MTTR)通常较高,IT人员会严格控制服务器并实施严格的政策以确保其稳定性和高可用性。而在云环境中,一个普通的云数据中心通常拥有数十万台物理服务器和更多的虚拟服务器,即使只有1%的错误率,每天也会有数百甚至数千台服务器出现故障。云处理这些故障的方式是为用户分配另一台健康的服务器,而不是当场修复故障服务器。因此,应用的MTTR几乎完全取决于能否快速将应用迁移到新服务器并成功启动。此外,云平台可能会主动将应用迁移到不同的服务器以优化资源利用,这就要求应用能够在无需人工干预的情况下持续部署。容器技术提供了一种轻量级的方式,将应用及其所有依赖项打包在一起,使得应用能够快速迁移到不同的服务器并以可预测、一致的方式启动。
- 水平扩展 :在本地数据中心,当应用需要更多处理能力时,需要升级托管服务器或迁移到更强大的服务器。在云环境中,虽然也可以进行类似的升级,但这并没有充分利用云的弹性。云的弹性允许用户按需使用计算资源,并按实际使用量计费。当需要更多处理能力时,用户可以根据自身经济实力增加服务器数量,云会在每台服务器上部署应用实例,并通过负载均衡器将用户流量分配到所有连接的服务器上。水平扩展要求应用能够在多台服务器上稳定部署和配置。

1.2 云原生应用设计原则

云原生应用应设计为能够拥抱错误和水平扩展。具有以下特征的应用更能适应云环境:
1. 由自包含、松耦合的组件组成 :为减少服务器迁移可能导致的停机时间,应用应分解为更小的、可单独部署的组件。每个组件应自给自足,即使依赖的组件不可用也不会崩溃,而是在所有依赖项恢复后恢复正常运行。
2. 基于消息的集成 :当应用组件在可控的计算平面上运行时,它们可以按需移动。如果无法保证连接性,组件可以使用消息骨干通过消息进行连接。基于消息的集成和事件驱动设计有很多好处,例如可以消除系统中可能成为瓶颈的中心部分。
3. 可一致部署 :应用组件应打包成可以稳定部署的格式,除了预期的运行时环境(如容器运行时)外,不应依赖外部依赖项。通常需要一个包存储库来促进包的分发,但在简单情况下也可以使用文件共享。
4. 可观测性 :由于云环境中的应用由移动组件组成,当出现问题时很难跟踪发生了什么。因此,每个组件应向中央数据收集器报告遥测和跟踪信息,以便观察整个系统。同时,能够关联来自分布式源的数据以跟踪完整的调用链也很重要。
5. 与基础设施隔离 :虽然不必将应用设计为与云无关,但通常希望在应用和底层基础设施之间创建一个缓冲层,避免直接依赖特定于平台的服务,如状态存储、秘密存储和负载均衡器。这样可以使应用更灵活地适应需求的变化和不同的托管环境。
6. 水平可扩展 :应用组件应具有水平可扩展性,即组件实例不应假设自己是唯一的。如果实例之间共享状态,应用必须考虑潜在的读写竞争条件并准备解决可能的冲突。更好的设计是确保实例不维护本地状态或封装自己的状态,以最大化组件的移动性。
7. 明确的API :在复杂的分布式系统中,许多组件由不同的团队设计、实现和管理。明确将组件的接口定义为API是一种良好的实践,并应将其作为组件与任何消费者之间的具有约束力的合同。API定义应包括方法和数据合同,并应明确版本化,以避免在API设计演变时给客户带来混淆。

1.3 云环境与本地环境差异对比

对比项 本地环境 云环境
错误处理 严格控制服务器,MTTR高 分配新服务器,要求应用快速迁移
扩展方式 升级服务器或迁移 按需增加服务器实例
部署要求 相对稳定,人工干预多 无需人工干预,持续部署

1.4 云环境下应用特性mermaid流程图

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(云环境):::process --> B(拥抱错误):::process
    A --> C(水平扩展):::process
    B --> D(容器技术):::process
    B --> E(微服务架构):::process
    C --> F(负载均衡):::process
    C --> G(多实例部署):::process

2. Dapr助力云原生应用开发

Dapr是一个分布式应用运行时,旨在帮助构建云原生应用。其独特之处在于,它并不要求从一开始就采用微服务架构,而是允许用户根据自己的节奏发展应用,并在需要时提供帮助。

2.1 演化单体应用

假设我们有一个单体应用,所有逻辑都在一个代码包中,作为单例运行。它使用外部数据库保存状态,但也在内存中保留了相当数量的状态,并使用Microsoft Active Directory(AD)进行身份验证。

2.1.1 引入Dapr边车

首先,引入Dapr边车来接管内存状态访问。由于Dapr可以配置为使用内存中的Redis状态存储,这样做只会引入最小的延迟开销。这一更新不会影响访问外部状态存储的现有应用代码,体现了Dapr的非侵入性。应用代码本身变得无状态,这意味着代码可以被云平台轻松迁移,并且可以进行容器化以进一步提高代码的移动性。当将新容器化的应用部署到PaaS平台(如基于托管Kubernetes集群构建的平台)时,可以获得自动故障转移和更快的部署时间。

2.1.2 从单例模式转变

单体应用通常具有以下特征:
- 独占状态访问 :在单例模式下,应用拥有整个状态集,并对数据存储具有独占的读写访问权限。例如,在单例汽车预订系统中,应用可以查询数据库、找到未预订的汽车并为客户预订,无需担心在查询结果返回和预订操作完成之间被他人抢占。
- 内存状态的因果使用 :单例应用可以为了提高性能而在内存中保留状态。例如,投票应用可以在内存中保留领先候选人的列表,由于单例应用是唯一读写该列表的,因此可以安全地使用内存数据结构提供快速访问。
- 全局决策 :单例应用了解应用宇宙中的所有信息,因此可以随时做出明智的决策。例如,卡车车队调度程序可以根据完整的数据集计算所有卡车的最优路线。

如果希望打破单例模式,使应用能够水平扩展,可以考虑将代码的作业生成部分和作业处理部分分离,并将它们打包成两个单独的包。这可以通过引入一个作业队列来实现,将前端和后端解耦,这种策略被称为“扼杀者模式”,即逐渐将旧服务从单体应用中分离出来成为独立的微服务。分离后,作业创建者变为无状态,与前端的无状态特性相匹配,可以根据需要进行扩展以提供更好的响应时间。后端可以根据工作负载独立扩展。

2.1.3 进一步优化

可以将作业封装为一个参与者(actor),使作业成为一个自包含的元素,由作业处理器进行操作。甚至可以尝试使作业自主运行,作业处理器只需启动一个带有提醒功能的作业参与者,该提醒会不断检查作业是否完成。同时,可以使用Dapr身份验证中间件来处理身份验证。这样,应用就与底层基础设施解耦,能够在不同环境中动态重新配置。

2.2 设计全新的云原生应用

以一个预订度假旅行套餐的旅行社网站为例,该网站有面向个人用户的公共端点,也为企业提供定制化部署,以与现有系统(如会计和邮件系统)集成。

2.2.1 确定实体和用户工作流

在设计新系统时,可以识别系统管理的实体类型以及可以对这些实体执行的操作,然后围绕实体的创建、读取、更新、删除(CRUD)操作设计API。另一种方法是先确定系统的不同用户类型,然后围绕他们的工作流设计API(即领域驱动设计,DDD)。在使用Dapr设计应用时,可以采用混合方法,将系统中的实体建模为参与者,并根据用户活动定义API。假设系统中识别出以下实体:
- 度假套餐 :包括航班预订、汽车预订、酒店预订。
- 旅行者 :包括个人资料(如姓名、地址、旅行预算)、支付方式、预订信息。
- 旅行政策
- 合作伙伴 :包括个人资料(如名称、合同信息、服务类型)、库存、特别优惠和促销活动。

同时,识别出以下用户及其典型工作流:
- 管理员 :管理旅行政策、合作伙伴、度假套餐和旅行者。
- 旅行者 :预订度假套餐、取消预订。
- 合作伙伴 :更新库存、更新优惠。

2.2.2 设计架构

基于以上信息,可以设计一个包含UI层、API层和实体层的架构。大多数实体被封装为参与者,但合作伙伴库存保留为API,用于与合作伙伴的库存系统集成。在预订过程中,由于预订度假套餐是一个复杂的分布式事务,可能需要数分钟甚至数小时才能完成,因此可以使用一个“度假套餐”参与者来表示要预订的套餐。该参与者通过旅行者UI获得期望状态,并使用定时器检查其状态,通过调用相应合作伙伴的库存API来尝试使其与期望状态一致。同时,引入作业创建和处理分离的设计,将套餐生成和套餐预订解耦。旅行者API在收到请求时直接启动新的“度假套餐”虚拟参与者。

2.2.3 企业用户部署选项

对于企业用户,有三种部署选项:
- 为每个企业客户部署整个堆栈 :无需进行代码更改,但在管理多个客户时会带来挑战,例如跨部署共享合作伙伴库存。
- 使管理路径多租户 :需要进行有限的代码更改,但需要分别管理客户的部署。不同客户可能有不同的扩展因素、政策更新频率和托管环境需求,因此为每个客户提供单独的堆栈可能是最佳选择。
- 使所有内容多租户 :需要进行最多的代码更改,但可以最小化管理开销,因为只需要管理一个全局部署。

2.3 单体应用演化步骤列表

  1. 引入Dapr边车接管内存状态访问
  2. 评估是否打破单例模式
  3. 分离作业生成和处理部分
  4. 封装作业为参与者
  5. 使用Dapr身份验证中间件

2.4 旅行网站设计架构mermaid流程图

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(用户):::process --> B(UI层):::process
    B --> C(API层):::process
    C --> D(实体层):::process
    D --> E(度假套餐参与者):::process
    D --> F(旅行者参与者):::process
    D --> G(合作伙伴API):::process
    E --> H(库存API):::process
    F --> E
    G --> H

3. 云原生应用开发中的关键技术与模式

3.1 容器与微服务架构

在云环境中,容器和微服务架构是实现应用快速迁移和水平扩展的关键技术。

3.1.1 容器技术优势

容器提供了一种轻量级的方式,将应用及其所有依赖项打包在一起。这使得应用能够在不同的服务器上快速、一致地部署和运行,而不会出现依赖项丢失的问题。例如,使用Docker容器可以将应用和其依赖的库、环境等封装在一个独立的镜像中,然后在任何支持Docker的环境中运行。

3.1.2 微服务架构特点

微服务架构将应用拆分为多个小型、自治的服务。每个服务都可以独立开发、部署和扩展,从而提高了应用的灵活性和可维护性。例如,一个电子商务应用可以拆分为用户服务、商品服务、订单服务等多个微服务。

3.1.3 容器与微服务结合的好处

将容器和微服务架构结合使用,可以进一步提高应用的性能和可扩展性。容器可以为每个微服务提供独立的运行环境,而微服务架构可以使应用更易于管理和维护。

3.2 消息传递与事件驱动设计

消息传递和事件驱动设计是云原生应用中常用的集成模式。

3.2.1 消息传递的作用

消息传递允许应用组件之间通过消息进行通信,而不是直接调用。这种方式可以降低组件之间的耦合度,提高系统的灵活性和可扩展性。例如,一个订单处理系统可以通过消息队列将订单信息发送给库存管理系统和物流系统。

3.2.2 事件驱动设计的优势

事件驱动设计基于事件的发生来触发相应的操作。它可以使系统更加响应式和灵活,能够更好地处理异步操作和复杂的业务逻辑。例如,当用户下单时,系统可以触发一系列事件,如发送通知、更新库存等。

3.2.3 消息传递与事件驱动的结合

将消息传递和事件驱动设计结合使用,可以构建出高效、灵活的分布式系统。例如,使用Kafka作为消息队列,结合Spring Cloud Stream等框架,可以实现事件驱动的微服务架构。

3.3 状态管理与数据存储

在云原生应用中,状态管理和数据存储是一个重要的问题。

3.3.1 状态管理的挑战

在分布式系统中,状态管理面临着数据一致性、并发访问等挑战。例如,多个微服务可能需要同时访问和修改同一个状态。

3.3.2 数据存储的选择

常见的数据存储方式包括关系型数据库、非关系型数据库、内存数据库等。不同的数据存储方式适用于不同的场景。例如,关系型数据库适用于需要严格数据一致性的场景,而非关系型数据库适用于需要高并发读写的场景。

3.3.3 Dapr的状态管理

Dapr提供了统一的状态管理接口,可以支持多种数据存储方式。通过Dapr,应用可以更方便地管理状态,而无需关心底层的数据存储实现。

3.4 关键技术与模式对比

技术/模式 优势 适用场景
容器技术 轻量级、快速部署、一致性 云环境下应用的快速迁移和部署
微服务架构 灵活性、可维护性、可扩展性 大型复杂应用的开发和管理
消息传递 解耦、异步通信 组件间的通信和集成
事件驱动设计 响应式、灵活处理业务逻辑 处理异步操作和复杂业务逻辑
Dapr状态管理 统一接口、支持多种存储 云原生应用的状态管理

3.5 关键技术与模式mermaid流程图

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(云原生应用):::process --> B(容器技术):::process
    A --> C(微服务架构):::process
    A --> D(消息传递):::process
    A --> E(事件驱动设计):::process
    A --> F(Dapr状态管理):::process
    B --> G(快速部署):::process
    C --> H(灵活扩展):::process
    D --> I(组件解耦):::process
    E --> J(响应式处理):::process
    F --> K(统一状态管理):::process

4. 云原生应用开发的最佳实践

4.1 持续集成与持续部署(CI/CD)

持续集成与持续部署是云原生应用开发中的重要实践。

4.1.1 CI/CD的概念

持续集成是指频繁地将代码集成到共享的代码库中,并进行自动化测试。持续部署是指将经过测试的代码自动部署到生产环境中。

4.1.2 CI/CD的好处

通过CI/CD,可以提高代码质量、减少部署时间、降低部署风险。例如,使用Jenkins、GitLab CI/CD等工具可以实现自动化的CI/CD流程。

4.1.3 CI/CD的流程

一个典型的CI/CD流程包括代码提交、代码检查、单元测试、集成测试、构建镜像、部署到测试环境、用户验收测试、部署到生产环境等步骤。

4.2 监控与日志管理

在云原生应用中,监控与日志管理是确保应用稳定运行的关键。

4.2.1 监控的重要性

监控可以实时了解应用的运行状态,及时发现和解决问题。例如,监控应用的CPU使用率、内存使用率、响应时间等指标。

4.2.2 日志管理的作用

日志管理可以记录应用的运行信息,帮助开发人员进行故障排查和问题分析。例如,使用ELK Stack(Elasticsearch、Logstash、Kibana)可以实现日志的收集、存储和分析。

4.2.3 监控与日志管理的结合

将监控和日志管理结合使用,可以更全面地了解应用的运行情况。例如,当监控指标出现异常时,可以查看相应的日志信息,找出问题的根源。

4.3 安全与合规

安全与合规是云原生应用开发中不可忽视的问题。

4.3.1 安全措施

采取多种安全措施,如身份验证、授权、加密等,可以保护应用和数据的安全。例如,使用OAuth 2.0进行身份验证,使用SSL/TLS进行数据加密。

4.3.2 合规要求

不同的行业和地区可能有不同的合规要求,如GDPR、HIPAA等。在开发云原生应用时,需要确保应用符合相关的合规要求。

4.3.3 安全与合规的实践

建立安全的开发流程,进行安全审计和漏洞扫描,定期更新安全补丁等,可以提高应用的安全性和合规性。

4.4 最佳实践列表

  1. 采用CI/CD流程,实现自动化部署
  2. 建立完善的监控和日志管理体系
  3. 采取多种安全措施,确保应用和数据安全
  4. 遵循相关的合规要求,进行安全审计和漏洞扫描

4.5 最佳实践mermaid流程图

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(云原生应用开发):::process --> B(CI/CD):::process
    A --> C(监控与日志管理):::process
    A --> D(安全与合规):::process
    B --> E(自动化部署):::process
    C --> F(实时监控):::process
    C --> G(日志分析):::process
    D --> H(身份验证):::process
    D --> I(数据加密):::process
    D --> J(合规审计):::process
通过短时倒谱(Cepstrogram)计算进行时-倒频分析研究(Matlab代码实现)内容概要:本文主要介绍了一项关于短时倒谱(Cepstrogram)计算在时-倒频分析中的研究,并提供了相应的Matlab代码实现。通过短时倒谱分析方法,能够有效提取信号在时间倒频率域的特征,适用于语音、机械振动、生物医学等领域的信号处理故障诊断。文中阐述了倒谱分析的基本原理、短时倒谱的计算流程及其在实际工程中的应用价值,展示了如何利用Matlab进行时-倒频图的可视化分析,帮助研究人员深入理解非平稳信号的周期性成分谐波结构。; 适合人群:具备一定信号处理基础,熟悉Matlab编程,从事电子信息、机械工程、生物医学或通信等相关领域科研工作的研究生、工程师及科研人员。; 使用场景及目标:①掌握倒谱分析短时倒谱的基本理论及其傅里叶变换的关系;②学习如何用Matlab实现Cepstrogram并应用于实际信号的周期性特征提取故障诊断;③为语音识别、机械设备状态监测、振动信号分析等研究提供技术支持方法参考; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,先理解倒谱的基本概念再逐步实现短时倒谱分析,注意参数设置如窗长、重叠率等对结果的影响,同时可将该方法其他时频分析方法(如STFT、小波变换)进行对比,以提升对信号特征的理解能力。
先看效果: https://pan.quark.cn/s/aceef06006d4 OJBetter OJBetter 是一个 Tampermonkey 脚本项目,旨在提升你在各个在线评测系统(Online Judge, OJ)网站的使用体验。 通过添加多项实用功能,改善网站界面和用户交互,使你的编程竞赛之旅更加高效、便捷。 ----- 简体中文 ----- 安装 主要功能 安装脚本,你可以获得: 黑暗模式支持:为网站添加黑暗模式,夜晚刷题不伤眼。 网站本地化:将网站的主要文本替换成你选择的语言。 题目翻译:一键翻译题目为目标语言,同时确保不破坏 LaTeX 公式。 Clist Rating 分数:显示题目的 Clist Rating 分数数据。 快捷跳转:一键跳转到该题在洛谷、VJudge 的对应页面。 代码编辑器:在题目页下方集成 Monaco 代码编辑器,支持自动保存、快捷提交、在线测试运行等功能。 一些其他小功能…… [!NOTE] 点击 网页右上角 的 按钮,即可打开设置面板, 绝大部分功能均提供了帮助文本,鼠标悬浮在 ”? 图标“ 上即可查看。 使用文档 了解更多详细信息和使用指南,请访问 Wiki 页面。 如何贡献 如果你有任何想法或功能请求,欢迎通过 Pull Requests 或 Issues 我们分享。 改善翻译质量 项目的非中文版本主要通过机器翻译(Deepl & Google)完成,托管在 Crowdin 上。 如果你愿意帮助改进翻译,使其更准确、自然,请访问 Crowdin 项目页面 贡献你的力量。 支持其他OJ? 由于作者精力有限,并不会维护太多的类似脚本, 如果你有兴趣将此脚本适配到其他在线评测系统,非常欢迎,你只需要遵守 GP...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值