Go Micro(4)——基于消息隊列NATS構建微服務

Go Micro(4)——基于消息隊列NATS構建微服務

這篇文章我們會討論基于 NATS 使用 Micro。討論包括了服務發(fā)現(xiàn),同步通信和異步通信。


NATS是什么?

NATS 是一個開源的消息系統(tǒng),或者說消息隊列。NATS 的作者是 Derek Collison, Apcera 的作者。它起源于 VMWare,最開始是一個 ruby 的系統(tǒng)。后來使用 golang 進行重寫,逐步的成為了一個高擴展性的高性能消息系統(tǒng)。


為什么是NATS?

為什么不是呢?過去我使用過很多消息隊列,很明顯 NATS 是鶴立雞群的,在過去消息系統(tǒng)似乎成了企業(yè)的靈丹妙藥了,結果是每個人參與的每個系統(tǒng)都離不開消息系統(tǒng)。導致了很多無效的承諾、高昂的研發(fā)投入,制造出比它解決的更多的麻煩。

NATS,相比之下,就十分專注,在難以置信的簡潔之下,解決了性能問題,解決了高可用行問題。它的口號是『always on and available』,使用了一種『fire and forget』的消息模式。它簡單、專注、輕量的特性使它在微服務的候選中脫穎而出。我們相信,在服務間的消息傳遞領域,它很快會變成主要的候選者。

NATS能提供什么?

  • 高性能、高擴展
  • 高可用
  • 極致的輕量級
  • 一次部署

NATS不支持什么?

  • 持久化
  • 事務
  • Enhanced delivery modes
  • Enterprise queueing

NATS 是否適合 Micro 呢?我們接著討論


Micro on NATS

Micro 采用插件化的架構設計,用戶可以替換底層的實現(xiàn),而不更改任何底層的代碼。每個 Go-Micro 框架的底層模塊定義了相應的接口,registry 是作為服務發(fā)現(xiàn),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
}

為每個組件創(chuàng)建一個插件很簡單,只需要實現(xiàn)這些組件的接口即可。我們會在未來的文章里詳細討論,怎樣寫插件,如果你想詳細了解 NATS 的插件或者其他的類似 etcd 作為服務發(fā)現(xiàn),kafka 作異步通信,rabbitmq 作同步通信,在這里可以看到: github.com/micro/go-plugins

Micro on NATS 本質上是實現(xiàn)一系列的插件,將 NATS 消息系統(tǒng)整合到 Micro 的框架中來。通過為 Go Micro 提供不同的插件,我們可以創(chuàng)造出很多靈活的組合。

在實踐過程中,不能一套系統(tǒng)打天下,Micro on NATS 的可以靈活的定義各種模型。

下面我們會討論一下 NATS 插件怎樣在 transport 、 brokerregistry 下工作。

Transport

[圖片上傳失敗...(image-a3bc83-1513577247790)]

transportgo-micro 定義的同步通信接口,它使用了泛型的語法描述,類似其他 golang 代碼,比如 Liesten,Dial,Accept。這些理念和模式在類似 TCPHTTP 這樣的同步通信中很容易理解,但是在消息系統(tǒng)中要怎樣兼容呢?通信過程中,連接是與消息隊列建立的,而不是服務本身。為了達到目的,我們使用消息系統(tǒng)中的 topicschannels 來創(chuàng)造虛連接。

它是怎樣工作起來的?

一個服務使用 transport.Listen 來監(jiān)聽消息,這會與 NATS 之間建立連接。當 transport.Accept 被調用時,一個唯一的 topic 會被創(chuàng)建并訂閱。這個唯一的 topic 地址會作為服務的地址,注冊到 go-micro 的注冊器中。每個收到的消息會被虛連接處理,如果一個連接已經(jīng)存在,而且回復的地址是一樣的,我們會簡單的把消息積壓在連接上。

客戶端通過 transport.Dial 來連接服務端,其實它是建立了與 NATS 的連接,然后創(chuàng)建了唯一的 topic 并且訂閱這個 topic。這個 topic 用于接收服務端的返回。任何時候客戶端發(fā)送消息到服務端時,它都會把回復地址設置成這個 topic。(譯注:服務端的地址是固定的,而客戶端的每個請求,都會生成一個客戶端地址,唯一的請求與唯一的地址實現(xiàn)一一關聯(lián))

當任何一邊想要關閉連接時,簡單的調用 transport.Close 就會斷開與 NATS 的連接。

[圖片上傳失敗...(image-a17b4e-1513577247790)]

使用 transport 插件

引用插件

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

啟動時傳入?yún)?shù)

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

或者直接在代碼中創(chuàng)建

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 本身作為消息系統(tǒng),是可以作為消息 broker 的。這里只有一個警告:nats 并不持久化消息。雖然在某些場景有風險,但我們相信 NATS 可以也應該用于 go-microbroker。持久化并不是必須的,它提供了高擴展的發(fā)布和訂閱架構。

NATS 通過 TopicsChannels 的理念,非常直接的實現(xiàn)了發(fā)布和訂閱機制。這里并沒有其他工作需要做。消息可以被發(fā)布到任何異步的 fire and forget manner。通過 NATSQueue Group,訂閱方可以通過 channel 的名字就行訂閱。實現(xiàn)消息自動的分發(fā)的多個訂閱者。

