0%

M3O - 微服务的设计模式

M3O - 微服务的架构设计

原文 Micro architecture & design patterns for microservices
本文添加部分译者的理解,如有不当之处,欢迎指正。

关于 Micro

Micro 是一个微服务工具组件。 它的功能和接口值得一看,同时提供了强大的可插拔体系结构。

Micro 专注于满足构建微服务的基本要求,并希望通过采取谨慎的设计方法来做到这一点。

关于Micro 工具组件的介绍,可以参考之前文章阅读。

以上是快速回顾,现在让我们更深入。

RPC,REST,Proto …

  • 首先想到的是服务间通信为什么使用的是 RPC? 为什么不使用 REST?
  • 为什么要使用 protobuf 编码?

Google 是 protobuf 的创建者,内部使用 RPC,以及其开源的 gRPC(RPC框架)。很多的大公司都是 RPC/Protobuf 坚定拥护者,例如 Uber、FB等。

站在巨人的肩膀上,我们并不孤单。

就个人而言,我们认为,未来的 API 会使用 RPC 构建,因为它们定义良好的结构化格式,易于与有效的编码协议(例如 protobuf )结合使用,并提供强大定义的 API 和高效的通信功能。

HTTP 到 RPC / API …

从现实的角度来讲,要是实现 RPC On Web,我们还有很长的路要走。 虽然它在数据中心内部是完美的,但是让它服务于公众流量(例如: web网站/ 移动服务),那就是另外一回事了。这是 micro 包含 API 网关来服务和转换 HTTP 请求的原因之一。

API 网关是用于微服务架构的模式。 它充当外界的单一入口点,并根据请求路由到适当的服务。 这允许 HTTP API 本身由不同的微服务组成, 这是一种强大的架构模式。对 API 的一部分进行更改可能会破坏整个依赖链上服务的日子已经一去不复返了。

Micro API 使用服务路径解析,因此每个唯一的请求路径可以由不同的 micro api服务提供服务, 例如:

  • /user => user api
  • /order => order api

* 举例 *

  • URL: /customer/orders
  • Method: Customer.Orders
  • Service: go.micro.api.customer

这是一个例子,对 /customer/orders 的请求将通过方法 Customer.Orders 发送到API服务 go.micro.api.customer

那么 Micro API 到底是什么?

  • 服务类型
  • 命名空间
  • 同步与异步

服务类型

让每个程序就做好一件事。如果有新任务,就重新开始,不要往原程序中加入新功能而搞得复杂。
- Doug McIlroy (Unix管道的发明人、Unix传统的奠基人之一)

微服务的概念全都涉及服务按照职能的分离,并且从 Unix 哲学中汲取了很多东西: 一个程序只做一件事,并做好。还有部分原因是我们认为在职责不同的服务之间需要逻辑上和架构上的分离。

现在,我将承认这些概念并不是什么新鲜事物,但是鉴于它们已经在非常成功的大型技术公司中得到证明,因此它们令人信服。 我们的目标是传播这些开发理念,并通过工具指导设计决策。

因此,这是我们当前定义的服务类型。

  • API - 由 micro api 提供的 API 服务位于您的基础架构的接入层,最有可能服务于外部请求。 您可以使用 HTTP 处理程序来构建它,并以反向代理模式运行 micro api,或者默认情况下处理特定的 RPC API 请求响应格式。

  • WEB - 由 micro web 提供的 Web 服务专注于提供 html 内容和仪表板。 micro web 反向代理 HTTP 和 WebSockets。 这些是目前唯一受支持的协议,但将来可能会扩展。

  • SRV - 这些是基于 RPC 的后端服务。 他们主要致力于为您的系统提供核心功能,并且很可能不是面向公众的。 如果愿意,您仍然可以使用 /rpc 端点通过 micro api 或 Web访问它们,但更有可能的是 API,Web 和其他 SRV 服务使用 go-micro 客户端直接调用它们。

根据过去的经验,我们发现这种架构模式非常强大,并且可以扩展到数百种服务。 通过将这种服务类型构建到整个架构体系中,我们认为它为微服务开发奠定了良好的基础。

命名空间

因此,您可能想知道,是什么协调了 micro api 与 web 服务的对话或 micro web 与 api 服务的对话。 我们使用逻辑命名空间将其分开。 通过在服务名称之前添加名称空间,我们可以清楚地标识其用途和在系统中的位置。 这是一个简单但有效的模式,对我们很有帮助。

micro apimicro web 将组成名称空间的服务名称和请求路径的第一个路径,例如,对 /api/customer 的请求将变为 go.micro.api.customer

默认名称空间是:

API - go.micro.api
WEB - go.micro.web
SRV - go.micro.srv

您应该将这些设置为您的域,例如 com.example.{api,web,srv} 。 可以在运行时配置 micro apimicro web,以路由到您的名称空间。

同步与异步

您经常会在与响应模式相同的句子中听到微服务。 对于许多人来说,微服务是关于创建事件驱动的体系结构和设计主要通过异步通信进行交互的服务。

Micro 将建议优先使用异步通信,这是微服务的基本构建模块。通过异步消息传递通信事件,任何人都可以使用它们并对其采取行动。 可以构建新的独立服务,而无需对系统的其他方面进行任何修改。 这是一种强大的设计模式,因此,我们在 go-micro 中包含了 Broker 接口。

在 Micro 中,同步和异步通信作为单独的要求解决。 传输接口用于在服务之间创建点对点连接。 go-micro 客户端和服务器在传输基础上构建,以执行请求-响应RPC并提供双向流功能。

