将单体应用程序架构为微服务的最佳实践

介绍

Serverless 架构允许在必要的基础上实现后端 Web 服务,而不是需要维护自己的服务器配置,为无服务器提供商构建软件可以最大限度地减少相关的负担。

无服务器部署通常涉及 _microservices。使用微服务是对软件架构的一种方法,该方法将应用程序构成一系列服务,这些服务是松散的,可以独立部署,可以独立维护和测试。微服务架构预先于无服务器部署的广泛使用,但它们是自然相匹配的。

本教程将审查一些改造单一应用程序以使用微服务的最佳实践。

微服务的概述

重构,或 refactoring,一个单一的应用程序,通常是无形的设计. 如果你计划在没有引入新功能的同时显著重写你的应用程序逻辑,你的目标应该是尽可能避免服务中断。这可能意味着使用某种形式的 蓝绿色部署。 实施微服务时,它通常也意味着逐步更换你的应用程序的功能。 这需要你彻底执行单元测试,以确保你的应用程序优雅地处理任何意想不到的边缘情况。

几乎所有主要编程语言都同样支持微服务,采用微服务驱动的架构可以促进在同一项目内组合多个不同的语言或框架,这允许您为您的堆栈的每个组件采用最佳的解决方案,但也可以改变您对代码维护的看法。

框架与国家管理

某些架构比其他更适合微服务。如果您的应用程序逻辑包含多种依赖于彼此的序列步骤,那么将每个步骤抽象化为单个微服务可能不是一个好主意。在这种情况下,您需要一个复杂的控制器架构,可以处理和路由任何中间阶段的错误。这可以通过使用一个微服务架构,例如 Gearman来分发子进程,但在使用无服务器部署时更不方便,并且可以增加复杂性而不必解决问题。

相反,你可以在应用程序状态的变化之间划分微服务,或者每次某些输出被返回给用户时划分微服务。这样,你不需要在单个流程中在公共 API 调用之间传输相同的数据。处理应用程序状态可能具有挑战性,因为每个微服务只会访问其自己的输入,而不是全球定义的范围。

考虑创建和维护您自己的应用程序库,用于核心逻辑和可能在多个地方使用的功能,然后创建微服务,这些微服务结合了这种逻辑的独特组合。

从 Git 部署

在与微服务合作时,你应该尽可能地使用 GitOps的原则。 将 Git 存储库视为部署目的的单一真理来源。 大多数特定语言的包管理器,如 Python 的 pip 和 Node.js 的 npm 都提供语法来部署您自己的 Git 存储库中的软件包。 除了从 PyPInpmjs.com 或其他上游存储库安装的默认功能外,还可以使用此功能。

火灾终点

您的每个微服务都可以实现自己的API,并且根据您的应用程序的复杂性,您可以部署另一个API层(等等),并计划只向您的用户暴露最高级别的API。尽管维持多个不同的API路径可以增加复杂性,但这种复杂性可以通过对每个微服务的API终端的良好文档来解决。

采用微服务可以自然地推动您也采用更多的软件作为服务(SaaS)工具作为应用程序堆栈的不同部分的落入替代品。这在原则上几乎总是好的。

向微服务迁移

有效地迁移到微服务需要你合成一些软件开发和部署的最佳实践。

使用 CI/CD 原则

当重新设计应用程序以使用微服务时,您应该遵循 持续集成和连续交付的最佳实践以逐步取代您单一架构的功能。例如,您可以使用抽象分支 - 在现有实现中构建抽象层,以便在抽象后面并行构建新的实现 - 以便在用户无任何干扰的情况下重构生产代码。您还可以使用装饰器,一种语言功能为 TypeScriptPython,将更多的代码路径添加到现有函数中。

便携性

微服务在像Docker这样的集装箱化框架同时变得流行,有很好的理由,它们有类似的目标和架构假设:

  • 容器提供流程和依赖隔离,以便在个别基础上部署
  • 容器允许其他与它们并行运行的应用程序作为黑匣子发挥作用 - 它们不需要共享状态或任何信息,除了输入和输出
  • 容器注册表,如 Docker Hub,允许您与第三方依赖程序互换发布和使用自己的依赖。

