云原生软件架构

转载:原创 易立 阿里巴巴中间件

https://mp.weixin.qq.com/s/PwPC1ZWNZvzQoOZvOAF2Qw

前言


 

在《云原生基础设施》一文中我们谈到了,云原生计算包含三个维度的内容,云原生基础设施,软件架构和交付与运维体系,本文将聚焦于软件架构层面。

“Software architecture refers to the fundamental structures of a software system and the discipline of creating such structures and systems. ” - 维基百科。

 

在我的理解,软件架构主要目标是解决下列挑战:

  • 控制复杂性。由于业务的复杂性,需要我们用更好的手段帮助研发组织克服认知障碍,更好的分工协作。分而治之,关注点分离等手段皆是如此。

  • 应对不确定性。业务在快速发展,需求在不断变化。即使再完美的软件架构,然而随着时间的推移,团队的变化,软件架构的调整不可避免。读《设计模式》,《微服务设计》等书字里行间写的都是“解耦”两字,让我们关注架构中确定性和不确定性的分离,提升架构的稳定性和应变能力。

  • 管理系统性风险。管理系统中的确定性以及不确定性风险,规避已知陷阱,对未知的风险做好准备。

云原生应用架构的目标是构建松耦合、具备弹性、韧性的分布式应用软件架构,可以更好地应对业务需求的变化和发展,保障系统稳定性。本文将分享我在这个领域的观察和思考。

缘起 - 12要素应用


 

2012 年,Heroku 创始人 Adam Wiggins 发布十二要素应用宣言。它为构建一个优雅的互联网应用,定义了需要遵循的一些基本原则和方法论,也广泛影响了众多的微服务应用架构。十二要素重点关注:应用程序的健康成长,开发者之间的有效的协作,以及避免软件架构腐化的影响。其内容在今天也值得每个同学认真体会。

 

图片来源:https://12factor.net/zh_cn/

12 要素应用为我们提供了很好的架构指导,帮助我们:

  • 构建水平伸缩的弹性应用架构,更好支撑互联网规模应用。

  • 提升研发流程的标准化、自动化水平,提升研发效率。

  • 减少开发环境和生产环境的差异,并使用持续交付实施敏捷开发。

  • 提升应用的可移植性,适合云化部署,降低资源成本和管理复杂性。

松耦合架构设计


 

微服务的核心理念是,系统中的各个服务可被独立开发、独立部署,独立升级,各个服务之间是松耦合的。云原生应用架构理念是进一步强调架构的松耦合,降低服务之间相互依赖的程度。

API 优先的应用架构设计

在面向对象的软件架构中,最重要的是定义对象以及对象的接口契约。SOLID 原则是最被人广为熟知的设计原则。

  • Single responsibility principle - 单一职责原则

  • Open/closed principle - 开放/封闭原则

  • Liskov substitution principle - 里氏替换原则

  • Interface segregation principle - 接口隔离原则

  • Dependency inversion principle - 依赖翻转原则

将以上五个原则的英文首字母拼在一起就是 SOLID 原则,这也是帮助我们构建高内聚,低耦合、具备柔性的应用架构。在分布式微服务应用架构中,API优先是契约优先(Contract First)的自然拓展。

API 应该是被优先设计的:我们知道用户需求是复杂多变的,比如从桌面到移动端,应用的展现方式和操作流程都有可能不同;然而业务逻辑的概念模型和服务交互是相对稳定的。相对而言,API 的接口是更加稳定的,而具体的实现是可以迭代实现和持续变化的。定义良好的 API 可以更好保障应用系统的质量。

 

API 应该是声明式,可描述/自描述的:通过规范化的描述,API 易于沟通、易于理解、易于验证,简化开发协同。支持服务的消费者和提供者并行开发,加速开发周期。支持不同的技术栈的实现,比如对于同一个 API 接口,其服务实现采用 Java 。前端应用可以使用 JavaScript ,而服务器端应用可以使用 Golang 进行服务调用等等。这样可以让开发组织可以根据自己的技能栈和系统要求灵活选择合适的技术。

API 应该具备 SLA :API 作为服务间的集成界面,与系统的稳定性息息相关。SLA 应该作为 API 设计的一部分,而不是部署后再考虑。在分布式系统中,稳定性风险无处不在,通过 API 优先的设计模式,我们对独立的服务进行稳定性架构设计、容量规划;我们还可以对独立的 API 进行故障注入、稳定性演练,来消除系统性的稳定性风险。

在 API 领域,最重要的趋势是标准化技术的崛起。gRPC 是 Google 开源的的高性能、通用的、平台无关的 RPC 框架。它采用分层设计,其数据交换格式基于 Protobuf  (Protocol Buffers) 协议开发,具备优秀的序列化/反序列化效率,也支持众多开发语言。在传输层协议, gRPC 选择了 HTTP/2,相较于 HTTP/1.1,其传输效率有了很大提升。此外 HTTP/2 作为一个成熟的开放标准,具备丰富的安全、流控等能力,同时拥有良好的互操作性。gRPC 不仅可以用于 Server 端服务调用,也可以支持浏览器、移动 App 和 IoT 设备与后端服务的交互。gRPC 在功能上已经具备完整的 RPC 能力,也提供了扩展机制来支持新的功能。

在 Cloud Native 的潮流下,跨平台、跨厂商、跨环境的系统间互操作性的需求必然会催生基于开放标准的 RPC 技术,而 gRPC 顺应了历史趋势,得到了越来越广泛地应用。在微服务领域, Dubbo 3.0 宣布了对 gRPC 协议的支持,未来我们也会看到更多的微服务架构基于 gRPC 协议开发,并提供良好的多语言支持。此外,在数据服务领域,gPRC 也成为一个优秀的选择,大家可以参考 Alluxio的文章:

