go語言中文社區,谷歌放棄golang了
gRPC簡介
gRPC () 是一個由Google開發的高性能、開源、跨多種編程語言和通用的遠程過程調用協議(RPC) 框架,用于客戶端和服務器端之間的通信,使用HTTP/2協議并將 ProtoBuf ()作為序列化工具。
gRPC模式
gRPC主要有4種請求/響應模式,分別是:
(1) 簡單模式(Simple RPC)
(2) 服務端數據流模式(Server-side streaming RPC)
這種模式是客戶端發起一次請求,服務端返回一段連續的數據流。典型的例子是客戶端向服務端發送一個股票代碼,服務端就把該股票的實時數據源源不斷的返回給客戶端。
(3) 客戶端數據流模式(Client-side streaming RPC)
(4) 雙向數據流模式(Bidirectional streaming RPC)
顧名思義,這是客戶端和服務端都可以向對方發送數據流,這個時候雙方的數據可以同時互相發送,也就是可以實現實時交互。典型的例子是聊天機器人。
雙向數據流實戰
1、proto定義
2// 包名: chat
3package chat;
4/*
5 服務名: Chat。
6 其中只有 名為“BidStream”的一個RPC服務。
7 輸入是 Request格式的數據流, 輸出是 Response 格式的數據流
8*
9service Chat {
10 rpc BidStream(stream Request) returns (stream Response) {}
11}
12// 請求數據 Request格式定義
13message Request {
14 string input = 1;
15}
16// 響應數據Response格式定義
17message Response {
18 string output = 1;
19}
服務端程序 server.go
2import (
3 "io"
4 "log"
5 "net"
6 "strconv"
7 "google.golang.org/grpc"
8 proto "chat" // 自動生成的 proto代碼
9)

10// Streamer 服務端
11type Streamer struct{}
12// BidStream 實現了 ChatServer 接口中定義的 BidStream 方法
13func (s *Streamer) BidStream(stream proto.Chat_BidStreamServer) error {
14 ctx := stream.Context()
15 for {
16 select {
17 case <-ctx.Done():
18 log.Println("收到客戶端通過context發出的終止信號")
19 return ctx.Err()
20 default:
21 // 接收從客戶端發來的消息
22 輸入,err := stream.Recv()
23 if err == io.EOF {
24 log.Println("客戶端發送的數據流結束")
25 return nil
26 }
27 if err != nil {
28 log.Println("接收數據出錯:",err)
29 return err
30 }
31 // 如果接收正常,則根據接收到的 字符串 執行相應的指令
32 switch 輸入.Input {
33 case "結束對話 ":
這個項目可以理解為針對互聯網IT人打造的中文版awesome-go。已有的awesome-go項目, 匯總了很多go開源項目, 但存在的問題是收集太全了, 而且每個項目沒有詳細描述。本項目作為awesome-go的一個擴展,根據go語言中文社區提供的。
34 log.Println("收到'結束對話'指令")
36 return err
37 }
38 // 收到結束指令時,通過 return nil 終止雙向數據流
39 return nil
40 case "返回數據流 ":
41 log.Println("收到'返回數據流'指令")
42 // 收到 收到'返回數據流'指令, 連續返回 10 條數據
43 for i := 0; i < 10; i++ {
44 if err := stream.Send(&proto.Response{Output: "數據流 #" + strconv.Itoa(i)}); err != nil {
45 return err
46 }
47 }
社區活躍度更高,更強調社區的作用,有[RFC](GitHub - rust-lang/rfcs: RFCs for changes to Rust)。[中文社區](Rust China)也有了 Rust的劣勢是:語言特性復雜,對新手就不會那么友好 穩定性不夠,語言的進化較激進 。
48 default:
49 // 缺省情況下, 返回 '服務端返回: ' + 輸入信息
50 log.Printf("[收到消息]: %s",輸入.Input)
51 if err := stream.Send(&proto.Response{Output: "服務端返回: " + 輸入.Input}); err != nil {
52 return err
53 }
54 }
55 }
56 }
57}
58func main() {
59 log.Println("啟動服務端...")
60 server := grpc.NewServer()
61 // 注冊 ChatServer
62 proto.RegisterChatServer(server,&Streamer{})
63 address,err := net.Listen("tcp",":3000")
64 if err != nil {
65 panic(err)
66 }
67 if err := server.Serve(address); err != nil {
68 panic(err)
69 }
70}
客戶端程序 client.go
2import (
3 "bufio"
4 "context"
5 "io"
6 "log"
7 "os"
8 "google.golang.org/grpc"
9 proto "chat" // 根據proto文件自動生成的代碼
10)
11func main() {
12 // 創建連接
14 if err != nil {
15 log.Printf("連接失敗: [%v] ",err)
16 return
17 }
18 defer conn.Close()
19 //
20 client := proto.NewChatClient(conn)
21 //
22 ctx := context.Background()
23 // 創建雙向數據流
24 stream,err := client.BidStream(ctx)
25 if err != nil {
26 log.Printf("創建數據流失敗: [%v] ",err)
27 }
28 // 啟動一個 goroutine 接收命令行輸入的指令
29 go func() {
30 log.Println("請輸入消息...")
31 輸入 := bufio.NewReader(os.Stdin)
32 for {
33 // 獲取 命令行輸入的字符串, 以回車 作為結束標志
34 命令行輸入的字符串,_ := 輸入.ReadString(' ')
35 // 向服務端發送 指令
36 if err := stream.Send(&proto.Request{Input: 命令行輸入的字符串}); err != nil {
37 return
38 }
39 }
40 }()
41 for {
42 // 接收從 服務端返回的數據流
43 響應,err := stream.Recv()
Go 由于不支持泛型而臭名昭著,但最近,泛型已接近成為現實。Go 團隊實施了一個看起來比較穩定的設計草案,并且正以源到源翻譯器原型的形式獲得關注。本文講述的是泛型的最新設計,以及如何自己嘗試泛型。例子FIFO Stack 假設。
44 if err == io.EOF {
45 log.Println("?? 收到服務端的結束信號")
46 break //如果收到結束信號,則退出“接收循環”,結束客戶端程序
47 }
48 if err != nil {
49 // TODO: 處理接收錯誤
50 log.Println("接收數據出錯:",err)
51 }
52 // 沒有錯誤的情況下,打印來自服務端的消息
53 log.Printf("[客戶端收到]: %s",響應.Output)
54 }
55}
運行效果
先啟動服務端程序 server.go
再啟動客戶端程序 client.go
輸入消息,結果類似下圖:
總結
gRPC是個很強大的RPC框架,而且支持多語言編程,上面的服務端、客戶端程序我們完全可以用不同的語言實現,比如服務端用JAVA,客戶端用Python...
gRPC的四種交互模式也給我們提供了很大的發揮空間,最近Nginx宣布支持gRPC,這可能也預示著某種趨勢...
異步社區是一個有料、有貨,又專業的IT專業圖書社區,在這里可以讀到最新、最熱的IT類圖書!
我想要社區的《Git高手之路》這本書,這本書是網絡編程的經典圖書,請大家幫我點贊!
本文摘自異步社區,作者:阿貍不歌 作品:《gRPC雙向數據流的交互控制(go語言實現)》
版權聲明:本站文章均來源于網絡,如有侵權請聯系刪除!