在构建系统时,应同时使用两种通信方式,但了解何时以及何处适当才是关键。 在很多情况下,没有对与错,而是会进行一定的权衡。

以下是异步通信在一个审计跟踪系统中的使用,该系统用于跟踪客户事件历史记录。

在此示例中,当发生某些操作(例如客户登录,更新其个人资料或下订单)时,每个API或服务都会发布一个事件。 审核服务将订阅这些事件,并将它们存储在某种时间序列数据库中。 然后,管理员或其他任何人都可以查看任何用户在系统内发生的事件的历史记录。

如果将其作为同步呼叫完成,那么在流量很大或并发请求数量较高时,我们很容易使审计服务不堪重负。 如果由于某种原因使审计服务不可用或呼叫失败,我们将基本上失去此历史记录。 通过将这些事件发布给代理,我们可以异步保留它们。 这是事件驱动架构和微服务中的常见模式。

G3O 是如何定义微服务的?

我们的信念和建立的思想是,微服务是专注于单一类型的实体或域的应用程序,它通过强定义的API提供对它的访问。

让我们使用诸如社交网络之类的真实示例。

随着 Ruby on Rails 的兴起而流行的一种定义明确的软件体系结构模式是 MVC(模型-视图-控制器)。

MVC 世界中,每个实体或域都将代表一个模型,该模型又将数据库抽象化。 该模型可以与其他模型具有关系,例如一对多或多对多。 控制器处理即将到来的请求,从模型中检索数据并将其传递给视图以呈现给用户。

现在相同的示例,以微服务架构为例。 这些模型中的每一个都是服务,并通过API传递其数据。 用户请求,数据收集和呈现由许多不同的Web服务处理。

每个服务都有一个重点。 当我们想要添加新功能或实体时,我们可以简单地更改与该功能相关的一项服务或编写一项新服务。 功能点的分离为弹性软件开发提供了一种模式。

版本控制

版本控制是开发实际软件的重要部分。 在微服务领域,鉴于API和业务逻辑分散在许多不同的服务中,这一点至关重要。 因此,将服务版本控制作为核心工具的一部分,允许对更新和流量整形进行更精细的控制非常重要。

go-micro 中,通过名称和版本定义服务。 注册表将服务作为列表返回,按节点注册时的版本划分节点。

这是我们基于版本的路由的构建模块。

1
2
3
4
5
6
7
type Service struct { 
Name string
Version string
Metadata map[string]string
Endpoints []*Endpoint
Nodes []*Node
}

结合使用 go-micro 中的客户端负载均衡器 Selector ,可以确保将请求相应地分配到各个版本中。

选择器是一个强大的接口,我们正在构建该接口以提供不同类型的路由算法。 默认是随机算法,并且支持轮询、以及基于标签、基于延迟的方式。

通过使用默认的随机哈希负载平衡算法并逐渐添加新服务版本的实例,您可以执行蓝绿色部署并进行灰度测试。

将来,我们将寻求实现一个全局服务负载平衡器,该平衡器将与选择器绑定在一起,从而可以根据正在运行的系统中的历史趋势进行路由决策。 它还将能够在运行时调整发送到服务的每个版本的流量的百分比,并为服务动态添加元数据或标签,从而可以基于标签做出路由决策。

扩展能力

上面有关版本控制的评论开始暗示扩展服务的基本模式。 尽管注册表用作存储有关服务信息的机制,但我们使用选择器将路由和负载平衡的考虑分开。

同样,服务按照职能的拆分和让每个程序就做好一件事的概念。 扩展基础结构以及代码的重点在于简单性,严格定义的 API 和分层体系结构。 通过创建这些构建块,我们允许我们自己构建更多可伸缩的软件并解决其他地方的更高层次的问题。

这是 Micro 编写方式以及我们希望如何指导微服务世界中的软件开发的基础。

在生产环境中部署服务时,您将寻求构建可伸缩,容错和高性能的产品。 现在,云计算使我们可以访问几乎无限的规模,但是没有什么可以避免失败。 实际上,故障是我们在构建分布式系统时要解决的关键方面之一,并且在构建基础结构时应考虑到这一点。

在云世界中,我们希望容忍可用区(数据中心)故障,甚至整个区域(多DC)中断。 在过去的几天中,我们经常谈论冷热备用系统或灾难恢复计划。 如今,最先进的技术公司以全球化的方式开展业务,每个应用程序的多个副本在全球多个数据中心中运行。

我们需要向 Google,Facebook,Netflix和 Twitter 等公司学习。 我们必须构建能够容忍AZ故障而又不对用户造成任何影响的系统,并且在大多数情况下,我们必须在几分钟或更短的时间内处理区域故障。

Micro 使您能够构建这种架构。 通过提供可插拔接口,我们可以利用最合适的分布式系统来满足 micro 工具箱的每个需求。

服务发现和注册表是 Micro 的基础。 它可用于隔离和发现AZ或区域或您选择的任何配置中的一组服务。 然后,可以使用Micro API在该拓扑中路由和平衡许多服务及其实例。

总结

希望这篇博文可以使您更清楚地了解 Micro 的体系结构,以及它如何为微服务实现可扩展的设计模式。

  • 微服务首先是软件设计模式。 我们可以通过工具启用某些基础模式,同时为其他模式的出现或使用提供灵活性。
  • 由于 Micro 是可插拔的体系结构,因此它是各种设计模式的强大支持者,可以在许多情况下适当使用。

    例如,如果您正在构建视频流基础结构,则可以选择 HTTP 传输进行点对点通信。 如果您对延迟不敏感,则可以选择传输插件,例如 NATS 或 RabbitMQ。