本文要点
在企业级软件开发中,API、服务、数据和系统集成是最具挑战性,同时也是最重要的需求;
过去,我们曾经将这些独立的应用以点对点的风格集成在一起,随后这种方式被 ESB(企业服务总线,Enterprise Service Bus)风格所代替,与之同时出现的还有面向服务架构(Service Oriented Architecture,SOA);
随着微服务和“云原生”架构的普及,出现了“服务网格”的概念。服务网格的核心思想是将所有业务逻辑的代码作为服务的一部分,同时将网络通信相关的逻辑放到到服务间通信基础设施之中。
因为服务网格提供了一些 ESB 的功能,所以有人将其误解为分布式 ESB,让它也负责应用集成。这是不正确的。
服务网格只是用来在服务间进行通信的基础设施,开发人员不应该在服务网格中构建任何业务逻辑。有一些其他的框架和库可以用来实现云原生企业应用的集成模式。
在企业级软件应用开发中,长期以来,API、服务、数据以及系统的集成都是最具挑战性同时也是最基本的需求。
在过去,我们会将这些独立的应用以点对点的方式进行集成,这种方式随后被企业服务总线(enterprise service bus,ESB)和面向服务架构(service-oriented architecture,SOA)所替代。
但是,在现代微服务和云原生架构中,我们很少再去讨论应用集成了。但这并不意味着这种现代架构已经解决了企业应用集成的所有挑战。
应用集成的挑战几乎没有什么变化,但是我们解决它们的方式却发生了变化。
从 ESB 到智能端点和哑管道
大多数采用 SOA 的企业都会使用 ESB 作为中心总线,以连接和集成所有独立的 API、服务、数据和系统。
如果给定的业务场景需要与组织中不同的实体进行通信的话,ESB 的职责就是探测所有的实体并创建组合功能。
因此,通常来讲,ESB 解决方案是所有内置集成功能的动力源,例如到不同系统和 API 的连接器、消息路由、转换、弹性通信、持久性和事务。
图 1:使用 USB 进行集成
但是,微服务架构倾向于通过构造智能端点和哑管道来替代ESB,这意味着我们的微服务必须要负责所有的应用程序集成。
智能 ESB 去中心化的一个代价就是微服务代码的复杂性会明显增加,因为除了服务的业务逻辑之外,它们必须还要处理这些应用集成的功能。例如,图 2 展现了多个作为智能端点的微服务(B、F 和 G),它们同时包含了与多个其他服务通信的结构和业务本身的逻辑。
图 2:微服务的服务间通信和组合
微服务架构的另一项挑战是如何构建不属于服务业务逻辑的特性,如弹性通信、传输级别的安全性、发布统计数据、将跟踪数据发布到可观察性工具等。服务本身必须将这些特性作为服务逻辑的一部分来进行实现。在每个微服务中实现所有的这些特性是非常复杂的,如果我们的服务是使用多语言(polyglot)实现的话,这会极大地增加相关的工作量,而服务网格可以解决这个问题。
图 3:实际的服务网格
服务网格的核心思想是将所有业务逻辑的代码作为服务的一部分,同时将网络通信相关的逻辑放到到服务间通信基础设施之中。在使用服务网格的时候,给定的微服务不会直接与其他的微服务进行通信。服务和服务之间的通信会通过一个额外的软件组件来进行,这个组件运行在服务的进程之外,叫做服务网格代理或 sidecar 代理。sidecar 进程和服务位于同一个虚拟机(VM)或 Pod(Kubernetes)中。sidecar 代理层也被成为数据平面(data plane)。所有的 sidecar 代理都会由控制平面(control plane)来进行控制,服务间通信相关的配置都会用到这里。
服务网格并不是用来进行应用集成的
因为服务网格提供了一些 ESB 的功能,所以有人将其误解为分布式 ESB,让它也负责应用集成。这是不正确的。服务网格只是用来在服务间进行通信的基础设施,我们不应该在服务网格中构建任何业务逻辑。假设我们有三个微服务,名为 X、Y 和 Z,它们以请求/响应的方式进行通信,为了实现业务功能,X 需要与 Y 和 Z 进行通信(参加图 4)。业务逻辑的组合应该是微服务 A 的代码,服务网格的 sidecar 不应该包含任何与组合逻辑相关的内容。
图 4:服务组合逻辑与服务网格
类似的,对于使用事件驱动通信的服务来讲,服务的代码应该处理所有的业务逻辑细节(值得一提的是,服务网格还没有完全支持事件驱动架构)。所以,即便我们基于服务网格运行微服务或云原生应用,这些服务和应用的集成依然是必要的。在现代微服务和云原生架构时代,应用集成是最关键的需求之一,但在很大程度上它依然是隐形的需求。
微服务和云原生应用的集成
在微服务和云原生应用中,应用集成或构建智能终端都涉及到集成微服务、API、数据和系统。这些集成需求涉及的范围从几个微服务之间的集成到与单体子系统的集成,再到创建反腐败层(anti-corruption layer)。深入研究微服务和云原生应用程序中的应用程序集成需求,我们会发现在应用程序集成框架中需要具备以下关键功能:
集成运行时必须是云原生的,能够平稳运行在 Docker/Kubernetes 中,并且提供与云原生生态系统的无缝集成。
它需要支持服务编排(orchestrations)/活动组合,这样给定的服务要包含调用多个其他服务的逻辑,从而能够组合业务功能。
它需要支持服务协同(choreography)/反应式组合,这样服务间通信可以通过同步的事件驱动通信来实现,避免出现包含服务交互逻辑的中心化服务。
它必须具有对各种消息协议(HTTP、gRPC、GraphQL、Kafka、NATS、AMQP、FTP、SFTP、WebSockets、TCP)的内置抽象。
它必须要支持消息和服务调用的分叉(forking)、连接(joining)、分割(splitting)、循环(looping)和聚合(aggregation)。
它需要支持存储和转发、持久化投递和幂等消息等技术。
它必须具有消息类型映射和转换的功能。
它必须能够与 SaaS(如 Salesforce)、专有方案(如 SAP)和遗留系统进行集成。
应该具有面向业务逻辑的消息路由。
它必须支持以补偿的方式实现分布式事务。
它必须具备长时间运行的工作流。
反腐败层必须能够连接微服务和单体子系统。
在任何微服务和云原生应用中,这些功能都是很常见的,但是从头进行构建可能是一项艰巨的任务。这也是为什么在构建微服务和云原生应用时,仔细分析这些功能并基于集成需求选择合适的技术和框架为何如此重要。例如,如果我们要构建的服务需要复杂的编排逻辑,那么我们选择的框架或技术应该能让这种类型的组合更易于编写。如果我们想要构建的服务要长期运行并且具备补偿功能,那么就要选择一个内置工作流和补偿功能的框架(参见 InfoQ 的文章“事件、流程和长期运行的服务:工作流自动化的现代解决方案”,Martin Schimak 和 Bernd Rücker 深入分析了当前面向云原生架构的工作流技术)。
尽管应用集成被大多数的微服务专家所忽视,但是像 Christian Posta(Red Hat 前首席架构师,Solo.io 的 Field CTO)这样的文章作者已经强调了应用集成的重要性,比如 Posta 的博客文章不能将应用程序的安全性和正确性放到Istio或其他服务网格上。Bilgin Ibryam 在 InfoQ 文章后Kubernetes 时代的微服务一文中,强调了云原生架构中应用集成的去中心化,以及如何基于服务网格构建应用集成。
CNCF 视野下的开发和集成
云原生计算基金会(Cloud Native Computing Foundation,CNCF)处在构建微服务和云原生应用程序的最前沿,它的目标是构建可持续的生态系统,并围绕一组高质量的项目打造一个社区,将容器编排作为微服务架构的一部分。CNCF 托管由开源技术和框架组成的项目,这些项目可以实现微服务或云原生架构的不同方面。我们可以看一下这些应用集成技术位于技术栈的什么位置。
CNCF 推荐的云原生路径有一个应用定义和开发(App Definition and Development)部分,但是没有专门的应用开发或集成的分类。考虑到应用程序集成的重要性,我们可以看到它将来会纳入 CNCF 之中。图 5 展示了应用定义和开发下的应用集成技术。
图 5:未来 CNCF 中的应用集成
应用集成相关的技术
尽管有很多单体的应用集成技术可供使用,但是,它们中的大多数并不适合云原生或微服务架构。在已有的集成提供商中,只有很少一部分为它们的产品和工具实现了针对云原生的变种。
有一些专门的集成框架,可以在应用集成领域实现通用的集成模式。通常,大多数这样的技术都是从传统的基于 ESB 的集成方式中继承而来的,但是它们都经过了修改,并且可以直接集成到云原生架构中:
Apache Camel/Camel-K是最流行的开源集成框架之一,Camel-K 项目基于 Camel 运行时为 Kubernetes 生态系统提供了无缝支持。
WSO2 Micro Integrator是开源 WSO2 企业级集成平台的云原生变种形式。Micro Integrator 提供了轻量级的集成运行时,它能在 Kubernetes 生态系统中直接运行。
尽管Spring Integration没有专门在 Kubernetes 上的运行时版本,但是它能够很好地用到云原生架构中的应用集成功能中。
一些应用开发框架也能满足应用集成的需求:
Spring Boot本身并不是一个集成框架,但是它具备应用集成所需的很多重要功能。
Vert.x是一个用于构建反应式云原生应用的工具包,它也能用来进行应用集成。
Micronaut是一个现代的、基于 JVM 的全栈框架,能够用来构建模块化和易于测试的微服务以及 serverless 应用。该框架内置了很多集成抽象,并且避免了传统框架(如 Spring)的复杂性。
Go、JavaScript/Node.js等编程语言有一些内置的或者可以以库的形式使用的应用集成特性。一些新兴的语言,比如Ballerina,语言本身就提供了对集成的抽象。
Quarkus是一个新的 Kubernetes 原生 Java 栈,它针对 GraalVM 和 OpenJDK 进行了定制,由最好的 Java 库和标准组装而成。它组合了多个应用开发库,比如 RESTeasy、Camel、Netty 等。
结论
在将单体应用拆分为微服务和云原生应用的过程中,如何连接这些应用的需求变得越来越具有挑战性。服务和应用程序分散在网络中,并通过不同的通信结构连接。实现任何的业务场景都需要微服务集成,这需要作为服务实现逻辑的一部分来完成。因此,在微服务和云原生架构时代,云原生应用集成是最关键的需求之一,但它在很大程度上是隐形的需求。
服务网格模式克服了微服务集成方面的一些挑战,但是它只提供了服务间通信的通用特性,这是独立于服务的业务逻辑的,因此业务场景相关的应用集成逻辑还是要在服务级别来实现。所以,最重要的是选择合适的开发技术来构建集成服务,并将服务组合在一起所需的开发时间最小化。有一些框架和技术正在出现,以满足云原生环境中应用集成相关的需求,我们需要根据每个特定的用例来评估这些技术。
关于作者
Kasun Indrasiri 是 WSO2 的集成架构主管,也是微服务架构和企业集成架构方面的作者/布道师。他撰写了《企业级微服务》(Apress)和《WSO2 ESB 入门》(Apress)。他是 Apache 的提交者,曾担任产品经理和 WSO2 Enterprise Integrator 的架构师。他曾在 O’Reilly 软件架构会议(GOTO Chicago 2019)和很多 WSO2 会议上发表过演讲,参加过旧金山湾区大部分的微服务会议。他在旧金山湾区创立了 Silicon Valley Microservice, APIs, and Integration 会议,这是一个独立于供应商的微服务会议。
原文链接:
Application Integration for Microservices Architectures: A Service Mesh Is Not an ESB
评论 1 条评论