欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go?gRPC服務客戶端流式RPC教程

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

前言

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

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

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

新建proto文件

新建client_stream.proto文件

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

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

2.定義接收信息

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

3.定義服務方法RouteList

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

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

4.編譯proto文件

進入client_stream.proto所在目錄,運行指令:

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

創(chuàng)建Server端

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

// SimpleService 定義我們的服務
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服務器

const (
	// Address 監(jiān)聽地址
	Address string = ":8000"
	// Network 網(wǎng)絡通信協(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服務器實例
	grpcServer := grpc.NewServer()
	// 在gRPC服務器注冊我們的服務
	pb.RegisterStreamClientServer(grpcServer, &SimpleService{})

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

運行服務端

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

創(chuàng)建Client端

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

// routeList 調(diào)用服務端RouteList方法
func routeList() {
	//調(diào)用服務端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() {
	// 連接服務器
	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()
}

運行客戶端

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

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

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

思考

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

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

1.我們把服務端的RouteList方法實現(xiàn)稍微修改,當接收到一條數(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)用服務端RouteList方法
func routeList() {
	//調(diào)用服務端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,當服務端在消息沒接收完前主動調(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,因為當服務端在消息沒接收完前主動調(diào)用SendAndClose()關(guān)閉stream,若此時客戶端繼續(xù)執(zhí)行Send(),則會返回EOF錯誤。

總結(jié)

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

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

參考:gRPC官方文檔中文版

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

相關(guān)文章

  • 淺析Golang中的協(xié)程(goroutine)

    淺析Golang中的協(xié)程(goroutine)

    在Go語言中,協(xié)程(goroutine)是輕量級的線程,它是Go語言中實現(xiàn)并發(fā)編程的基礎,Go語言中的協(xié)程是由Go運行時調(diào)度器(scheduler)進行管理和調(diào)度的,本文將給大家簡單的介紹一下Golang中的協(xié)程,需要的朋友可以參考下
    2023-05-05
  • Golang實現(xiàn)HTTP代理突破IP訪問限制的步驟詳解

    Golang實現(xiàn)HTTP代理突破IP訪問限制的步驟詳解

    在當今互聯(lián)網(wǎng)時代,網(wǎng)站和服務商為了維護安全性和保護用戶隱私,常常會對特定的IP地址進行封鎖或限制,本文將介紹如何使用Golang實現(xiàn)HTTP代理來突破IP訪問限制,需要的朋友可以參考下
    2023-10-10
  • golang通過cgo調(diào)用C++庫源碼示例

    golang通過cgo調(diào)用C++庫源碼示例

    這篇文章主要給大家介紹了關(guān)于golang通過cgo調(diào)用C++庫的相關(guān)資料,CGO是GO語言里面的一個特性,CGO屬于GOLANG的高級用法,主要是通過使用GOLANG調(diào)用CLANG實現(xiàn)的程序庫,需要的朋友可以參考下
    2024-02-02
  • 深入理解Golang?Channel?的底層結(jié)構(gòu)

    深入理解Golang?Channel?的底層結(jié)構(gòu)

    這篇文章主要介紹了深入理解Golang?Channel?的底層結(jié)構(gòu),Go?語言的?channel?底層是什么數(shù)據(jù)結(jié)構(gòu)?下面我們就一起來深入解析一下?channel,需要的朋友可以參考下
    2022-01-01
  • Go語言CSP并發(fā)模型goroutine及channel底層實現(xiàn)原理

    Go語言CSP并發(fā)模型goroutine及channel底層實現(xiàn)原理

    這篇文章主要為大家介紹了Go語言CSP并發(fā)模型goroutine?channel底層實現(xiàn)原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • GoPath模式和GoMoudle模式的相愛相殺

    GoPath模式和GoMoudle模式的相愛相殺

    這篇文章主要介紹了GoPath模式和GoMoudle模式的相愛相殺,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 在Go中構(gòu)建并發(fā)TCP服務器

    在Go中構(gòu)建并發(fā)TCP服務器

    今天小編就為大家分享一篇關(guān)于在Go中構(gòu)建并發(fā)TCP服務器的文章,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • golang中的時間格式化

    golang中的時間格式化

    這篇文章主要介紹了golang中的時間格式化問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 一文總結(jié)Go語言切片核心知識點和坑

    一文總結(jié)Go語言切片核心知識點和坑

    都說Go的切片用起來絲滑得很,Java中的List怎么用,切片就怎么用,作為曾經(jīng)的Java選手,因為切片的使用不得當,喜提缺陷若干,本文就給大家總結(jié)一下Go語言切片核心知識點和坑,需要的朋友可以參考下
    2023-06-06
  • Go素數(shù)篩選分析詳解

    Go素數(shù)篩選分析詳解

    學習Go語言的過程中,遇到素數(shù)篩選的問題。這是一個經(jīng)典的并發(fā)編程問題,是某大佬的代碼,短短幾行代碼就實現(xiàn)了素數(shù)篩選,這篇文章主要介紹了Go素數(shù)篩選分析,需要的朋友可以參考下
    2022-10-10

最新評論