在理论上,你的微服务应该与在无服务器部署中一样适合运行在Docker容器或Kubernetes集群中。在实践中,可能有相当大的优势。在无服务器环境中,高CPU密集型微服务(如视频处理)可能不是经济的,而维护Kubernetes控制平板和配置细节需要大量的承诺。然而,考虑到可移动性,建设始终是一个值得的投资。取决于你的架构的复杂性,你可能只能通过创建相关的.yml元数据声明和Dockerfile来支持多个环境。为Kubernetes和无服务器环境进行原型设计可以提高你的架构的整体弹性。

一般来说,您不应该担心数据库兼并或其他存储扩展问题在微服务本身. 任何相关的优化都应该由您的数据库、数据库抽象层或数据库作为服务(DBaaS)提供商直接解决和实施,以便您的微服务可以执行任何创建更新删除(CRUD)操作,而无需进行装饰。

版本

例如,您可能提供/my/service/v2除了现有/my/service/v1之外,并计划逐步削减/v1端点。

微服务迁移的例子

将微服务部署到应用程序中可以通过将其推广到自己的独立服务来取代嵌入式函数调用或私人方法,举一个Flask应用程序的例子,该应用程序基于用户在网页表单中输入的 Google 查询,然后操作结果,然后将其返回给用户:

 1[label sample_flask_app.py]
 2from flask import *
 3from flask import render_template
 4from flask import Markup
 5from googleapiclient.discovery import build
 6from config import *
 7
 8app = Flask(__name__)
 9
10def google_query(query, api_key, cse_id, **kwargs):
11    query_service = build("customsearch", "v1", developerKey=api_key)
12    query_results = query_service.cse().list(q=query, cx=cse_id, **kwargs).execute()
13    return query_results['items']
14
15def manipulate_result(input, cli=False):
16    search_results = google_query(input, keys["api_key"], keys["cse_id"])
17    for result in search_results:
18        abc(result)
1920    return manipulated_text
21
22@app.route('/<string:text>', methods= ["GET"])
23def get_url(text):
24    manipulated_text = manipulate_result(text)
25    return render_template('index.html', prefill=text, value=Markup(manipulated_text))
26
27if __name__ == "__main__":
28    serve(app, host='0.0.0.0', port=5000)

该应用程序提供自己的网页终端,其中包括HTTPGET方法. 向该终端提供一个文本字符串,呼吁一个名为manipulate_result()的函数,该函数首先将文本发送到另一个函数google_query(),然后从查询结果中操作文本,然后将其返回给用户。

这个应用程序可以重构成两个单独的微服务,两者都将HTTPGET参数作为输入参数。第一种会根据一些输入返回谷歌查询结果,使用googleapiclientPython库:

1[label microservice_1.py]
2from googleapiclient.discovery import build
3from config import *
4
5def main(input_text):
6    query_service = build("customsearch", "v1", developerKey=api_key)
7    query_results = query_service.cse().list(q=query, cx=cse_id, **kwargs).execute()
8    return query_results['items']

然后,第二个微服务将操纵并提取相关数据,从这些搜索结果中返回给用户:

 1[label microservice_2.py]
 2import requests
 3
 4def main(search_string, standalone=True):
 5    if standalone == False:
 6        search_results = requests.get('https://path/to/microservice_1/v1/'+search_string).text
 7    else:
 8        search_results = search_string
 9    for result in search_results:
10        abc(result)
1112    return manipulated_text

在本示例中,microservice_2.py 执行所有输入处理,并通过 HTTP 邮件直接调用microservice_1.py,如果提供了额外的参数,standalone=False。

这是一个简单的例子,原始 Flask 代码似乎没有显著的维护负担,但仍然有能够从堆栈中删除 Flask 的优点. 如果您不再需要运行自己的 Web 请求处理器,则可以将这些结果返回静态网站,使用 Jamstack 环境,而不是需要维护 Flask 后端。

结论

在本教程中,您审查了一些转移单一应用程序到微服务的最佳实践,并按照一个简短的例子将Flask应用程序分解为两个单独的微服务终端。

接下来,您可能想了解更多关于 有效监控微服务架构以更好地了解无服务器部署的优化。

Published At
Categories with 技术
comments powered by Disqus