微服务应用程序可以以多种方式运行,每种方式都有不同的权衡和成本结构。适用于跨越几个服务的小型应用程序可能不足以用于大型系统。
从简单到复杂,以下是运行微服务的五种方式:
- 单机多进程:购买或租用服务器并将微服务作为进程运行。
- 多台机器,多进程:显而易见的下一步是添加更多服务器并分配负载,提供更高的可扩展性和可用性。
- 容器:将微服务封装在容器中,可以更轻松地与其他服务一起部署和运行。这也是迈向 Kubernetes 的第一步。
- 编排器:Kubernetes 或 Nomad 等编排器是完整的平台,旨在同时运行数千个容器。
- 无服务器:无服务器允许我们忘记进程、容器和服务器,并直接在云中运行代码。
方案一:单机多进程
在最基本的层面上,我们可以在一台机器上将微服务应用程序作为多个进程运行。每个服务侦听不同的端口并通过环回接口进行通信。
微服务部署的最基本形式使用单机。应用程序是一组加上负载平衡的进程。
这种简单的方法有一些明显的好处:
- 轻量级:没有开销,因为它只是在服务器上运行的进程。
- 方便:这是体验微服务的好方法,无需其他工具的学习曲线。
- 轻松排除故障:一切都在同一个地方,因此如果您有持续交付,那么在出现问题时发现问题或恢复到工作配置非常简单。
- 固定计费:我们知道我们每个月必须支付多少。
DIY 方法最适合只有少量微服务的小型应用程序。除此之外,它还不够,因为:
- 没有可扩展性:一旦你最大化了服务器的资源,就是这样。
- 单点故障:如果服务器宕机,应用程序也会随之宕机。
- 脆弱的部署:我们需要自定义部署和监控脚本来确保服务安装和运行正确。
- 无资源限制:任何微服务进程都可以消耗任意数量的 CPU 或内存,从而可能使其他服务处于饥饿状态并使应用程序处于降级状态。
- 此选项的持续集成(CI) 将遵循相同的模式:在 CI管道中[url=
https://semaphoreci.com/blog/build-stage]构建[/url]和测试工件,然后使用持续部署进行部署。
这是学习微服务基础知识的最佳选择。您可以运行一个小型微服务应用程序来熟悉。单台服务器将带您走很远,直到您需要扩展,此时您可以升级到下一个选项。
方案2:多台机器和流程
该选项本质上是选项1的升级。当应用程序超出服务器的容量时,我们可以纵向扩展(升级服务器)或横向扩展(添加更多服务器)。在微服务的情况下,水平扩展到两台或多台机器更有意义,因为我们获得了更高的可用性作为奖励。而且,一旦我们有了分布式设置,我们总是可以通过升级服务器来扩大规模。
负载均衡器仍然是单点故障。为了避免这种情况,多个平衡器可以并行运行。
然而,水平缩放并非没有问题。超越一台机器会带来一些关键点,这些关键点会使故障排除变得更加复杂,并且会出现使用微服务架构带来的典型问题。
- 我们如何关联分布在许多服务器之间的日志文件?
- 我们如何收集合理的指标?
- 我们如何处理升级和停机?
- 我们如何处理流量的高峰和下降?
这些都是分布式计算固有的问题,一旦涉及多台机器,您就会遇到(并且必须处理)问题。
如果您有几台备用机器并希望提高应用程序的可用性,则此选项非常有用。只要您保持简单,使用或多或少统一的服务(相同的语言,类似的框架),您就可以了。一旦您通过了某个复杂度阈值,您将需要容器来提供更大的灵活性。
方案 3:使用容器部署微服务
虽然直接将微服务作为进程运行非常有效,但它是有代价的。
- 必须使用必要的依赖项和工具精心维护服务器。
- 一个失控的进程会消耗所有的内存或 CPU。
- 部署和监控微服务是一个脆弱的过程。
所有这些缺点都可以通过容器来缓解。容器是包含程序运行所需的一切的包。容器镜像是一个独立的单元,可以在任何服务器上运行,而无需先安装任何依赖项或工具(容器运行时本身除外)。
容器提供了足够的虚拟化来单独运行软件。有了它们,我们可以获得以下好处:
- 隔离:包含的进程彼此和操作系统隔离。每个容器都有一个私有文件系统,因此不可能发生依赖冲突(只要您不滥用卷)。
- 并发性:我们可以运行同一个容器镜像的多个实例而不会发生冲突。
- 更少的开销:由于不需要启动整个操作系统,容器比虚拟机轻得多。
- 免安装部署:安装容器只是下载和运行镜像的问题。无需安装步骤。
- 资源控制:我们可以对容器设置 CPU 和内存限制,这样它们就不会破坏服务器的稳定性。
上图容器化工作负载需要 CI/CD 上的镜像构建阶段。
1、服务器上的容器
这种方法用容器代替了流程,因为它们给了我们更大的灵活性和控制力。与选项 2 一样,我们可以在任意数量的机器上分配负载。
将微服务进程包装在容器中使它们更加便携和灵活。
2、无服务器容器
到目前为止描述的所有选项都是基于服务器的。但是软件公司不从事管理服务器的业务——必须配置、修补和升级的服务器——他们从事解决代码问题的业务。因此,许多公司宁愿尽可能避免使用服务器也就不足为奇了。
AWS Fargate和Heroku等容器即服务产品使运行容器化应用程序成为可能,而无需处理服务器。我们只需要构建容器镜像并将其指向云提供商,它会处理剩下的事情:配置虚拟机,下载、启动和监控镜像。这些托管服务通常包括一个内置的负载均衡器,这是一件少担心的事情。
使用 Fargate 的弹性容器服务 (ECS) 让我们无需租用服务器即可运行容器。它们由云提供商维护。
以下是托管容器服务的一些好处:
- 无服务器:无需维护或修补服务器。
- 轻松部署:只需构建一个容器镜像并告诉服务使用它。
- 自动缩放:云提供商可以在需求激增时提供更多容量,或者在没有流量时停止所有容器。
但是,在开始之前,您必须意识到一些重大缺点:
- 供应商锁定:这是一个大问题。摆脱托管服务总是充满挑战,因为云供应商提供并控制了大部分基础设施。
- 资源有限:托管服务强加了无法避免的 CPU 和内存限制。
- 更少的控制:我们没有与其他选项相同的控制水平。如果您需要托管服务未提供的功能,那您就不走运了。
方案 4:编排器
编排器是专门在一组服务器上分配容器工作负载的平台。最著名的编排器是Kubernetes,这是一个由 Google 创建的开源项目,由Cloud Native Computing Foundation维护。
除了容器管理之外,Orchestrator 还提供广泛的网络功能,例如路由、安全性、负载平衡和集中式日志——运行微服务应用程序可能需要的一切。
Kubernetes 使用 pod 作为调度单元。Pod 是一组共享一个网络地址的一个或多个容器。
使用 Kubernetes,我们摆脱了自定义部署脚本。相反,我们使用清单来编码所需的状态,并让集群负责其余的工作。
持续部署管道将清单发送到集群,集群会采取必要的步骤来完成它。
Kubernetes 得到所有云提供商的支持,是事实上的微服务部署平台。因此,您可能认为这是运行微服务的绝对最佳方式。对于许多公司来说,这是事实,但也需要牢记以下几点:
- 复杂性:编排器以其陡峭的学习曲线而闻名。如果不小心的话,射中自己的脚并不少见。对于简单的应用程序,编排器是多余的。
- 管理负担:维护 Kubernetes 安装需要大量专业知识。幸运的是,每个体面的云供应商都提供了托管集群,可以省去所有的管理工作。
- 技能组合:Kubernetes 开发需要专门的技能组合。了解所有活动部件并了解如何排除部署失败的故障可能需要数周时间。在团队熟悉这些工具之前,过渡到 Kubernetes 可能会很慢并且会降低生产力。
方案 5:将微服务部署为无服务器函数
无服务器函数偏离了我们迄今为止讨论的所有其他内容。我们使用云来简单地按需运行代码,而不是服务器、进程或容器。AWS Lambda和Google Cloud Functions等无服务器产品可处理可扩展和高可用性服务所需的所有基础设施细节,让我们可以专注于编码。
无服务器函数可自动扩展并按使用计费。
这是一个完全不同的范式,具有不同的优点和缺点。从好的方面来说,我们得到:
- 易用性:我们可以在不编译或构建容器映像的情况下即时部署功能,这对于尝试和原型设计非常有用。
- 易于扩展:您(基本上)获得了无限的可扩展性。云将提供足够的资源来满足需求。
- 按使用付费:您根据使用情况付费。如果没有需求,则不收费。
- 然而,缺点可能是相当大的,使得无服务器不适合某些类型的微服务:
- 供应商锁定:与托管容器一样,您正在购买供应商的生态系统。从供应商那里迁移可能要求很高。
- 冷启动:不常用的功能可能需要很长时间才能启动。发生这种情况是因为云提供商降低了附加到未使用功能的资源。
- 资源有限:每个函数都有内存和时间限制——它们不能是长时间运行的进程。
- 有限的运行时:仅支持少数语言和框架。您可能会被迫使用您不习惯的语言。
看不见的账单:由于成本是基于使用情况的,因此很难预测月底发票的大小。使用高峰可能会导致令人讨厌的意外。
无服务器为可扩展性提供了一种无需干预的解决方案。与 Kubernetes 相比,它没有给你太多的控制权,但它更容易使用,因为你不需要专门的 serverless 技能。对于快速发展的小公司来说,无服务器是一个很好的选择,只要他们能够忍受它的缺点和限制。
结论
运行微服务应用程序的最佳方式是由许多因素决定的。使用容器(或进程)的单个服务器是试验或测试原型的绝佳起点。
如果应用程序成熟并且跨越许多服务,您将需要更健壮的东西,例如托管容器或无服务器,并且随着应用程序的增长,可能还会需要 Kubernetes。