中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

gRPC的原理是什么

發布時間:2021-11-22 19:09:37 來源:億速云 閱讀:179 作者:柒染 欄目:云計算

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

什么是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解決方案,當然每個人都自己的看法或見解。針對不同的業務場景采用不同的解決方案,最終都是運行效率和開發效率的相互妥協的結果。

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新龙县| 天气| 东丽区| 巴塘县| 灵丘县| 临沧市| 玉田县| 嘉荫县| 沙洋县| 贞丰县| 石渠县| 隆安县| 芦溪县| 罗山县| 安图县| 东丰县| 巨鹿县| 西峡县| 扎鲁特旗| 阜南县| 武义县| 文成县| 高清| 天台县| 卫辉市| 从化市| 白朗县| 垦利县| 临澧县| 沭阳县| 灵山县| 增城市| 绵阳市| 开阳县| 洪雅县| 永州市| 乌海市| 温州市| 东城区| 高雄市| 共和县|