继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Go Micro(4)——基于消息队列NATS构建微服务

慕哥9229398
关注TA
已关注
手记 1241
粉丝 199
获赞 913

Go Micro(4)——基于消息队列NATS构建微服务

这篇文章我们会讨论基于 NATS 使用 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 作为异步通信。

type Transport interface {
    Dial(addr string, opts ...DialOption) (Client, error)
    Listen(addr string, opts ...ListenOption) (Listener, error)
    String() string
}

type Registry interface {
    Register(*Service, ...RegisterOption) error
    Deregister(*Service) error
    GetService(string) ([]*Service, error)
    ListServices() ([]*Service, error)
    Watch() (Watcher, error)
    String() string
}

type Broker interface {
    Options() Options
    Address() string
    Connect() error
    Disconnect() error
    Init(...Option) error
    Publish(string, *Message, ...PublishOption) error
    Subscribe(string, Handler, ...SubscribeOption) (Subscriber, error)
    String() string
}

为每个组件创建一个插件很简单,只需要实现这些组件的接口即可。我们会在未来的文章里详细讨论,怎样写插件,如果你想详细了解 NATS 的插件或者其他的类似 etcd 作为服务发现,kafka 作异步通信,rabbitmq 作同步通信,在这里可以看到: github.com/micro/go-plugins

Micro on NATS 本质上是实现一系列的插件,将 NATS 消息系统整合到 Micro 的框架中来。通过为 Go Micro 提供不同的插件,我们可以创造出很多灵活的组合。

在实践过程中,不能一套系统打天下,Micro on NATS 的可以灵活的定义各种模型。

下面我们会讨论一下 NATS 插件怎样在 transportbrokerregistry 下工作。

Transport

[图片上传失败...(image-a3bc83-1513577247790)]

transportgo-micro 定义的同步通信接口,它使用了泛型的语法描述,类似其他 golang 代码,比如 Liesten,Dial,Accept。这些理念和模式在类似 TCPHTTP 这样的同步通信中很容易理解,但是在消息系统中要怎样兼容呢?通信过程中,连接是与消息队列建立的,而不是服务本身。为了达到目的,我们使用消息系统中的 topicschannels 来创造虚连接。

它是怎样工作起来的?

一个服务使用 transport.Listen 来监听消息,这会与 NATS 之间建立连接。当 transport.Accept 被调用时,一个唯一的 topic 会被创建并订阅。这个唯一的 topic 地址会作为服务的地址,注册到 go-micro 的注册器中。每个收到的消息会被虚连接处理,如果一个连接已经存在,而且回复的地址是一样的,我们会简单的把消息积压在连接上。

客户端通过 transport.Dial 来连接服务端,其实它是建立了与 NATS 的连接,然后创建了唯一的 topic 并且订阅这个 topic。这个 topic 用于接收服务端的返回。任何时候客户端发送消息到服务端时,它都会把回复地址设置成这个 topic。(译注:服务端的地址是固定的,而客户端的每个请求,都会生成一个客户端地址,唯一的请求与唯一的地址实现一一关联)

当任何一边想要关闭连接时,简单的调用 transport.Close 就会断开与 NATS 的连接。

[图片上传失败...(image-a17b4e-1513577247790)]

使用 transport 插件

引用插件

import _ "github.com/micro/go-plugins/transport/nats"

启动时传入参数

go run main.go --transport=nats --transport_address=127.0.0.1:4222

或者直接在代码中创建

transport := nats.NewTransport()

go-microtransport 接口:

type Transport interface {
    Dial(addr string, opts ...DialOption) (Client, error)
    Listen(addr string, opts ...ListenOption) (Listener, error)
    String() string}

Broker

[图片上传失败...(image-14ecc9-1513577247790)]

brokego-micro 的异步通信接口,它定义了泛型的、高等级的通用接口。NATS 本身作为消息系统,是可以作为消息 broker 的。这里只有一个警告:nats 并不持久化消息。虽然在某些场景有风险,但我们相信 NATS 可以也应该用于 go-microbroker。持久化并不是必须的,它提供了高扩展的发布和订阅架构。

NATS 通过 TopicsChannels 的理念,非常直接的实现了发布和订阅机制。这里并没有其他工作需要做。消息可以被发布到任何异步的 fire and forget manner。通过 NATSQueue Group,订阅方可以通过 channel 的名字就行订阅。实现消息自动的分发的多个订阅者。

[图片上传失败...(image-be955d-1513577247790)]

使用 broker 插件

引入包

import _ "github.com/micro/go-plugins/broker/nats"

(译注:注意此时引用的是 broker 中的 nats 包,上面引用的是 transport 中的 nats 包)

