久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

gRPC的原理是什么

179次閱讀
沒有評論

共計 4664 個字符,預計需要花費 12 分鐘才能閱讀完成。

gRPC 的原理是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

什么是 gRPC

gRPC 是什么?可以用官網的一句話來概括:A high-performance, open-source universal RPC framework。

所謂 RPC(remote procedure call 遠程過程調用) 框架實際是提供了一套機制,使得應用程序之間可以進行通信,而且也遵從 server/client 模型。使用的時候客戶端調用 server 端提供的接口就像是調用本地的函數一樣。如下圖所示就是一個典型的 RPC 結構圖。

gRPC 的原理是什么

gRPC vs Restful API

gRPC 和 restful API 都提供了一套通信機制,用于 server/client 模型通信,而且它們都使用 http 作為底層的傳輸協議 (嚴格地說,gRPC 使用的 http2.0,而 restful api 則不一定)。不過 gRPC 還是有些特有的優勢,如下:

gRPC 可以通過 protobuf 來定義接口,從而可以有更加嚴格的接口約束條件。關于 protobuf 可以參見下期 Protobuf 簡明教程,另外,通過 protobuf 可以將數據序列化為二進制編碼,這會大幅減少需要傳輸的數據量,從而大幅提高性能。

gRPC 可以方便地支持流式通信 (理論上通過 http2.0 就可以使用 streaming 模式, 但是通常 web 服務的 restful api 似乎很少這么用,通常的流式數據應用如視頻流,一般都會使用專門的協議如 HLS,RTMP 等,這些就不是我們通常 web 服務了,而是有專門的服務器應用。)

使用場景

需要對接口進行嚴格約束的情況,比如我們提供了一個公共的服務,很多人,甚至公司外部的人也可以訪問這個服務,這時對于接口我們希望有更加嚴格的約束,我們不希望客戶端給我們傳遞任意的數據,尤其是考慮到安全性的因素,我們通常需要對接口進行更加嚴格的約束。這時 gRPC 就可以通過 protobuf 來提供嚴格的接口約束。

對于性能有更高的要求時。有時我們的服務需要傳遞大量的數據,而又希望不影響我們的性能,這個時候也可以考慮 gRPC 服務,因為通過 protobuf 我們可以將數據壓縮編碼轉化為二進制格式,通常傳遞的數據量要小得多,而且通過 http2 我們可以實現異步的請求,從而大大提高了通信效率。

但是,通常我們不會去單獨使用 gRPC,而是將 gRPC 作為一個部件進行使用,這是因為在生產環境,我們面對大并發的情況下,需要使用分布式系統來去處理,而 gRPC 并沒有提供分布式系統相關的一些必要組件。而且,真正的線上服務還需要提供包括負載均衡,限流熔斷,監控報警,服務注冊和發現等等必要的組件。不過,這就不屬于本篇文章討論的主題了,我們還是先繼續看下如何使用 gRPC。

gRPC DEMO 實例詳解

通過 protobuf 來定義接口和數據類型

編寫 gRPC server 端代碼

編寫 gRPC client 端代碼
本文使用 golang 去實現 demo,其中 protobuf 和 grpc 擴展的安裝就跳過了。

新建 userrpc.proto

