# Go Micro
Go Micro是一個插件式的RPC框架。它用于分布式系統開發。

## 特性
Go Micro抽象出分布式系統的細節。以下是主要功能。
- 服務發現 - 通過服務發現自動注冊和名稱解析
- 負載平衡 - 基于發現構建的服務的智能客戶端負載平衡
- 同步通信 - 基于RPC的通信,支持雙向流
- 異步通信 - 為事件驅動架構內置的Pub/Sub接口
- 消息編碼 - 基于帶有protobuf和json的內容類型的動態編碼
- 服務接口 - 所有功能都打包在一個簡單的高級界面中,用于開發微服務
Go Micro支持服務和功能編程模型。請繼續閱讀以了解更多信息。
## 插件
Go-micro使用Go界面進行抽象。由于這個原因,底層實現可以被換出。
我們提供了開箱即用的默認設置。
- Consul或mDNS服務發現
- 隨機散列客戶端負載平衡
- JSON-RPC 1.0和PROTO-RPC消息編碼
- HTTP通信機制
## 示例
在[示例/函數](https://github.com/micro/examples/tree/master/function)以及[示例/服務](https://github.com/micro/examples/tree/master/service)可以找到示例服務。
[示例](https://github.com/micro/examples)目錄包含使用諸如中間件/封裝器,選擇器過濾器,pub/sub,grpc,插件等的示例。對于完整的greeter示例,請查看[示例/greeter](https://github.com/micro/examples/tree/master/greeter)程序。其他示例可以在整個GitHub存儲庫中找到。
觀看[Golang UK Conf 2016](https://www.youtube.com/watch?v=xspaDovwk34)視頻以獲取高級概述。
## 軟件包
Go micro由多個軟件包組成。
- 傳輸同步消息
- 代理異步消息
- 用于消息編碼的編解碼器
- 服務發現注冊表
- 選擇器進行負載平衡
- 客戶端提出請求
- 服務器來處理請求
更多細節如下
### 注冊機制
注冊機制提供了一個服務發現機制來將名稱解析為地址。它可以由consul,etcd,zookeeper,dns,gossip等提供支持。服務應該在啟動時使用注冊機制進行注冊,并在關閉時取消注冊。服務可以選擇提供一個到期的TTL并在一段時間內重新注冊以確保活躍,并且如果服務死亡,服務將被清除。
### 選擇器
選擇器是建立在注冊表上的負載平衡抽象。它允許使用過濾器功能對“服務”進行“過濾”,并使用諸如random,roundrobin,leastconn等算法選擇“選擇”服務。客戶端在請求時利用選擇器。客戶端將使用選擇器而不是注冊表,因為它提供了內置的負載平衡機制。
### 傳輸
傳輸是用于服務之間的同步請求/響應通信的接口。它類似于golang網絡包,但提供更高層次的抽象,允許我們切換通信機制,例如http,rabbitmq,websockets,NATS。該傳輸也支持雙向流式傳輸。這對客戶端推送到服務器提供強大的能力。
### 代理
代理為消息代理提供異步發布/訂閱通信的接口。這是事件驅動架構和微服務的基本要求之一。默認情況下,我們使用收件箱樣式指向HTTP系統,來最小化基本所需的依賴的數量。但是,在go-plugins中有許多消息代理實現可用,例如RabbitMQ,NATS,NSQ,Google Cloud Pub Sub。
### 編解碼器
編解碼器用于編碼和解碼消息,然后再通過線路傳輸消息。這可能是json,protobuf,bson,msgpack等。這與其他大多數編解碼器不同之處在于我們實際上也支持RPC格式。所以我們有JSON-RPC,PROTO-RPC,BSON-RPC等。它將客戶端/服務器的編碼分離出來,并提供了一個強大的方法來集成其他系統,如gRPC,Vanadium等。
### 服務器
服務器是編寫服務的構建模塊。在這里,您可以命名您的服務,注冊請求處理程序,添加middeware等。該服務構建在上述軟件包上,為服務請求提供統一接口。內置一個RPC系統的服務器。將來可能會有其他的實現。該服務器還允許您定義多個編解碼器以提供不同的編碼消息。
### 客戶端
客戶端提供一個接口來向服務發出請求。就像服務器一樣,它建立在其他軟件包上,以提供一個統一的界面,用于使用注冊機制,根據名稱查找服務,使用選擇器進行負載平衡,使用代理進行傳輸和異步消息傳輸的同步請求。
上述組件被組合在微服務的頂層。
## 內部實現
以下是關于核心部件的內部工作的原理。
### service.Run()
Go-micro服務通過調用service.Run()來啟動,
1. 在啟動功能之前執行
```
for _, fn := range s.opts.BeforeStart {
if err := fn(); err != nil {
return err
}
}
```
2. 啟動服務
```
if err := s.opts.Server.Start(); err != nil {
return err
}
```
3. 注冊和服務發現
```
if err := s.opts.Server.Register(); err != nil {
return err
}
```
4. 在啟動功能后執行
```
for _, fn := range s.opts.AfterStart {
if err := fn(); err != nil {
return err
}
}
```
### server.Start()
server.Start由service.Run調用
1. 調用transport.Listen監聽連接
```
ts, err := config.Transport.Listen(config.Address)
if err != nil {
return err
}
```
2. 調用transport.Accept開始接收鏈路
```
go ts.Accept(s.accept)
```
3. 調用broker.Connect開始處理鏈路消息
```
config.Broker.Connect()
```
4. 等待退出信號,關閉運輸并斷開代理
```
go func() {
// wait for exit
ch := <-s.exit
// wait for requests to finish
if wait(s.opts.Context) {
s.wg.Wait()
}
// close transport listener
ch <- ts.Close()
// disconnect the broker
config.Broker.Disconnect()
}()
```
## 編寫服務
查看入門[文檔](https://micro.mu/docs/writing-a-go-service.html)