最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go?gRPC服務(wù)客戶端流式RPC教程

 更新時間:2022年06月16日 08:52:24   作者:煙花易冷人憔悴  
這篇文章主要為大家介紹了Go?gRPC服務(wù)客戶端流式RPC教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

上一篇介紹了服務(wù)端流式RPC,客戶端發(fā)送請求到服務(wù)器,拿到一個流去讀取返回的消息序列。 客戶端讀取返回的流的數(shù)據(jù)。本篇將介紹客戶端流式RPC。

客戶端流式RPC:與服務(wù)端流式RPC相反,客戶端不斷的向服務(wù)端發(fā)送數(shù)據(jù)流,而在發(fā)送結(jié)束后,由服務(wù)端返回一個響應(yīng)。

情景模擬:客戶端大量數(shù)據(jù)上傳到服務(wù)端

新建proto文件

新建client_stream.proto文件

1.定義發(fā)送信息

// 定義流式請求信息
message StreamRequest{
    //流式請求參數(shù)
    string stream_data = 1;
}

2.定義接收信息

// 定義響應(yīng)信息
message SimpleResponse{
    //響應(yīng)碼
    int32 code = 1;
    //響應(yīng)值
    string value = 2;
}

3.定義服務(wù)方法RouteList

客戶端流式rpc,只要在請求的參數(shù)前添加stream即可

service StreamClient{
    // 客戶端流式rpc,在請求的參數(shù)前添加stream
    rpc RouteList (stream StreamRequest) returns (SimpleResponse){};
}

4.編譯proto文件

進(jìn)入client_stream.proto所在目錄,運(yùn)行指令:

protoc --go_out=plugins=grpc:./ ./client_stream.proto

創(chuàng)建Server端

1.定義我們的服務(wù),并實現(xiàn)RouteList方法

// SimpleService 定義我們的服務(wù)
type SimpleService struct{}
// RouteList 實現(xiàn)RouteList方法
func (s *SimpleService) RouteList(srv pb.StreamClient_RouteListServer) error {
	for {
		//從流中獲取消息
		res, err := srv.Recv()
		if err == io.EOF {
			//發(fā)送結(jié)果,并關(guān)閉
			return srv.SendAndClose(&pb.SimpleResponse{Value: "ok"})
		}
		if err != nil {
			return err
		}
		log.Println(res.StreamData)
	}
}

2.啟動gRPC服務(wù)器

const (
	// Address 監(jiān)聽地址
	Address string = ":8000"
	// Network 網(wǎng)絡(luò)通信協(xié)議
	Network string = "tcp"
)

func main() {
	// 監(jiān)聽本地端口
	listener, err := net.Listen(Network, Address)
	if err != nil {
		log.Fatalf("net.Listen err: %v", err)
	}
	log.Println(Address + " net.Listing...")
	// 新建gRPC服務(wù)器實例
	grpcServer := grpc.NewServer()
	// 在gRPC服務(wù)器注冊我們的服務(wù)
	pb.RegisterStreamClientServer(grpcServer, &SimpleService{})

	//用服務(wù)器 Serve() 方法以及我們的端口信息區(qū)實現(xiàn)阻塞等待,直到進(jìn)程被殺死或者 Stop() 被調(diào)用
	err = grpcServer.Serve(listener)
	if err != nil {
		log.Fatalf("grpcServer.Serve err: %v", err)
	}
}

運(yùn)行服務(wù)端

go run server.go
:8000 net.Listing...

創(chuàng)建Client端

1.創(chuàng)建調(diào)用服務(wù)端RouteList方法