[圖片上傳失敗...(image-be955d-1513577247790)]

使用 broker 插件

引入包

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

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

通過參數(shù)啟動

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

也可以直接啟動

broker := nats.NewBroker()

go-microbroker 需要實現(xiàn)的接口:

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 定義的服務發(fā)現(xiàn)接口,你也許想過。用消息系統(tǒng)做服務發(fā)現(xiàn)?這能工作嗎?事實上它不僅能工作,還工作的很好。許多人在服務發(fā)現(xiàn)中使用消息系統(tǒng),避免了不一致的發(fā)現(xiàn)機制。這是因為消息隊列通過 topicschannels 實現(xiàn)了路由,Topics 定義為服務的名字可以作為路由的 key,訂閱 topics 的服務自動實現(xiàn)了負載均衡。

Go-micro 把服務發(fā)現(xiàn)和傳輸機制看做兩個不同的領域,任何時候,客戶端向服務發(fā)起請求,都會首先在注冊器中根據(jù)服務的名字查詢到正在運行的服務節(jié)點,然后客戶端通過 transport 與節(jié)點進行通信。

一般來說,最常見的存儲服務發(fā)現(xiàn)信息的方式是通過分布式 key-value store,比如 zookeeper、etcd 等等。正如你了解到的,NATS 不是一個分布式的 KV store,我們將做一下改動。。。

廣播查詢!

廣播查詢正如你想象的那樣,服務都會監(jiān)聽一個特點的 topic,任何需要服務發(fā)現(xiàn)信息的都需要訂閱這個 topic,然后對這個 topic 做一個反饋。

因為我們并不知道有多少服務正在運行,我們對響應時間設置一個上限。這是一個粗糙的服務發(fā)現(xiàn)機制,但因為 NATS 本身的高擴展性和高性能,它運行的反而非常好。它也間接的提高了過濾服務節(jié)點的響應時間。未來我們會試著提高底層的實現(xiàn)。

我們總結一下它是怎么工作的:

  • 創(chuàng)建一個 reply topic 并訂閱
  • 向廣播 topic 發(fā)起查詢,附帶上 reply topic
  • 監(jiān)聽回復,超過限制時間就注銷訂閱
  • 聚合響應并返回結果

[圖片上傳失敗...(image-9adecd-1513577247790)]

使用 register 插件

引入包

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

通過參數(shù)啟動

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
}

大規(guī)模在 Micro 中使用 NATS

在上面的例子中,我們只是用了單個的 NATS 服務,但是在實際情況下,我們一般都是使用 NATS 集群來實現(xiàn)高可用和容錯。你可以在這里看看更多 NATS 集群的知識。

Micro 在啟動時可以接收一系列的參數(shù),如環(huán)境變量等。如果直接使用 client 的庫,也可以在創(chuàng)建時指定參數(shù)。

在目前云計算的架構下,我們過去的經(jīng)驗是,每個 AZ 都應該有集群。大部分的云計算公司,不同的 AZ 之間的延遲大概是3到5毫秒,集群的通信是沒有任何問題的。當我們運行一個高可用的配置,你的系統(tǒng)必須要能在 AZ 宕機、甚至整個 region 崩潰時還能提供服務。我們不建議跨 region 部署集群。理想的高等級工具應該是用于管理多集群和多 region 系統(tǒng)。

Micro 是一個極其靈活的微服務系統(tǒng),它本身就被設計成運行在任何配置的任何地方。整個 Micro 世界是通過服務發(fā)現(xiàn)進行指導,服務的集群可以運行在機器集群中,AZ 或者 regions。再考慮到 NATS 集群,它可以讓你構建高可用的服務。

[圖片上傳失敗...(image-92f6b7-1513577247790)]

總結

NATS 是一個高可用和高性能的消息系統(tǒng),在我們的微服務生態(tài)系統(tǒng)中運行的很好。它與 Micro 配合的非常的好,我們可以把它用在 register,transport,broker 中,我們也已經(jīng)全部實現(xiàn)了這些插件。

NATSMicro 中的使用只是一個示例,它展示了 Micro 高度的插件化架構,每個 go-micro 的包都可以被替換,底層不需要改動代碼,上層也只需要改動非常少的代碼。在未來我們還會看到更多的 Micro on X,下一個可能是 Micro on kubernetes。

希望這可以鼓勵你來使用 Micro on NATS,或者編寫自己的插件并回饋給社區(qū)。

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

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 姓名:周小蓬 16019110037 轉載自:http://blog.csdn.net/YChenFeng/art...
    aeytifiw閱讀 34,915評論 13 425
  • 微服務工具箱 現(xiàn)在你也許聽到了這個新現(xiàn)象:微服務。如果你對此不熟悉也有興趣學習,歡迎參考上一篇文章。 這篇文章我們...
    浮x塵閱讀 6,391評論 0 13
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,694評論 19 139
  • 背景介紹 Kafka簡介 Kafka是一種分布式的,基于發(fā)布/訂閱的消息系統(tǒng)。主要設計目標如下: 以時間復雜度為O...
    高廣超閱讀 13,062評論 8 167
  • Kafka入門經(jīng)典教程-Kafka-about云開發(fā) http://www.aboutyun.com/threa...
    葡萄喃喃囈語閱讀 10,987評論 4 54

友情鏈接更多精彩內容