syntax =  proto3 
package user;
option go_package =  ./grpc/user 
// The User service definition.
service User { 
 // Get all Users with id - A server-to-client streaming RPC.
 rpc GetUsers(UserFilter) returns (stream UserRequest) {}
 // Create a new User - A simple RPC 
 rpc CreateUser (UserRequest) returns (UserResponse) {}
// Request message for creating a new user
message UserRequest {
 int32 id = 1; // Unique ID number for a User.
 string name = 2;
 string email = 3;
 string phone= 4;
 message Address {
 string province = 1;
 string city = 2; 
 }
 repeated Address addresses = 5;
message UserResponse {
 int32 id = 1;
 bool success = 2;
message UserFilter { int32 id = 1;}

編譯 .proto 文件

protoc --go_out=plugins=grpc:. userrpc.proto

新建服務端 server.go

package main
import (
  log 
  net 
  golang.org/x/net/context 
  google.golang.org/grpc 
 pb  userrpc/grpc/user 
const (
 port =  :50051 
// server is used to implement user.UserServer.
type server struct { savedUsers []*pb.UserRequest
// CreateUser creates a new User
func (s *server) CreateUser(ctx context.Context, in *pb.UserRequest) (*pb.UserResponse, error) { s.savedUsers = append(s.savedUsers, in)
 return  pb.UserResponse{Id: in.Id, Success: true}, nil
// GetUsers returns all users by given id
func (s *server) GetUsers(filter *pb.UserFilter, stream pb.User_GetUsersServer) error {
 for _, user := range s.savedUsers {
 if filter.Id == 0 {
 continue
 }
 if err := stream.Send(user); err != nil {
 return err
 }
 }
 return nil
func main() { lis, err := net.Listen( tcp , port)
 if err != nil { log.Fatalf( failed to listen: %v , err)
 }
 // Creates a new gRPC server
 s := grpc.NewServer()
 pb.RegisterUserServer(s,  server{})
 s.Serve(lis)
}

客戶端 client.go

package main
import (
  io 
  log 
  golang.org/x/net/context 
  google.golang.org/grpc 
 pb  userrpc/grpc/user 
const (
 address =  localhost:50051 
// createUser calls the RPC method CreateUser of UserServer
func createUser(client pb.UserClient, user *pb.UserRequest) { resp, err := client.CreateUser(context.Background(), user)
 if err != nil { log.Fatalf( Could not create User: %v , err)
 }
 if resp.Success { log.Printf( A new User has been added with id: %d , resp.Id)
 }
// getUsers calls the RPC method GetUsers of UserServer
func getUsers(client pb.UserClient, id *pb.UserFilter) {
 // calling the streaming API
 stream, err := client.GetUsers(context.Background(), id)
 if err != nil { log.Fatalf( Error on get users: %v , err)
 }
 for { user, err := stream.Recv()
 if err == io.EOF {
 break
 }
 if err != nil { log.Fatalf( %v.GetUsers(_) = _, %v , client, err)
 }
 log.Printf(User: %v , user)
 }
func main() {
 // Set up a connection to the gRPC server.
 conn, err := grpc.Dial(address, grpc.WithInsecure())
 if err != nil { log.Fatalf( did not connect: %v , err)
 }
 defer conn.Close()
 // Creates a new UserClient
 client := pb.NewUserClient(conn)
 user :=  pb.UserRequest{
 Id: 1,
 Name:  test ,
 Email:  fasd@163.com ,
 Phone:  132222222 ,
 Addresses: []*pb.UserRequest_Address{
  pb.UserRequest_Address{
 Province:  hebei ,
 City:  shijiazhuang ,
 },
 },
 }
 // Create a new user
 createUser(client, user)
 // Filter with an id
 filter :=  pb.UserFilter{Id: 1}
 getUsers(client, filter)
}

啟動 server.go

go run server.go

新打開一個窗口,啟動 client.go

go run client.go

結果為

2019/07/04 17:01:16 A new User has been added with id: 1
2019/07/04 17:01:16 User: id:1 name: test

Api 實現起來比較繁瑣,給開發帶來難度。總的來說 gRPC 是一個不錯的跨語言 rpc 解決方案,當然每個人都自己的看法或見解。針對不同的業務場景采用不同的解決方案,最終都是運行效率和開發效率的相互妥協的結果。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注丸趣 TV 行業資訊頻道,感謝您對丸趣 TV 的支持。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-25發表,共計4664字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 图片| 民勤县| 内乡县| 南漳县| 隆化县| 湘西| 龙州县| 治县。| 翁牛特旗| 沽源县| 贡觉县| 兴义市| 南安市| 澄城县| 高密市| 凤庆县| 泸溪县| 武功县| 穆棱市| 渑池县| 阿瓦提县| 凤庆县| 麻江县| 通州区| 清徐县| 闸北区| 时尚| 浪卡子县| 彩票| 彰化县| 武邑县| 庐江县| 奈曼旗| 通辽市| 区。| 昌都县| 娄烦县| 崇信县| 池州市| 同德县| 松滋市|