https://www.alluxio.io/blog/moving-from-apache-thrift-to-grpc-a-perspective-from-alluxio/

此外在 API 领域 Swagger (OpenAPI规范),GraphQL 都是大家值得关注的开放标准。大家根据自己的业务诉求灵活选用,本文不再赘述。

Event Driven Architecture 的崛起

谈事件驱动架构 (EDA - Event Driven Architecture),我们首先来解释一下什么是事件。事件是指对已经发生的事情、状态变化等的记录。它们是不可变的(无法更改或删除),并且按其创建顺序排序。相关各方可以通过订阅已发布的事件来获取有关这些状态变化的通知,然后使用所选择的业务逻辑根据这些信息采取操作。

事件驱动架构是一种构建松耦合的微服务系统的架构方式,微服务之间通过异步事件通信来进行交互。

事件驱动架构实现了事件的生产者和消费者的彻底解耦。生产者无需关注事件如何被消费,同时消费者无需关注事件的生产方式;我们可以动态添加更多消费者而不影响生产者,可以增加消息中间件对事件进行动态路由和转换。这还意味着事件的生产者和消费者没有时序上的依赖,即使由于应用宕机无法及时处理消息,在重新恢复后,程序可以继续从消息队列中获取这些事件继续执行。这样的松耦合架构,为软件架构提供更高的敏捷性、灵活性和健壮性。

事件驱动架构的另一个重要优点是提升了系统的可伸缩性。事件生产者在等待事件消费时不会被阻塞,并且可以采用 Pub/Sub 方式,让多个消费者并行处理事件。

事件驱动架构还可以完美地与 Function as a Service (FaaS) 相整合。事件触发函数执行业务逻辑,在函数中也可以编写集成多个服务的“胶水代码”,简单、高效地构建事件驱动架构的应用。

但是 EDA 架构依然存在很多挑战。

  • 分布式的松耦合架构大大增加了应用基础设施的复杂性。基于云的部署交付方式和云服务(消息队列、函数计算服务等)可以使得该架构的稳定性,性能和成本效益进一步提高。

  • 与传统同步处理方式相比,异步事件处理存在与事件排序、幂等性、回调和异常处理相关的要求,整体设计难度更大一些。

  • 在大多数情况下,由于缺乏跨多个系统的分布式事务支持,维护数据一致性是非常具有挑战性的。开发者可能需要权衡可用性和一致性之间的关系。比如通过Event Sourcing(事件溯源)实现最终一致性,详情:

    https://martinfowler.com/eaaDev/EventSourcing.html

  • 互操作性。在现实世界中,事件无处不在,然而不同生产者对事件的描述却不尽相同。开发者希望无论事件是从哪里发出,都能够以一致的方式构建事件驱动的应用程序。CloudEvents(https://cloudevents.io/) 是一种以通用、一致的方式描述事件数据的规范,由 CNCF Severless 工作组提出,提升了事件驱动应用的可移植性。目前,阿里云 EventBridge、Azure Event Grid 等事件处理中间件,以及 Knative Eventing ,阿里云函数计算等 FaaS 技术已经提供了对 CloudEnvents 的支持。

由于 EDA 自身架构的优点,在互联网应用架构,业务数据化和智能化、IoT等场景有非常广阔的前景。关于 EDA 的架构讨论,不在此继续展开。

面向交付的应用架构

在云原生软件架构中,我们在设计阶段不只是关注软件如何被构建,也需要以终为始。关注如何合理设计和实现软件,才可以被更好地交付和运维。

应用和运行环境解耦

在 12 要素应用中,应用和运行环境解耦就已经被提出。而 Docker 容器的出现则进一步加强了这个理念。容器是一种轻量化的应用虚拟化技术,容器之间共享操作系统内核,支持秒级启动,Docker 容器镜像是一个自包含的应用打包格式,将应用和其依赖(如系统库、配置文件)等打包在一起,在不同环境保持部署一致性。

容器可以作为 Immutable Infrastructure (不可变基础设施)的基础,提升应用交付的稳定性。不可变基础设施是由 Chad Fowler 于 2013 年提出的构想:在这种模式中,任何基础设施的实例(包括服务器、容器等各种软硬件)一旦创建之后便成为一种只读状态,不可对其进行任何更改。如果需要修改或升级某些实例,就是创建一批新的实例进行替换。这种模式的可以减少了配置管理工作的负担,保障系统配置变更和升级可以可靠地重复执行,避免令人头疼的配置漂移问题;易于解决部署环境间的差异,让持续集成与持续部署过程变得更流畅;支持更好的版本管理,在部署出错时可进行快速回滚,

Kubernetes 作为容器的分布式编排调度系统,进一步提升了容器应用的可移植性。K8s通过一系列抽象如 Loadbalance Service, Ingress, CNI, CSI,帮助业务应用可以屏蔽底层基础设施的实现差异,灵活迁移。通过这样的能力,我们可以实现工作负载在数据中心、边缘计算和云环境的动态迁移。

在应用架构中,我们需要避免将静态环境信息,比如IP,mac地址等与应用逻辑耦合。在微服务架构中,可以利用 Zookeeper/Nacos 等实现服务的注册发现;在 Kubernetes 中,我们可以通过 Service,Service Mesh 减少对服务端点IP的依赖。此外,对应用状态的持久化也尽可能通过分布式存储或者云服务等实现,这样可以大大提升应用架构可伸缩性和自愈能力。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值