微服务和 C++ 如何有效结合?

Blog
Author:
Amir KirshAmir Kirsh
Published On:
9月 5, 2021
Estimated reading time:
1 minute

微服务结构,是企业程序开发的一种流行方案,帮助开发或支持松散耦合的服务。通常,这些服务较小,协议为轻量级。服务,代表单个业务流程,因此微服务架构非常适合服务导向的程序,这与长期以来的主流一体化代码库不同。

传统上,企业应用程序由三个主要部分组成,其中包括数据库、用户界面和服务器端程序。服务器端包含整个程序的业务逻辑,一般用于提供大范围的功能。这种体系结构比微服务更固定。尽管传统的体系结构有其优点,但对这两种体系结构的比较,超出了本文的内容范围。因此,我们将聚焦 C++ 的微服务开发,以及它在这一领域与一体化程序的区别。这篇文章中介绍了一些微服务的实际用例。

C-Microservices

图片来源: https://docs.oracle.com/en/solutions/learn-architect-microservice

微服务的特性

微服务的两个主要特性,是模块化和扩展性。单个服务表示为模块,每个模块依据具体业务功能进行构建。各个服务各司其职,处理其对应的功能,且一般无法越过其功能界限。微服务可以独立部署,但这并不意味着,它们独立于其他模块。相反,尽管微服务之间是松散耦合的,且作为单独的进程运行,但各服务之间有通信机制。升级或更换模块操作简单,但要保证从整体体系结构来看,模块的功能是完善的。与一体式程序相比,微服务体系结构的扩展性更强。

微服务的交互性

值得注意的是,微服务通常属于大系统中的活跃部分,因此,各个服务间需要进行交互。一体化程序可能依赖于简单的函数调用,微服务则使用不同协议进行进程间的通信,例如 HTTP(如 REST API)、TCP(针对基于二进制的协议)或 AMQP(也可使用 TCP)。

微服务可以使用任何形式的数据进行交互,但通常以 JSON、XML 或二进制为基础。基于 REST API 的微服务通常以 JSON 的形式传递数据。“微服务”一词并没有将其局限于某个功能,你甚至可以使用非标准格式。不过,我们不建议将其用于公开发布的服务。智能端点和哑管道(非智能管道)的原理与微服务相似,指的是在服务之间进行简单的通信。

微服务可内外兼用

shutterstock_1981823216_Microservices-Architecture.

微服务可以在内部使用,为产品组件建立功能,也可以在外部使用,便与第三方解决方案交互。内部微服务可能在微服务集群中运行,在功能丰富的一体式程序中,充当一个模块的角色。

内部微服务可通过 API 访问,但这并不意味着 API 是公共的。相反,服务是特定于产品的,功能不能单独提供给第三方。

外部微服务可以向其他产品提供其功能,通过公开公共 API。第三方系统可以使用此接口来使用这项服务。例如 Open Weather,它是一个公开的 API 平台,提供各种与天气相关的数据。我们可以发送一个有效的请求,这个程序将返回相应的数据块,客户机因此可以使用这些数据。

微服务基础设施

开发者通常依赖某种基础设施来使用微服务,这样可以避免编写通信和协议解码编码文件,因此开发者只需在服务中实现具体代码的功能。

创建微服务的流行基础设施

有几种可用于创建微服务的基础设施,但具体使用哪种基础设施,通常由编程语言决定。例如,Flask 可以用于微服务,但如果你的代码是使用 Python 编写的,通常较为普遍的选择是 FastAPI。同样,Spring Boot 很受 Java 开发者的追捧,支持嵌入式服务器,便于使用容器部署的,并且可以抵消对外部服务器的需求。但如果你是使用 NodeJS 进行开发,那么你可以使用开源工具 ExpressJS 或 Moleculer,这两种都是非常流行的框架。

为什么表面上微服务与 C++ 关系不大?

对于微服务开发,大家倾向选择简单的语言。流行的微服务开发语言包括Java、Python、Javascript 和 Go。许多人都觉得 C++ 是一种较为复杂的语言,尽管 C++ 在运行时速度和内存管理上有其独特的优势。但在大部分情况下,微服务不需要这种级别的性能,特别是当服务以 RESTful API 为基础运行时。