// routeList 調(diào)用服務(wù)端RouteList方法
func routeList() {
	//調(diào)用服務(wù)端RouteList方法,獲流
	stream, err := streamClient.RouteList(context.Background())
	if err != nil {
		log.Fatalf("Upload list err: %v", err)
	}
	for n := 0; n < 5; n++ {
		//向流中發(fā)送消息
		err := stream.Send(&pb.StreamRequest{StreamData: "stream client rpc " + strconv.Itoa(n)})
		if err != nil {
			log.Fatalf("stream request err: %v", err)
		}
	}
	//關(guān)閉流并獲取返回的消息
	res, err := stream.CloseAndRecv()
	if err != nil {
		log.Fatalf("RouteList get response err: %v", err)
	}
	log.Println(res)
}

2.啟動gRPC客戶端

// Address 連接地址
const Address string = ":8000"

var streamClient pb.StreamClientClient

func main() {
	// 連接服務(wù)器
	conn, err := grpc.Dial(Address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("net.Connect err: %v", err)
	}
	defer conn.Close()

	// 建立gRPC連接
	streamClient = pb.NewStreamClientClient(conn)
	routeList()
}

運(yùn)行客戶端

go run client.go
code:200 value:"hello grpc"
value:"ok"

服務(wù)端不斷從客戶端獲取到數(shù)據(jù)

stream client rpc 0
stream client rpc 1
stream client rpc 2
stream client rpc 3
stream client rpc 4

思考

服務(wù)端在沒有接受完消息時候能主動停止接收數(shù)據(jù)嗎(很少有這種場景)?

答案:可以的,但是客戶端代碼需要注意EOF判斷

1.我們把服務(wù)端的RouteList方法實現(xiàn)稍微修改,當(dāng)接收到一條數(shù)據(jù)后馬上調(diào)用SendAndClose()關(guān)閉stream.

// RouteList 實現(xiàn)RouteList方法
func (s *SimpleService) RouteList(srv pb.StreamClient_RouteListServer) error {
	for {
		//從流中獲取消息
		res, err := srv.Recv()
		if err == io.EOF {
			//發(fā)送結(jié)果,并關(guān)閉
			return srv.SendAndClose(&pb.SimpleResponse{Value: "ok"})
		}
		if err != nil {
			return err
		}
		log.Println(res.StreamData)
		return srv.SendAndClose(&pb.SimpleResponse{Value: "ok"})
	}
}

2.再把客戶端調(diào)用RouteList方法的實現(xiàn)稍作修改

// routeList 調(diào)用服務(wù)端RouteList方法
func routeList() {
	//調(diào)用服務(wù)端RouteList方法,獲流
	stream, err := streamClient.RouteList(context.Background())
	if err != nil {
		log.Fatalf("Upload list err: %v", err)
	}
	for n := 0; n < 5; n++ {
		//向流中發(fā)送消息
		err := stream.Send(&pb.StreamRequest{StreamData: "stream client rpc " + strconv.Itoa(n)})
		//發(fā)送也要檢測EOF,當(dāng)服務(wù)端在消息沒接收完前主動調(diào)用SendAndClose()關(guān)閉stream,此時客戶端還執(zhí)行Send(),則會返回EOF錯誤,所以這里需要加上io.EOF判斷
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalf("stream request err: %v", err)
		}
	}
	//關(guān)閉流并獲取返回的消息
	res, err := stream.CloseAndRecv()
	if err != nil {
		log.Fatalf("RouteList get response err: %v", err)
	}
	log.Println(res)
}

客戶端Send()需要檢測err是否為EOF,因為當(dāng)服務(wù)端在消息沒接收完前主動調(diào)用SendAndClose()關(guān)閉stream,若此時客戶端繼續(xù)執(zhí)行Send(),則會返回EOF錯誤。

總結(jié)

本篇介紹了客戶端流式RPC的簡單使用,下篇將介紹雙向流式RPC。

教程源碼地址:https://github.com/Bingjian-Zhu/go-grpc-example

參考:gRPC官方文檔中文版

