Go的微服務庫kite
Kite
Kite是用Go開發的一套RPC庫,很適合作為分布式微服務的開發框架。
Kite 的傳輸層使用 SockJS 提供的WebSocket服務, 瀏覽器Javascript也可以連接到Kite上 (Kite.js);
Kite 的RPC消息格式使用修改過的 dnode 協議,Kite 增加了 session 和 authentication 層, 用於Kites 的發現和識別。
標識一個Kite的參數如下:
- Username: Kite的屬主;
- Environment: 當前環境,比如“production”, “testing”, “staging” 等;
- Name: 標識Kite類別的名稱,比如mykite, fs, terminal 等;
- Version: 版本號,比如1.0.0;
- Region: 當前區域, 比如 “Europe”, “Asia” 或其它地區;
- Hostname: Kite的Hostname;
- ID: 識別Kite的唯一ID,這個是由Kite庫生成的,但用戶也可以自己指定一個;
註意:以上參數的順序很重要;
Kite的使用
如下面的例子:
服務端:
package main import "github.com/koding/kite" func main() { k := kite.New("first", "1.0.0") k.Config.Port = 6000 k.Run() }
代碼說明:
- kite.New創建了一個名字為"first",版本號為"1.0.0"的Kite;
- k.Config 用於設置Kite的屬性,比如端口號;
- Run方法表示運行此服務,這是個阻塞式的調用,之後,Kite就可以接收請求了;
客戶端:
package main import ( "fmt" "github.com/koding/kite" ) func main() { k := kite.New("second", "1.0.0") client := k.NewClient("http://localhost:6000/kite") client.Dial() response, _ := client.Tell("kite.ping") fmt.Println(response.MustString()) }
代碼說明:
- NewClient方法指定需要連接的服務端的URL;
- Tell方法傳入調用的方法名,在服務端,這個方法名對應一個handler,這裏的kite.ping是一個默認的方法,當調用這個方法的時候,client端會受到一個字符串"pong";
下面再來看看怎麽調用一個自定義方法:
服務端:
package main import "github.com/koding/kite" func main() { k := kite.New("first", "1.0.0") k.Config.Port = 6000 k.Config.DisableAuthentication = true k.HandleFunc("square", func(r *kite.Request) (interface{}, error) { a := r.Args.One().MustFloat64() return a * a, nil })
k.Run() }
定義了一個squid方法,對應的handler接收一個數字,並返回這個數字的平方;
客戶端:
package main import ( "fmt" "github.com/koding/kite" ) func main() { k := kite.New("second", "1.0.0") client := k.NewClient("http://localhost:6000/kite") client.Dial() response, _ := client.Tell("square", 4) fmt.Println(response.MustFloat64()) }
服務註冊和發現Kontrol
Kite之間可以互相通信,通過Kontrol的服務發現機制,一個Kite可以發現其它的Kites。也就是說一個Kite可以在Kontrol註冊自己,從而讓其它的kites能找到它;
Kontrol本身也是一個Kite,它用於對服務進行註冊和鑒權;Kontrol 使用 etcd 作為後端存儲, 當然,也可以用其它數據庫替換,比如PostgreSQL。任何滿足 kontrol.Storage接口的都可以作為後端存儲。
服務端:
package main import ( "net/url" "github.com/koding/kite" ) func main() { k := kite.New("first", "1.0.0") k.Config.Port = 6000 k.HandleFunc("square", func(r *kite.Request) (interface{}, error) { a := r.Args.One().MustFloat64() return a * a, nil }) k.Register(&url.URL{Scheme: "http", Host: "localhost:6000/kite"}) k.Run() }
服務端調用Register方法將自己註冊到Kontrol,使用的URL參數是其它kites連接本kite的地址,Kontrol會保存這個url,方便其它kites獲取;
客戶端:
package main import ( "fmt" "github.com/koding/kite" "github.com/koding/kite/protocol" ) func main() { k := kite.New("second", "1.0.0") // search a kite that has the same username and environment as us, but the // kite name should be "first" kites, _ := k.GetKites(&protocol.KontrolQuery{ Username: k.Config.Username, Environment: k.Config.Environment, Name: "first", }) // there might be several kites that matches our query client := kites[0] client.Dial() response, _ := client.Tell("square", 4) fmt.Println(response.MustFloat64()) }
GetKites方法會連接Kontrol,並獲取符合查找條件的kites列表。
本例子中是查找同一個用戶名下面名為"first"的所有kites,如果該用戶註冊了10個名為"first"的kites,在client都能返回,調用方可以使用特定的負載均衡算法(例如round robin)選擇其中一個。
參考文檔:
Kite API
https://blog.gopheracademy.com/birthday-bash-2014/kite-microservice-library/
https://toutiao.io/posts/yfwvyt/preview
Go的微服務庫kite