很多用例显示,当所有模块需要在同一进程中运行时,使用 C++ 编写代码有其优点。因为组件之间的外部通信需求消失了,相反,通讯依赖于直接的 API 调用。这仍然可以进一步模块化,而且应该进行模块化。不同的组件可以构建一些代码库,各个代码库之间静态或动态链接,在运行时可动态加载,最终在同一进程中运行。但这就不属于经典的微服务范畴了。

为什么微服务与 C++ 仍然有关联?

对于计算密集型的微服务来说,C++ 可能是一个不错的选择。

在 C++ 中,你可以看到更多的二进制服务(例如,使用 GRPC 协议),而不是使用 RESTORY API 的文本服务:在性能极其重要的情况下,我们大都会选择 C++。相对地,文本 API(如REST)则不是首选。

如果你有一个微服务结构,且使用 C++ 更具优势,你想向其公开外部 API,通过选择协议来实现。然而,还有一些细节值得考虑。例如,如果服务器返回的数据块相当大,我们则可以压缩二进制流以节省带宽。当然,服务可能同时公开二进制和文本 API,最终的选择权将留给客户。

虽然 C++ 向微服务架构转移的趋势较慢,但是传统上,C++ 开发者喜欢在同一个进程中运行所有的组件,因此 C++ 与微服务依然有其联系,我相信,慢慢地,我们会看到 C++ 微服务的转变,其动力主要是基于二进制协议,另外还有一部分性能原因。

微服务的 C++ 框架

可用于微服务开发的 C++ 库和框架不计其数。其中一个是  C++ Micro Services,简化了程序的构建和管理,尤其针对模块化及以动态服务导向的程序。另外一些可用于 C++ 微服务的框架包括 C++ REST SDK、 Crow、HttpLib、 Pistache、Restbed 和 Restinio。这些流行框架的基准测试可点击链接阅读。更多其他的框架,可从这个列表中获取。这些丰富的信息说明,不论 C++ 开发者想要支持什么协议,他们都有很多选择。更多与这个主题相关的一些框架讨论,在这里也有一些展示。

微服务的挑战

 shutterstock_305188655_Challenges-of-Microservices.

采用微服务结构有其优点,但与大多数事物一样,优势与劣势并存。实际上,一个设计粗糙的微服务,其开发时间可能更长,且失败的频率更高。编写微服务有不少难点,其中最主要的一些难点是,定义合适的API、区隔微服务、服务间通信、错误处理和总体复杂性。

在为微服务设计 API 时,需要考虑到每个微服务都将使用 API 进行通信。所以首先要清楚哪些是共享数据,一旦确定了这一点,微服务结构就拥有了与一体式程序竞争的能力。这种情况下,关于 API 通信最重要的一点,是松散耦合。如果无法简化依赖关系,那么,你选择使用微服务初衷,即微服务的基础优势很可能都无法实现!

进行测试时,微服务需要视为独立的组件,这就需要对每个微服务进行更严格的测试。与一体式程序中的相同功能相比,微服务之间的区隔,让测试更容易,因为你可以单独测试每个服务。但是测试每个微服务时,我们应该考虑所有可能的输入和程序流,特别是当调用方来自程序外部时。

错误处理、调试和故障排除也是如此,由于微服务之间的松散耦合和相互通信,问题变得更加复杂。与一体式程序相比,分析错误可能变得很复杂,因为程序流是分散的,几个不同的微服务可能报告同一错误的一小部分。此外,与错误相关的数据可能在某些微服务中丢失,因此定位错误的根源变得更加困难。

最后一点,通过多个微服务跟踪请求,比跟踪一体式程序中的函数调用更困难。

结论

与一体式系统不同,微服务将复杂程序分解为更小、更易于管理的组件,以此简化程序开发。微服务是模块化的,本质上更具扩展性。与此同时,微服务确实带来了其他需要考虑的问题。首先,微服务开发中在部分编程语言中很流行,但 C++ 微服务开发还有待发展。在实践中,C++ 是一种可使用微服务的优秀编程语言,特别是当进程需要 C++ 的优势功能,如运行时速度和直接内存访问时。另外,与其他编程语言一样,支持 C++ 微服务的基础设施多种多样,方便你开始尝试微服务。

Whitepaper download