<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
gRPC預設的請求的超時時間是很長的,當你沒有設定請求超時時間時,所有在執行的請求都佔用大量資源且可能執行很長的時間,導致服務資源損耗過高,使得後來的請求響應過慢,甚至會引起整個程序崩潰。
為了避免這種情況,我們的服務應該設定超時時間。
前面的入門教學
提到當用戶端發起請求時候,需要傳入上下文context.Context,用於結束超時或取消的請求。
本篇以簡單RPC為例,介紹如何設定gRPC請求的超時時間。
修改呼叫伺服器端方法
1.把超時時間設定為當前時間+3秒
clientDeadline := time.Now().Add(time.Duration(3 * time.Second)) ctx, cancel := context.WithDeadline(ctx, clientDeadline) defer cancel()
2.響應錯誤檢測中新增超時檢測
// 傳入超時時間為3秒的ctx res, err := grpcClient.Route(ctx, &req) if err != nil { //獲取錯誤狀態 statu, ok := status.FromError(err) if ok { //判斷是否為呼叫超時 if statu.Code() == codes.DeadlineExceeded { log.Fatalln("Route timeout!") } } log.Fatalf("Call Route err: %v", err) } // 列印返回值 log.Println(res.Value)
完整的client.go程式碼
package main import ( "context" "log" "time" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" pb "go-grpc-example/6-grpc_deadlines/proto" ) // Address 連線地址 const Address string = ":8000" var grpcClient pb.SimpleClient func main() { // 連線伺服器 conn, err := grpc.Dial(Address, grpc.WithInsecure()) if err != nil { log.Fatalf("net.Connect err: %v", err) } defer conn.Close() ctx := context.Background() // 建立gRPC連線 grpcClient = pb.NewSimpleClient(conn) route(ctx, 2) } // route 呼叫伺服器端Route方法 func route(ctx context.Context, deadlines time.Duration) { //設定3秒超時時間 clientDeadline := time.Now().Add(time.Duration(deadlines * time.Second)) ctx, cancel := context.WithDeadline(ctx, clientDeadline) defer cancel() // 建立傳送結構體 req := pb.SimpleRequest{ Data: "grpc", } // 呼叫我們的服務(Route方法) // 傳入超時時間為3秒的ctx res, err := grpcClient.Route(ctx, &req) if err != nil { //獲取錯誤狀態 statu, ok := status.FromError(err) if ok { //判斷是否為呼叫超時 if statu.Code() == codes.DeadlineExceeded { log.Fatalln("Route timeout!") } } log.Fatalf("Call Route err: %v", err) } // 列印返回值 log.Println(res.Value) }
當請求超時後,伺服器端應該停止正在進行的操作,避免資源浪費。
// Route 實現Route方法 func (s *SimpleService) Route(ctx context.Context, req *pb.SimpleRequest) (*pb.SimpleResponse, error) { data := make(chan *pb.SimpleResponse, 1) go handle(ctx, req, data) select { case res := <-data: return res, nil case <-ctx.Done(): return nil, status.Errorf(codes.Canceled, "Client cancelled, abandoning.") } } func handle(ctx context.Context, req *pb.SimpleRequest, data chan<- *pb.SimpleResponse) { select { case <-ctx.Done(): log.Println(ctx.Err()) runtime.Goexit() //超時後退出該Go協程 case <-time.After(4 * time.Second): // 模擬耗時操作 res := pb.SimpleResponse{ Code: 200, Value: "hello " + req.Data, } // //修改資料庫前進行超時判斷 // if ctx.Err() == context.Canceled{ // ... // //如果已經超時,則退出 // } data <- &res } }
一般地,在寫庫前進行超時檢測,發現超時就停止工作。
完整server.go程式碼
package main import ( "context" "log" "net" "runtime" "time" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" pb "go-grpc-example/6-grpc_deadlines/proto" ) // SimpleService 定義我們的服務 type SimpleService struct{} const ( // Address 監聽地址 Address string = ":8000" // Network 網路通訊協定 Network string = "tcp" ) func main() { // 監聽本地埠 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.RegisterSimpleServer(grpcServer, &SimpleService{}) //用伺服器 Serve() 方法以及我們的埠資訊區實現阻塞等待,直到程序被殺死或者 Stop() 被呼叫 err = grpcServer.Serve(listener) if err != nil { log.Fatalf("grpcServer.Serve err: %v", err) } } // Route 實現Route方法 func (s *SimpleService) Route(ctx context.Context, req *pb.SimpleRequest) (*pb.SimpleResponse, error) { data := make(chan *pb.SimpleResponse, 1) go handle(ctx, req, data) select { case res := <-data: return res, nil case <-ctx.Done(): return nil, status.Errorf(codes.Canceled, "Client cancelled, abandoning.") } } func handle(ctx context.Context, req *pb.SimpleRequest, data chan<- *pb.SimpleResponse) { select { case <-ctx.Done(): log.Println(ctx.Err()) runtime.Goexit() //超時後退出該Go協程 case <-time.After(4 * time.Second): // 模擬耗時操作 res := pb.SimpleResponse{ Code: 200, Value: "hello " + req.Data, } // //修改資料庫前進行超時判斷 // if ctx.Err() == context.Canceled{ // ... // //如果已經超時,則退出 // } data <- &res } }
伺服器端:
:8000 net.Listing...
goroutine still running
使用者端:
Route timeout!
超時時間的長短需要根據自身服務而定,例如返回一個hello grpc,可能只需要幾十毫秒,然而處理大量資料的同步操作則可能要很長時間。需要考慮多方面因素來決定這個超時時間,例如系統間端到端的延時,哪些RPC是序列的,哪些是可以並行的等等。
教學原始碼地址:https://github.com/Bingjian-Zhu/go-grpc-example
參考:https://grpc.io/blog/deadlines/
以上就是Go gRPC進階服務超時設定的詳細內容,更多關於Go gRPC超時設定的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45