在过去的十年中,Web 应用程序已经发展到可以容纳数百万用户并产生数 TB 的数据。这些应用程序的用户期望快速响应和 高可用性。为了使应用程序快速可用,它们必须快速响应以增加负载。实现这一目标的一种方法是使用微服务架构。
在本文中,您将了解微服务架构的含义、它与其他软件架构模式的比较以及使之成为可能的技术。您还将了解微服务架构的优缺点、应避免的实践,并获得资源以进一步提高您的知识。
入门 | 微服务
微服务架构是一种软件架构模式,其中应用程序执行的每个任务都由称为服务的独立应用程序处理。该服务通常管理自己的数据库,并通过事件、消息或 REST API 与其他服务通信。微服务简化了构建软件的任务,尤其是在规模上。
微服务可帮助您实现以下目标:
- 提高开发人员的工作效率并让开发团队拥有更大的自主权。
- 使独立扩展应用程序变得更加容易。
- 使发布新功能更容易,因为不必为每次更改重新部署整个应用程序。
什么是微服务?
微服务是一组独立的、用途有限的应用程序,它们共同构成一个更大的应用程序。
以电子商务应用程序为例。产品列表功能可以打包为单个服务,价格计算功能也可以。当用户选择产品并查看价格时,价格计算服务将计算折扣和运费。每项服务都可以拥有自己的专用数据库和 Web 服务器,从而可以根据需要进行扩展。
微服务允许系统更加模块化。您无需构建单个大型系统,而是构建一组服务,每个服务处理系统的一个方面。在微服务成为主流之前,工程团队将系统构建和部署为单个内聚单元。这有时会导致开发和可扩展性瓶颈,因为对应用程序的每次更改都需要重新构建整个应用程序。这意味着开发人员在如何进行更改方面的自由度较低,并且在扩展到更强大的部署目标时需要重新部署整个应用程序。微服务解决了这些问题,使您能够构建快速且可扩展的系统。
为什么微服务很重要?
与单体架构相比,微服务架构提供了一些实质性的好处:
- 微服务允许系统模块化。进行更改时,大型应用程序通常需要数小时才能重建,但微服务消除了部署整个代码库的构建时间瓶颈。当每个团队都维护自己的微服务时,他们对如何进行更改和部署有更多的自主权。
- 因为其他服务可以使用不同版本的服务,所以团队能够以不同的速度移动。版本控制可以使用语义版本控制来完成,确保每个重大更改都作为主要版本发布。例如,如果有两个服务 A 和 B,并且服务 B 的新部署包含重大更改,则服务 A 可以继续使用服务 B 的先前版本,直到它准备好迁移到新版本为止。
- 微服务允许更好的系统范围的资源共享,因为每个服务只获得它需要的资源。
微服务架构与其他方法的比较
虽然微服务架构是一种非常流行的构建应用程序的方式,但它并不是唯一的。以下是它与其他一些常见方法的比较。
单体架构
在微服务成为主流之前,单体架构被广泛使用。单体架构意味着系统的所有组件都部署在一台机器上。
单体应用是垂直扩展的,这意味着部署目标的 RAM 和 CPU 等计算资源会增加。负载的增加意味着必须部署副本机器以满足需求,每个机器都通过负载均衡器接收一部分负载。随着负载的增加,使用单个数据库变得越来越困难,并且也必须进行复制。该复制数据库必须确保已部署节点之间的一致性。在单个机器上运行每个组件所产生的一致性和紧密耦合是单体架构的主要缺点。
微服务是独立部署的,每个服务都有自己的数据库。每项服务都可以扩展以满足需求,新的部署不必花费数天时间来完成。
面向服务的架构
面向服务的架构或 SOA 是一种架构模式,旨在解决由单体系统产生的问题。在 SOA 架构中,每个服务都存在于系统的专用层上。它与微服务架构的不同之处在于,它依赖于服务总线来促进服务层之间的通信,这意味着所有层都使用相同的通信途径。
微服务架构如何工作?
微服务应用程序由许多较小的应用程序组成,每个应用程序都处理应用程序的一个单独功能。服务根据需要与其他服务进行通信以实现其功能。即使在下面非常简化的图表中,您也可以看到 API 网关如何处理来自前端用户的传入请求并将它们传递给适当的服务,然后根据需要直接相互通信。
微服务相互通信
微服务架构的优点和局限性
与任何架构模式一样,微服务架构既有优点也有局限性。
微服务的优点
微服务允许与语言无关的应用程序开发。这意味着团队可以使用最适合该应用程序类型的语言构建应用程序。一个团队可以使用 Node.js 构建实时聊天应用程序后端以利用 Node.js 的流式传输功能,而另一个团队可以使用 Rust 来构建图像处理微服务。这导致系统范围的性能改进。
由于每个服务都可以由专门的团队构建,因此每个团队只需要担心系统的一部分。在微服务架构中,团队在如何构建和部署服务方面拥有自主权。这使团队能够独立工作,而不必担心他们的更改会对系统的整体状态产生巨大影响。这也与持续测试和交付的敏捷理念很好地结合在一起。
微服务还促进重用和协作。为了使微服务中的组件保持一致,团队经常使用共享库。这种共享仍然允许服务解耦,但保持一致。此外,微服务允许在其他应用程序中重用部分服务——如果已经为一个应用程序构建了聊天功能,并且以后的应用程序也需要该功能,则可以在以后的应用程序中使用相同的微服务。
每个组织都希望其产品在使用高峰时具有可扩展性。微服务可以无限横向扩展,它们的轻量级特性意味着每个服务都可以更好地扩展以满足传入的需求。随着更多负载被引入系统,可以添加更多服务器来平衡负载。
微服务是高度容错的。即使一项服务出现故障,架构固有的隔离性质也意味着其他服务可能在很大程度上不受影响。由于单个服务相对较小,停机时间通常可以很快得到补救,因为可以立即清楚问题源自服务的哪一部分。
微服务的局限性
尽管有所有好处,但微服务也有一些限制。它们需要运营团队进行更多配置,因为不同的服务需要有效地相互通信。此外,由于微服务架构的分布式特性,监控和可观察性工具需要与它们一起部署。
使微服务成为可能的工具和技术
微服务架构是一种架构模式。这意味着它不会强迫团队使用特定的工具和技术;相反,它建议解决该模式的技术。
微服务作为容器部署在集群中,容器可以根据流量进行配置和扩展。容器通过 API 协议进行通信,消息队列帮助缓冲消息以防止服务过载。身份验证和授权部署为一个或多个单独的服务。以下是适合这种模式的一些工具和技术。
容器化
容器化是将软件打包成易于复制的单元,这些单元与机器中的其他软件隔离开来。使用 Docker 和 Kubernetes 等工具可以做到这一点。
Docker是一个工具,它允许您在一个名为image的文件中定义运行软件所需的所有要求(例如操作系统、运行时和源代码),并从该映像构建称为容器的独立应用程序。微服务通常部署为 Docker 容器,这使团队能够随着负载的增加添加更多容器。
Kubernetes是一个容器编排工具,这意味着它可以管理配置了多少容器,以及它们如何在网络中扩展。随着特定微服务负载的增加,Kubernetes 可以提供更多容器来满足该负载。当负载减少时,它会拆除额外的容器。Kubernetes 具有三种众所周知的自动缩放方法,包括 Horizontal Pod Autoscaler (HPA)、Vertical Pod Autoscaler (VPA) 和 Cluster Autoscaler。
云提供商
云提供商减轻了大规模构建微服务的财务压力。它们以服务的形式提供软件基础架构,例如虚拟机和容器注册表。这通常只相当于在数据中心运行您自己的基础架构成本的一小部分。云提供商使组织能够以具有成本效益的方式部署其微服务。如果没有云提供商,希望在全球范围内运作的组织将需要在多个区域拥有自己的数据中心,并且还必须自己管理其基础设施。
身份验证提供程序
为了使分布式服务能够有效地进行通信,需要有一种跨不同服务访问用户数据的方法。为此,您可以使用像Okta这样的身份验证提供程序,或者将自己的身份验证服务实现为独立的微服务。为了使独立的微服务有效,您需要有一个健壮的身份验证系统。
CI/CD
持续集成和持续部署 (CI/CD) 工具使开发人员能够在开发新功能和修复现有错误时不断将代码推送到服务器。由于微服务是独立部署的,因此该架构要求每个团队能够以快速有效的方式推送新功能和错误修复。诸如Jenkin、Travis CI和GitHub Actions等 CI/CD 工具有效地服务于这一目的。
基础设施即代码 (IaC)
基础设施即代码是一种范式,它允许运维团队将其基础设施定义为配置文件,通常在YAML中。这使他们能够在可以部署微服务的云提供商中快速启动服务。常见的 IaC 工具包括Terraform、Pulumi和Ansible。
用于实现微服务的模式
为了有效的微服务实施,必须实施某些工具和模式。这些模式的范围从 API 网关到访问令牌。本节将介绍这些模式以及如何将它们集成到微服务架构中。
API 网关
API 网关是一种服务,用于管理微服务网格中的不同微服务。API 网关通过仅向互联网公开一个公共 IP 来帮助保持微服务的私密性。它们还有助于服务发现、负载平衡、IP 白名单、响应缓存、重试和速率限制。常见的 API 网关包括Kong、Ambassador和Ocelot。
访问令牌
访问令牌是一种从中央身份验证提供程序向不同服务提供授权的功能。一个组织通常会部署一个处理身份验证的微服务,该服务将与其他服务通信以向用户数据的不同部分提供授权。
日志聚合
日志聚合是将来自不同微服务的日志组合到单个日志文件中的行为。LogDNA、ContainIQ 和Apache Kafka等工具可用于此目的。然后可以在仪表板上分析和可视化生成的日志。
日志聚合是必要的,因为微服务通常部署在临时容器中,当服务重新启动时,这些容器会丢失日志。日志聚合还简化了日志分析,因为所有日志都在一个位置。如果您使用的是 Kubernetes,ContainIQ 的日志记录功能集可以轻松聚合和可视化Kubernetes 集群级别和应用程序日志。
健康检查 API
健康检查 API 是一个 API 端点,用于检查微服务的运行状态及其依赖项。它必须返回以下信息:
- 所有相关下游服务的状态。例如,在具有订单和运输服务的电子商务应用程序中,健康检查 API 在检查运输服务的运行状态时会检查订单服务的运行状态。这是因为运输服务依赖于来自订单服务的数据来运行。
- 服务的数据库连接状态及其平均响应时间。将此检查返回的结果与预期平均值进行比较,以确定相关服务是否完全可操作。
- 平均内存消耗。平均值用于说明可能由于内存泄漏而出现的峰值。Kubernetes 等编排工具使用来自健康检查 API 的信息来确定何时启动新的应用程序部署或提醒开发团队或问题。
微服务反模式
由于微服务是一种架构模式而不是框架,因此很容易将反模式引入您的应用程序。在本节中,您将了解应该避免的微服务反模式。
构建分布式单体
巨石通常通过复制运行它们的机器来扩展。通过这种方式,每台机器都运行单体应用程序,即使它在不同的数据中心或区域中复制。在这种方法中,单体应用仍然面临同样的部署瓶颈,因此是不可取的。
使用共享数据库
另一个微服务反模式是多个服务与单个数据库通信时。这种安排使代码更改变得困难,因为多个团队必须在进行模式更改之前就架构更改达成一致。如果一个团队在没有其他团队的情况下更改数据库架构,则下游应用程序将中断。避免这种反模式的最好方法是为每个服务使用一个数据库,并利用 API 进行跨服务通信。
随处使用模式
当您使用随处可见的模式构建微服务时,您会引入模式配置问题。对此的解决方案是使用语义版本控制。这允许团队逐步采用不同的服务,以便部署可以独立。
服务之间的尖峰负载
微服务架构要求服务通过某种协议进行通信以共享数据和消息。不幸的是,当太多服务互连时,它们会产生依赖关系。它还可能使微服务的数据库过载。为避免这种反模式,您应该使用 API 网关作为请求缓冲区,并使用消息代理对消息进行排队。
硬编码 IP 和端口
当您的微服务网格仍然很小时,硬编码 IP 和端口会很有帮助。但是,随着您的架构扩展,服务可能会随机分配到新的 IP 和端口,从而破坏具有硬编码 IP 和端口的应用程序之间的连接。对此的一种解决方案是引入服务发现工具,该工具将确保微服务仍然可以通信,即使 IP 和端口发生变化。
最后的想法
微服务架构是一种软件架构模式,其中大型应用程序的每个任务都被打包为一个独立的应用程序。如果做得正确并且使用得当,它可以极大地提高团队的敏捷性和应用程序的可扩展性。在本文中,您了解了架构的实现方式、支持它的组件以及组织如何从中受益。
构建微服务并非易事。您必须考虑您的容器编排和监控策略。有效监控 Kubernetes 指标、日志、事件和跟踪的一种方法是使用 ContainIQ。ContainIQ允许您查看和关联指标、日志、事件、延迟和跟踪,并通过预先构建的仪表板和易于设置的监视器为您的工程团队提供集群健康状况的清晰视图。