以上就是Go gRPC服務(wù)客戶端流式RPC教程的詳細(xì)內(nèi)容,更多關(guān)于Go gRPC客戶端流式RPC的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang的循環(huán)語句和循環(huán)控制語句詳解

    Golang的循環(huán)語句和循環(huán)控制語句詳解

    循環(huán)語句為了簡化程序中有規(guī)律的重復(fù)性操作,需要用到循環(huán)語句,和其他大多數(shù)編程語言一樣,GO的循環(huán)語句有for循環(huán),不同的是沒有while循環(huán),而循環(huán)控制語句可以改變循環(huán)語句的執(zhí)行過程,下面給大家介紹下go循環(huán)語句和循環(huán)控制語句的相關(guān)知識,一起看看吧
    2021-11-11
  • Go讀寫鎖操作方法示例詳解

    Go讀寫鎖操作方法示例詳解

    這篇文章主要為大家介紹了Go讀寫鎖方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 在?Golang?中使用?Cobra?創(chuàng)建?CLI?應(yīng)用

    在?Golang?中使用?Cobra?創(chuàng)建?CLI?應(yīng)用

    這篇文章主要介紹了在?Golang?中使用?Cobra?創(chuàng)建?CLI?應(yīng)用,來看下?Cobra?的使用,這里我們使用的?go1.13.3?版本,使用?Go?Modules?來進(jìn)行包管理,需要的朋友可以參考下
    2022-01-01
  • golang中defer的關(guān)鍵特性示例詳解

    golang中defer的關(guān)鍵特性示例詳解

    defer是golang語言中的關(guān)鍵字,用于資源的釋放,會在函數(shù)返回之前進(jìn)行調(diào)用。下面這篇文章主要給大家介紹了關(guān)于golang中defer的關(guān)鍵特性,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-08-08
  • Go語言使用Buffer實現(xiàn)高性能處理字節(jié)和字符

    Go語言使用Buffer實現(xiàn)高性能處理字節(jié)和字符

    在?Go?中,bytes.Buffer?是一個非常高效的類型,用于處理字節(jié)數(shù)據(jù)的讀寫操作,本文將詳細(xì)介紹一下如何使用Buffer實現(xiàn)高性能處理字節(jié)和字符,有需要的小伙伴可以了解下
    2025-01-01
  • 使用Golang實現(xiàn)流式輸出

    使用Golang實現(xiàn)流式輸出

    這篇文章主要為大家詳細(xì)介紹了使用Golang實現(xiàn)流式輸出的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • 淺析golang的依賴注入

    淺析golang的依賴注入

    這篇文章主要介紹了淺析golang的依賴注入,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-09-09
  • 9個Golang中map常用示例分享

    9個Golang中map常用示例分享

    這篇文章主要和大家分享9個Golang中map可能是常用的使用案例,從1到9,越來越厲害。文中的示例代碼講解詳細(xì),希望對大家學(xué)習(xí)Golang有一定的幫助
    2023-02-02
  • Go語言中interface語法與使用詳解

    Go語言中interface語法與使用詳解

    Go語言里面設(shè)計最精妙的應(yīng)該算interface,它讓面向?qū)ο?內(nèi)容組織實現(xiàn)非常的方便,下面這篇文章主要給大家介紹了關(guān)于Go語言中interface語法與使用的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • 利用Go語言實現(xiàn)在終端繪制小兔子

    利用Go語言實現(xiàn)在終端繪制小兔子

    這篇文章主要為大家詳細(xì)介紹了如何利用Go語言實現(xiàn)在終端繪制小兔子來給大家拜個早年,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-01-01

最新評論

克山县| 棋牌| 泸定县| 航空| 集安市| 安龙县| 含山县| 靖边县| 浦江县| 田东县| 嘉义市| 漳浦县| 双柏县| 托里县| 兴城市| 河南省| 城口县| 洛南县| 关岭| 克山县| 新沂市| 鲁山县| 类乌齐县| 泗阳县| 霞浦县| 沂源县| 瑞昌市| 泰兴市| 宝清县| 镇巴县| 邻水| 东兰县| 晋城| 轮台县| 祥云县| 伊春市| 澳门| 郧西县| 闸北区| 时尚| 洛扎县|