这是一系列介绍Micro框架的文章的第四篇,我将会把作者的博客翻译成中文,推广Micro这个微服务框架。
这篇文章我们会讨论基于NATS使用Micro。讨论包括了服务发现,同步通信和异步通信。如果需要了解Micro,请翻看以前的文章。
NATS是什么?
NATS是一个开源的消息系统,或者说消息队列。NATS的作者是Derek Collison, Apcera的作者。它起源于VMWare,最开始是一个ruby的系统。后来使用golang进行重写,逐步的成为了一个高扩展性的高性能消息系统。
为什么是NATS?
为什么不是呢?过去我使用过很多消息队列,很明显NATS是鹤立鸡群的,在过去消息系统似乎成了企业的灵丹妙药了,结果是每个人参与的每个系统都离不开消息系统。导致了很多无效的承诺、高昂的研发投入,制造出比它解决的更多的麻烦。
NATS,相比之下,就十分专注,在难以置信的简洁之下,解决了性能问题,解决了高可用行问题。它的口号是『always on and available』,使用了一种『fire and forget』的消息模式。它简单、专注、轻量的特性使它在微服务的候选中脱颖而出。我们相信,在服务间的消息传递领域,它很快会变成主要的候选者。
NATS能提供什么?
高性能、高扩展
高可用
极致的轻量级
一次部署
NATS不支持什么?
- 持久化
- 事务
- Enhanced delivery modes
- Enterprise queueing
NATS是否适合Micro呢?我们接着讨论
Micro on NATS
Micro 采用插件化的架构设计,用户可以替换底层的实现,而不更改任何底层的代码。每个Go-Micro框架的底层模块定义了相应的接口, registry 是作为服务发现,transport作为同步通信, broker作为异步通信。
为每个组件创建一个插件很简单,只需要实现这些组件的接口即可。我们会在未来的文章里详细讨论,怎样写插件,如果你想详细了解NATS的插件或者其他的类似etcd作为服务发现,kafka作异步通信,rabbitmq作同步通信,在这里可以看到: github.com/micro/go-plugins
Micro on NATS本质上是实现一系列的插件,将NATS消息系统整合到Micro的框架中来。通过为Go Micro提供不同的插件,我们可以创造出很多灵活的组合。
在实践过程中,不能一套系统打天下,Micro on NATS的可以灵活的定义各种模型。
下面我们会讨论一下NATS插件怎样在transport,broker和registry下工作。
Transport
transport 是 go-micro定义的同步通信接口,它使用了泛型的语法描述,类似其他golang代码,比如Liesten,Dial,Accept
。这些理念和模式在类似TCP和HTTP这样的同步通信中很容易理解,但是在消息系统中要怎样兼容呢?通信过程中,连接是与消息队列建立的,而不是服务本身。为了达到目的,我们使用消息系统中的topics和channels来创造虚连接。
它是怎样工作起来的?
一个服务使用transport.Listen
来监听消息,这会与NATS之间建立连接。当transport.Accept
被调用时,一个唯一的topic会被创建并订阅。这个唯一的topic地址会作为服务的地址,注册到go-micro的注册器中。每个收到的消息会被虚连接处理,如果一个连接已经存在,而且回复的地址是一样的,我们会简单的把消息积压在连接上。
客户端通过transport.Dial
来连接服务端,其实它是建立了与NATS的连接,然后创建了唯一的topic并且订阅这个topic。这个topic用于接收服务端的返回。任何时候客户端发送消息到服务端时,它都会把回复地址设置成这个topic。(译注:服务端的地址是固定的,而客户端的每个请求,都会生成一个客户端地址,唯一的请求与唯一的地址实现一一关联)
当任何一边想要关闭连接时,简单的调用transport.Close
就会断开与NATS的连接。
使用transport插件
引用插件
1 | import _ "github.com/micro/go-plugins/transport/nats" |
启动时传入参数
1 | go run main.go --transport=nats --transport_address=127.0.0.1:4222 |
或者直接在代码中创建
1 | transport := nats.NewTransport() |
go-micro的transport接口:
1 | type Transport interface { |
Broker
broke是go-micro的异步通信接口,它定义了泛型的、高等级的通用接口。NATS本身作为消息系统,是可以作为消息broker的。这里只有一个警告:nats并不持久化消息。虽然在某些场景有风险,但我们相信NATS可以也应该用于go-micro的broker。持久化并不是必须的,它提供了高扩展的发布和订阅架构。
NATS通过Topics和Channels的理念,非常直接的实现了发布和订阅机制。这里并没有其他工作需要做。消息可以被发布到任何异步的fire and forget manner。通过NATS的Queue Group,订阅方可以通过channel的名字就行订阅。实现消息自动的分发的多个订阅者。
使用broker插件
引入包
1 | import _ "github.com/micro/go-plugins/broker/nats" |
(译注:注意此时引用的是broker中的nats包,上面引用的是transport中的nats包)
通过参数启动
1 | go run main.go --broker=nats --broker_address=127.0.0.1:4222 |
也可以直接启动
1 | broker := nats.NewBroker() |
go-micro的broker需要实现的接口:
1 | type Broker interface { |
Register
注册器是go-micro定义的服务发现接口,你也许想过。用消息系统做服务发现?这能工作吗?事实上它不仅能工作,还工作的很好。许多人在服务发现中使用消息系统,避免了不一致的发现机制。这是因为消息队列通过topics和channels实现了路由,Topics定义为服务的名字可以作为路由的key,订阅topics的服务自动实现了负载均衡。
Go-micro把服务发现和传输机制看做两个不同的领域,任何时候,客户端向服务发起请求,都会首先在注册器中根据服务的名字查询到正在运行的服务节点,然后客户端通过transport与节点进行通信。
一般来说,最常见的存储服务发现信息的方式是通过分布式key-value store,比如zookeeper、etcd等等。正如你了解到的,NATS闭市一个分布式的KV store,我们将做一下改动。。。
广播查询!
广播查询正如你想象的那样,服务都会监听一个特点的topic,任何需要服务发现信息的都需要订阅这个topic,然后对这个topic做一个反馈。
因为我们并不知道有多少服务正在运行,我们对响应时间设置一个上限。这是一个粗糙的服务发现机制,但因为NATS本身的高扩展性和高性能,它运行的反而非常好。它也间接的提高了过滤服务节点的响应时间。未来我们会试着提高底层的实现。
我们总结一下它是怎么工作的:
- 创建一个reply topic并订阅
- 向广播topic发起查询,附带上reply topic
- 监听回复,超过限制时间就注销订阅
- 聚合响应并返回结果
使用register插件
引入包
1 | import _ "github.com/micro/go-plugins/registry/nats" |
通过参数启动
1 | go run main.go --registry=nats --registry_address=127.0.0.1:4222 |
或者直接在代码中设置
1 | registry := nats.NewRegistry() |
go-micro中的register接口
1 | type Registry interface { |
大规模在Micro中使用NATS
在上面的例子中,我们只是用了单个的NATS服务,但是在实际情况下,我们一般都是使用NATS集群来实现高可用和容错。你可以在这里看看更多NATS集群的知识。
Micro 在启动时可以接收一系列的参数,如环境变量等。如果直接使用client的库,也可以在创建时指定参数。
在目前云计算的架构下,我们过去的经验是,每个AZ都应该有集群。大部分的云计算公司,不同的AZ之间的延迟大概是3到5毫秒,集群的通信是没有任何问题的。当我们运行一个高可用的配置,你的系统必须要能在AZ宕机、甚至整个region崩溃时还能提供服务。我们不建议跨region部署集群。理想的高等级工具应该是用于管理多集群和多region系统。
Micro是一个极其灵活的微服务系统,它本身就被设计成运行在任何配置的任何地方。整个Micro世界是通过服务发现进行指导,服务的集群可以运行在机器集群中,AZ或者regions。再考虑到NATS集群,它可以让你构建高可用的服务。
总结
NATS是一个高可用和高性能的消息系统,在我们的微服务生态系统中运行的很好。它与Micro配合的非常的好,我们可以把它用在register,transport,broker中,我们也已经全部实现了这些插件。
NATS在Micro中的使用只是一个示例,它展示了Micro高度的插件化架构,每个go-micro的包都可以被替换,底层不需要改动代码,上层也只需要改动非常少的代码。在未来我们还会看到更多的Micro on X,下一个可能是Micro on kubernetes。
希望这可以鼓励你来使用Micro on NATS,或者编写自己的插件并回馈给社区。
在这里看更多的NATS插件github.com/micro/go-plugins