通过参数启动

go run main.go --broker=nats --broker_address=127.0.0.1:4222

也可以直接启动

broker := nats.NewBroker()

go-microbroker 需要实现的接口:

type Broker interface {
    Options() Options    Address() string    Connect() error    Disconnect() error    Init(...Option) error    Publish(string, *Message, ...PublishOption) error    Subscribe(string, Handler, ...SubscribeOption) (Subscriber, error)
    String() string
}

Register

[图片上传失败...(image-f5229e-1513577247790)]

Registergo-micro 定义的服务发现接口,你也许想过。用消息系统做服务发现?这能工作吗?事实上它不仅能工作,还工作的很好。许多人在服务发现中使用消息系统,避免了不一致的发现机制。这是因为消息队列通过 topicschannels 实现了路由,Topics 定义为服务的名字可以作为路由的 key,订阅 topics 的服务自动实现了负载均衡。

Go-micro 把服务发现和传输机制看做两个不同的领域,任何时候,客户端向服务发起请求,都会首先在注册器中根据服务的名字查询到正在运行的服务节点,然后客户端通过 transport 与节点进行通信。

一般来说,最常见的存储服务发现信息的方式是通过分布式 key-value store,比如 zookeeper、etcd 等等。正如你了解到的,NATS 不是一个分布式的 KV store,我们将做一下改动。。。

广播查询!

广播查询正如你想象的那样,服务都会监听一个特点的 topic,任何需要服务发现信息的都需要订阅这个 topic,然后对这个 topic 做一个反馈。

因为我们并不知道有多少服务正在运行,我们对响应时间设置一个上限。这是一个粗糙的服务发现机制,但因为 NATS 本身的高扩展性和高性能,它运行的反而非常好。它也间接的提高了过滤服务节点的响应时间。未来我们会试着提高底层的实现。

我们总结一下它是怎么工作的:

  • 创建一个 reply topic 并订阅

  • 向广播 topic 发起查询,附带上 reply topic

  • 监听回复,超过限制时间就注销订阅

  • 聚合响应并返回结果

[图片上传失败...(image-9adecd-1513577247790)]

使用 register 插件

引入包

import _ "github.com/micro/go-plugins/registry/nats"

通过参数启动

go run main.go --registry=nats --registry_address=127.0.0.1:4222

或者直接在代码中设置

registry := nats.NewRegistry()

go-micro 中的 register 接口

type Registry interface {
    Register(*Service, ...RegisterOption) error    Deregister(*Service) error    GetService(string) ([]*Service, error)
    ListServices() ([]*Service, error)
    Watch() (Watcher, error)
    String() string
}

大规模在 Micro 中使用 NATS

在上面的例子中,我们只是用了单个的 NATS 服务,但是在实际情况下,我们一般都是使用 NATS 集群来实现高可用和容错。你可以在这里看看更多 NATS 集群的知识。

Micro 在启动时可以接收一系列的参数,如环境变量等。如果直接使用 client 的库,也可以在创建时指定参数。

在目前云计算的架构下,我们过去的经验是,每个 AZ 都应该有集群。大部分的云计算公司,不同的 AZ 之间的延迟大概是3到5毫秒,集群的通信是没有任何问题的。当我们运行一个高可用的配置,你的系统必须要能在 AZ 宕机、甚至整个 region 崩溃时还能提供服务。我们不建议跨 region 部署集群。理想的高等级工具应该是用于管理多集群和多 region 系统。

Micro 是一个极其灵活的微服务系统,它本身就被设计成运行在任何配置的任何地方。整个 Micro 世界是通过服务发现进行指导,服务的集群可以运行在机器集群中,AZ 或者 regions。再考虑到 NATS 集群,它可以让你构建高可用的服务。

[图片上传失败...(image-92f6b7-1513577247790)]

总结

NATS 是一个高可用和高性能的消息系统,在我们的微服务生态系统中运行的很好。它与 Micro 配合的非常的好,我们可以把它用在 register,transport,broker 中,我们也已经全部实现了这些插件。

NATSMicro 中的使用只是一个示例,它展示了 Micro 高度的插件化架构,每个 go-micro 的包都可以被替换,底层不需要改动代码,上层也只需要改动非常少的代码。在未来我们还会看到更多的 Micro on X,下一个可能是 Micro on kubernetes

希望这可以鼓励你来使用 Micro on NATS,或者编写自己的插件并回馈给社区。

在这里看更多的NATS插件 github.com/micro/go-plugins



作者:流年1004
链接:https://www.jianshu.com/p/a65922fbd2c0


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP