有很多关于 micro
架构的疑问和微服务的设计模式的问题,今天我们讨论一下这两个话题。
关于Micro
Micro
是一个微服务工具箱,它有自己固有的设计模式,但插件化的架构可以让底层的实现很轻易的被替换。
micro
专注于定位微服务构建过程中的最基本的需求,并通过精密的设计来满足这些需求。
查看过往的文章可以了解微服务的理念和 Micro
的特性。
关于工具箱
Go Micro
是一个用 golang
编写的,插件化的 RPC
框架。它提供了基础的库,比如服务发现、客户端负载均衡、编解码、同步异步通信等。
Micro API
是一个 API
网关,用于将外部的 HTTP
请求路由到内部的 micro
服务上。它有单一的接入点,可以通过反向代理或者 http
转换成 RPC
来访问。
Micro Web
是一个 web
仪表盘,也是作为 micro web
应用的反向代理。我们相信 web
应用也应该是一个微服务,在微服务世界里也应该是第一等公民。它表现的很像 Micro API
但也有单独的特性比如 websocket
。
Micro Sidecar
使用 http
服务,提供了 go-micro
的所有特性。虽然我们喜欢 golang
来构建微服务,但你也许想使用其他语言。所以 Sidecar
提供了一种其他语言的应用接入 Micro
世界的方式。
Micro CLI
是一个简单直接的命令行接口,用于与你的服务交互。他也可以使用你的 Sidecar
作为代理来连接服务。
上面是很简单的介绍,下面我们更加深入一些。
RPC,REST,Proto…
第一件你想到的事情是,为什么是 RPC
,而不是 REST
? 在内部服务间的通信上,我们相信 RPC
是更合适的。或者更明确一点,RPC
使用 protobuf
做编码,通过 protobuf
定义 API
。这种方式把两个需求结合起来了:一个需求是需要明确定义的 API
接口,另一个需求是高性能的消息编解码。RPC
是非常直接的通信方式。
我们在这个选择上并不孤独。
Google
是 protobuf
的创造者,在内部通过 gRPC
这个框架,大量的使用 RPC
调用。Hailo
也从 RPC/protobuf
的组合中收益很多,不仅是系统性能,开发速度也提高很多。Uber
选择开发自己的RPC框架,名字叫 TChannel
。
个人而言我认为未来的 API
将会使用 RPC
进行构建,因为它们结构化的格式、高效的编解码提供了定义良好的 API
和高性能的通信。
HTTP to RPC,API…
事实上,我们在 web
上 RPC
还有很长的路要走。在内部 RPC
的表现是完美的,但在面对外部请求比如网站、手机 app
的接口等等,就是另外一回事了。我们需要面对这个,这就是为什么 Micro
需要一个 API
网关,用来接受并转换 http
请求。
API
网关在微服务架构中是一个常见的模式。它作为一个单一的接入点,外部世界的请求,通过它进行路由分发。它让 HTTP API
可以由背后的很多服务所组成。
micro
的 API
网关使用路径到服务的解决方案,因此不同的请求路径,对应了不同的服务。比如 /user => user api,/order => order api
。
这里有一个例子。一个请求的路径是 /comstomer/orders
,这个请求会被转发到 go.micro.api.customer
这个服务,会使用 Customer.Orders
这个方法进行处理。
你也许会问,API
服务到底是怎样的?我们下面来讨论一下不同类型的服务。
服务的类型
微服务的关键理念就是业务的拆解,这是从 unix
的设计哲学中得到的启示:『doing one thing and doing it well』,因为这个原因,我们认为不同的服务需要有逻辑上和架构上的区别,以实现自己不同的任务。
我们知道这些理念并没有什么太大的新意,但在一些非常大而且成功的公司,它们的实践取得了成功。我们的目标是传播这些开发理念,并通过工具来进行指导。
目前我们定义了下面的几种服务。
API
通过 micro api
运行,API
服务在你的架构中处于关键位置,大部分作用是接受外部世界的请求并分发到内部的服务上。你可以通过 micro api
提供的反向代理 REST
模式进行访问,也可以通过 RPC
接口进行访问。
WEB
通过 micro web
运行,web
服务专注于服务 html
请求,构建仪表盘。micro web
反向代理 http
和 websocket
,目前只有这两种协议支持,未来也许会增加。
SRV
这是后台的 RPC
服务,他们的目标是为你的系统提供核心的功能,大部分并不是公开的接口。你仍然可以通过 micro api
和 micro web
,使用 /rpc
接入点进行访问。这种接入方式直接使用 go-micro
的 client
进行调用。
按照过去的经验,我们发现这样的架构设计非常强大。可以被扩展到数以百计的服务。通过把它整合到 Micro
架构中,我们发现它为微服务的开发提供了非常好的基础。
Namespacing
你也许会想,怎样区分 micro api
或者 micro web
以及服务呢。我们通过命名空间进行拆分。通过命名的前缀,我们可以很清晰的看到,某个服务是哪种类型的。这很简单但很高效。
micro api
会把 /customer
这样的请求路径定位到 go.micro.api.customer
服务。
默认的命名空间是:
- API - go.micro.api
- WEB - go.micro.web
- SRV - go.micro.srv
你应该把它设置成你的域名,比如 com.example.api
。这些都可以进行配置。
同步和异步
你经常听说微服务是很灵活的模式。大多数来说,微服务是关于创造事件驱动的架构,以及设计通过异步通信的方式响应的服务。
Micro
把异步通信作为微服务构建中的第一等公民。事件通过异步消息,可以被任何人消费并作出反应,搭建一个新服务不需要对系统的其他部分作出任何更改。这是一种强大的设计模式,因为这个原因,我们在 go-micro
中定义了 Broker
接口。
异步和同步通信在Micro中是分离开的。Transport
接口用于构建服务之间的点对点的通信。go-micro
中的 client
和 server
基于 transport
来进行请求和返回RPC调用,提供了双向的通信流。
在构建系统时,两种通信方式都应该使用,但关键是理解在什么场景下应该用什么类型的通信方式。在大部分情况下并没有好坏之分,我们需要权衡处理。
一个 broker
和异步通信的典型使用方式是这样:监听系统通过 broker
对服务的事件历史进行记录。
在这个例子中,每个服务的每个 API
在被调用时,都会把事件上报到监听 topic
,监听系统会订阅这个 topic
,并把他们存储到时间序列的数据库中。在 admin
管理平台可以看到任何用户的操作历史。
如果我们通过同步通信做,监听系统直接面对巨大的请求数。如果监听系统宕机了,我们就丢失了这些数据。通过把这些事件发布到 broker
,我们可以异步的持久化这些数据。这是一种微服务中常见的事件驱动设计模型。
我们怎样定义微服务?
我们已经讨论了很多 Micro
能为微服务提供的工具箱,也定义了服务的类型。但还没有真正讨论,到底什么是微服务。
微服务与其他应用的区别到底在哪里,微服务为什么叫微服务。
现在有很多不同的定义,但有两条适合大部分微服务系统。
Loosely coupled service oriented architecture with a bounded context
An approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms
微服务的哲学与 unix
也类似
Do one thing and do it well
我们认为微服务是这样一种应用程序:专注于单一的业务,并通过明确定义的API对外提供服务。
看看我们在社交网络中怎样使用微服务:
其中一种是流行的 MVC
架构,在 MVC
世界中,每个实体代表了一个模型,模型又是作为数据库的抽象。模型之间也许有一对多或者多对多的关系。controller
模块负责处理请求,接受 model
模块返回的数据,并把数据传输到 view
层,进行渲染,最后输出给用户。
在微服务架构中,面对同样的例子。每个模型实际上是一个服务,通过 API
进行服务间通信。用户请求,数据的集合以及渲染是通过一系列不同的 web
服务进行处理的。每个服务有自身的专注点,当我们需要增加一个新特性时,我们只需要把关联的服务进行修改,或者直接写一个新的服务。分离的理念提供了大规模开发的模式。
版本
开发真实世界的软件时,版本是非常重要的。在微服务世界里,严格的把 API
和业务逻辑分离到许多不同的服务上,因为这个原因,服务的版本控制是核心的工具的很重要的一部分。可以让我们在流量很大时也能进行升级。
在 go-micro
中,服务定义了名字和版本,Registry
模块返回服务的列表,根据版本把节点进行了区分。这里是 service
的接口定义。
type Service struct {
Name string
Version string
Metadata map[string]string
Endpoints []*Endpoint
Nodes []*Node
}
版本控制需要与 Selector 结合起来,selector
是客户端的负载均衡机制,通过 selector
的策略实现请求根据版本进行分发。
selector
是非常强大的接口,我们根据不同的路由算法,比如随机、轮询、根据标签、响应时间等等。
通过使用默认的随机负载算法,再加上版本控制算法,我们就可以进行灰度发布。
在未来,我们会尝试实现一个全局的负载策略,根据历史的趋势进行选择,可以根据版本,设置不同的百分比,并动态的为服务增加标签。
大规模扩展
上面的介绍的版本系统,是大规模扩展服务时的基本模式。register
存储了服务的注册信息,我们通过 selector
实现了路由和负载均衡。
按照 doing one thing well 的理念,扩展架构也应该是简单、明确定义的 API
、分层次的架构。通过创造这些工具,我们可以构建更加可靠的系统,专注于更高级别的业务需求。
这是 Micro
编写的基础理念,也是我们希望微服务开发者遵循的理念。
当我们在生产环境部署应用时,我们就需要构建可扩展、高容错、高性能的应用。云计算让我们可以进行不受限制的扩展,但是没有任何东西会一直正常运行。事实上,在构建分布式系统中,怎样对待运行失败的服务是非常重要的一方面,你在构建你的系统时,需要好好考虑。
在云计算的世界,我们想要在数据中运行错误,甚至多个数据中心运行错误的情况下,也能正常提供服务。在过去我们讨论的是冷热备份,或者是灾难恢复计划。在今天,最先进的技术公司,在全世界不停歇的运作,每个程序都会有多个备份,运行在世界上不同的数据中心。
我们需要向 google,facebook,netflix 和 Twitter 学习,即使在数据中心运行失败时,也要对用户提供服务,在多个数据中心运行失败时,也需要尽快恢复。
Micro
可以让你构建这样的应用,通过插件化的架构,我们可以为不同的分布式系统,实现不同的工具箱。
服务发现和注册器是 Micro
的关键模块,它们可以用于发现在数据中心中的一系列服务,Micro API
可以用于路由和负载一系列的服务。
[图片上传中...(image.png-ffb75d-1513663516734-0)]
总结
希望这篇文章清晰的讲解了Micro的架构,以及怎样实现可扩展的微服务设计模式。微服务首先是一种软件设计模式,我们可以通过工具实现基础、核心的功能,同时也能灵活组合其他设计模式。
因为 Micro
是一个插件化的架构,它强大的能力,可以实现不同的设计模式,在不同的场景中都能使用。比如你构建一个视频流的服务,你也许需要基于 http
的点对点服务。如果你对性能不敏感,你也许需要使用消息队列比如 NATS
或 RabbitMQ
。
使用Micro这样的工具进行开发是非常让人兴奋的。
作者:流年1004
链接:https://www.jianshu.com/p/1a5641befbc5
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。