# NATS
這篇文檔著眼于nats,將nats消息系統集成到micro工具包中。它討論包括圍繞服務發現,微服務的同步和異步通信。
## 什么是NATS?
[NATS](http://nats.io/)是一個開源的原生云消息系統或更簡單的消息總線。NATS由[Apcera](https://www.apcera.com/)的創始人Derek Collison創建。它起源于VMWare,并開始成為一個基于ruby的系統。在Go中被重寫了很長時間,并且正在穩步獲得那些尋求高度可擴展性和高性能消息傳遞系統的人的采用。
如果您想了解有關NATS的更多信息,請訪問[nats.io](http://nats.io/)或加入[社區](http://nats.io/community/)。
## 為什么選擇NATS?
為什么不NATS?過去曾與許多消息總線合作過,很快就清楚NATS是分開的。多年來,消息傳遞被譽為企業的救星,導致系統試圖成為所有人的一切。這導致了很多虛假的承諾,顯著的性能膨脹和高成本技術,產生了比解決問題更多的問題。
相比之下,NATS采取非常專注的方式,解決性能和可用性問題,同時保持令人難以置信的精益。它提到“永遠在線并且可用”,并且使用“消防和忘記”消息模式。它的簡單性,重點和輕量級特性使其成為微服務生態系統的主要候選者。我們相信它很快將成為服務間消息傳遞的主要候選人。
NATS提供了什么:
- 高性能和可擴展性
- 高可用性
- 極其輕巧
- 最多一次交付
什么NATS不提供:
- 堅持
- 合約
- 增強交付模式
- 企業級排隊
這簡要介紹了選擇NATS的原因。那么它如何適應Micro?來!我們討論一下。
### Micro的NATS
[Micro](https://github.com/micro/micro)是一個微服務工具包,采用可插拔的體系結構,允許將底層的依賴關系以最小的更改進行替換。[Go-Micro](https://github.com/micro/go-micro)框架的每個接口都為微服務提供了構建塊;用于服務發現的[注冊表](https://godoc.org/github.com/micro/go-micro/registry#Registry),用于同步通信的[傳輸](https://godoc.org/github.com/micro/go-micro/transport#Transport),用于異步[消息總線](https://godoc.org/github.com/micro/go-micro/broker#Broker)的代理等等。
為每個組件創建插件并實現接口一樣簡單。我們將花更多時間詳細說明,如何在未來的博客文章中撰寫插件。如果您想查看NATS或任何其他系統的插件,例如etcd discovery,kafka broker,rabbitmq transport,您可以在這里找到它們[github.com/micro/go-plugins](https://github.com/micro/go-plugins)。
基于NATS的Micro本質上是一組go-micro插件,可用于與NATS消息總線系統集成。通過為go-micro的各種接口提供插件,我們創建了許多可以選擇的架構模式集成。
根據我們的經驗,一種尺寸不適合所有情況,而Micro NATS的靈活性允許您定義適合您和您的團隊模型。
下面我們將討論傳輸,代理和注冊中心的NATS插件的實現。
### 傳輸

傳輸是同步通信的Micro接口。它使用相當普通的Socket語義,與`Listen`,`Dial`和`Accept`類似。這些概念和模式對于使用tcp,http等的同步通信很好理解,但適應消息總線可能有些困難。與消息總線建立連接,而不是與服務本身建立連接。為了解決這個問題,我們使用與topics和channels的偽連接的概念。
這是它的工作原理。
服務使用`transport.Listen`來偵聽消息。這將創建一個到NATS的連接。當`transport.Accept`被調用時,一個獨特的topic被創建和訂閱。這個獨特的topic將被用作go-micro注冊表中的服務地址。接收到的每條消息將被用作偽套接字/連接的基礎。如果現有連接具有相同的回復地址,我們只需將該消息放入該連接的緩存中。
想要與此服務通信的客戶端將使用`transport.Dial`創建與服務的連接。 這將連接到NATS,創建它自己獨特的topic并訂閱它。該topic用于服務的響應。每當客戶端向服務發送消息時,它都會將回復地址設置為該topic。
當任何一方想要關閉連接時,他們只需調用`transport.Close`即可終止與NATS的連接。

**使用傳輸插件**
導入傳輸插件
```
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-micro傳輸接口
```
type Transport interface {
Dial(addr string, opts ...DialOption) (Client, error)
Listen(addr string, opts ...ListenOption) (Listener, error)
String() string
}
```
[Transport](https://github.com/micro/go-plugins/tree/master/transport/nats)
### Broker

代理是異步消息的轉發micro接口。它提供了適用于大多數郵件代理的高級通用實現。就其本質而言,NATS是一個異步消息傳輸系統,它被用作消息代理。只有一個警告,NATS不持久化消息。雖然這對一些人來說可能并不理想,但我們仍然認為NATS可以也應該作為一個代理來使用go-micro。在不需要持久性的情況下,它允許高度可擴展的pub/sub子體系結構。
NATS提供了一個非常直接的發布和訂閱機制,包括topic,channel等概念。在這里沒有真正的花哨工作來使它工作。消息可以以異步火災和遺忘的方式發布。使用相同channel名稱的訂閱者在NATS中形成一個隊列組,然后它將允許消息自動均勻分布在訂閱者中。

**使用代理插件**
導入代理插件
```
import _ "github.com/micro/go-plugins/broker/nats"
```
從代理標志開始
```
go run main.go --broker=nats --broker_address=127.0.0.1:4222
```
或者直接使用代理
```
broker := nats.NewBroker()
```
go-micro 代理接口:
```
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
}
```
[Broker](https://github.com/micro/go-plugins/tree/master/broker/nats)
### 注冊表

注冊表是服務發現的Go-Micro界面。你可能會想。使用消息總線進行服務發現?這能工作嗎?事實上它確實并且相當好。許多使用消息總線進行傳輸的人,會避免使用任何單獨的發現機制。這是因為消息總線本身可以處理通過topic和channel的路由。定義為服務名稱的topic可以用作路由key,在訂閱該topic的服務的實例之間自動進行負載平衡。
Go-micro將服務發現和傳輸機制視為兩個不同的問題。無論何時,客戶端向另一個服務器發出請求(在封面下方),它會按名稱在注冊表中查找服務,選擇節點的地址,然后通過傳輸器與其進行通信。
通常存儲服務發現信息的最常用方式是通過
一個分布式的鍵值存儲,如zookeeper,etcd或類似的東西。正如你可能已經意識到的那樣,NATS不是一個分布式的鍵值存儲,所以我們要做一些有點不同的事情......
**廣播查詢!**
廣播查詢與您想象的一樣。 服務監聽我們認為用于廣播查詢的特定主題。 任何想要獲得服務發現信息的人都會首先創建一個它所訂閱的回復主題,然后用他們的回復地址在廣播主題上進行查詢。
因為我們實際上并不知道有多少服務實例正在運行,或者有多少響應將被返回,所以我們設定了一個我們愿意等待響應的時間的上限。 這是發現分散聚集的粗糙機制,但由于NAT的可擴展和高性能特性,它實際上運行得非常好。 它也間接提供了一個非常簡單的過濾服務的方法,并且響應時間更長。 將來,我們將著眼于改進底層實現。
總結它的工作原理:
1. 創建回復topic并訂閱
2. 用廣播地址發送廣播topic的查詢
3. 聽取回復并在時間限制后取消訂閱
4. 合并響應和返回結果

**使用注冊表插件**
導入注冊表插件
```
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注冊表接口:
```
type Registry interface {
Register(*Service, ...RegisterOption) error
Deregister(*Service) error
GetService(string) ([]*Service, error)
ListServices() ([]*Service, error)
Watch() (Watcher, error)
String() string
}
```
[Registry](https://github.com/micro/go-plugins/tree/master/registry/nats)
### 在NATS上伸縮Micro服務
在上面的例子中,我們只在本地主機上指定了一個NATS服務器,但我們推薦的實際使用方法是,設置一個NATS群集以獲得高可用性和容錯性。要了解有關NAT群集的更多信息,請查看[此處](http://nats.io/documentation/server/gnatsd-cluster/)的NATS文檔。
Micro接受逗號分隔的地址列表作為上面提到的標志或可選地使用環境變量。如果您直接使用客戶端庫,它還允許一組可變主機作為注冊表,傳輸和代理的初始化選項。
對于云原生應用的世界架構而言,我們過去的經驗表明,每個AZ或每個地區的群集都是理想的。大多數云提供商在AZ之間具有相對較低(3-5ms)的延遲,這允許區域集群沒有問題。在運行高可用性配置時,確保您的系統能夠容忍AZ故障并且在更成熟的配置下,可以承受整個區域故障很重要。我們不建議跨地區集群。理想情況下,應該使用更高級別的工具來管理多群集和多區域系統。
Micro是一個令人難以置信的靈活的,運行時不感知的微服務系統。它可以在任何地方和配置下運行。它的世界是由服務注冊機制引導。服務集群可以完全基于您提供訪問權限的服務注冊中心,AZ或區域池中進行本地化和命名空間。結合NATS集群,您可以構建高度可用的體系結構以滿足您的需求。

### 概要
[NATS](http://nats.io/)是一個可擴展的高性能消息中間件系統,我們認為它非常適合微服務生態系統。它與Micro配合具有非常好競爭力,我們已經證明它可以用作[注冊表](https://godoc.org/github.com/micro/go-plugins/registry/nats),[傳輸](https://godoc.org/github.com/micro/go-plugins/transport/nats)或[代理](https://godoc.org/github.com/micro/go-plugins/broker/nats)的插件。我們已經實施了所有三項,以突出NATS的靈活性。
Micro on NATS,是Micro強大的可插拔架構的一個典型例子。每個go-micro軟件包都可以通過最小的更改來實現和替換。將來查看更多關于[X]的Micro示例。接下來最有可能是Kubernetes上的Micro。
希望這會激勵你嘗試使用NAT上的Micro,甚至為其他系統編寫一些插件并回饋給社區。
在[github.com/micro/go-plugins](https://github.com/micro/go-plugins)找到NATS插件的來源。