ホームページ >バックエンド開発 >Golang >gRPC を使用して Golang で同時データ送信を実装するためのベスト プラクティス

gRPC を使用して Golang で同時データ送信を実装するためのベスト プラクティス

WBOY
WBOYオリジナル
2023-07-18 22:17:082433ブラウズ

gRPC を使用して Golang で同時データ送信を実装するためのベスト プラクティス

はじめに:
クラウド コンピューティングとビッグ データ テクノロジの発展に伴い、データ送信の需要はますます緊急になっています。 Google のオープンソースの高性能リモート プロシージャ コール フレームワークである gRPC は、その効率性、柔軟性、および言語間の機能により、多くの開発者の最初の選択肢となっています。この記事では、プロジェクト構造の構築、接続プールの使用、エラー処理など、gRPC を使用して Golang で同時データ送信を実装する方法のベスト プラクティスを紹介します。

1. プロジェクト構造の構築
gRPC の使用を開始する前に、プログラムの組織と管理をより明確にするために、適切なプロジェクト構造を構築する必要があります。

  1. プロジェクト ディレクトリの作成
    まず、gRPC 関連のコードとリソース ファイルを保存するプロジェクト ディレクトリを作成する必要があります。次のディレクトリ構造に従って編成できます。
myproject
├── api
│   └── myservice.proto
│
├── client
│   ├── client.go
│   └── main.go
│
└── server
    ├── server.go
    ├── handler.go
    └── main.go

このうち、api ディレクトリは gRPC サービスのインターフェイス定義を格納するために使用され、client ディレクトリはクライアント関連のコードと主要な関数を格納します。 、サーバーディレクトリにはサーバー関連のコードとメイン関数が保存されます。

  1. サービス インターフェイスの定義
    API ディレクトリに myservice.proto という名前のファイルを作成して、サービス インターフェイスを定義します。サンプル コードは次のとおりです。
syntax = "proto3";

package myproject;

service MyService {
    rpc GetData (GetDataRequest) returns (GetDataResponse) {}
}

message GetDataRequest {
    string id = 1;
}

message GetDataResponse {
    string data = 1;
}

ここでは、MyService という名前のサービスが定義されています。これには、GetDataRequest パラメーターを受け取り、GetDataResponse パラメーターを返す GetData という名前の RPC メソッドが含まれています。

  1. コードの生成
    プロジェクトのルート ディレクトリで次のコマンドを実行して、Golang コード ファイルを生成します:
protoc --proto_path=./api --go_out=plugins=grpc:./api ./api/myservice.proto 

これにより、ファイルという名前のファイルが生成されます。 myservice.pb.go には、gRPC サービスとメッセージ定義、およびその他の関連コードが含まれています。

2. クライアントの作成
次に、サーバーに同時リクエストを送信し、返されたデータを受信するクライアント コードの作成を開始します。

  1. 依存関係のインポート
    client/main.go では、まず gRPC、コンテキスト、同期などの関連する依存関係をインポートする必要があります:
package main

import (
    "context"
    "log"
    "sync"
    "time"

    "google.golang.org/grpc"
    pb "myproject/api" // 导入生成的代码
)
  1. 接続の作成
    main 関数では、サーバーとの接続を作成する必要があります。接続は、grpc.Dial 関数を使用して作成できます。サンプル コードは次のとおりです。
func main() {
    // 创建连接并指定服务端地址和端口
    conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
    if err != nil {
        log.Fatalf("failed to connect: %v", err)
    }
    defer conn.Close()

    // 创建客户端
    client := pb.NewMyServiceClient(conn)
    
    // 发送并发请求
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()

            // 创建上下文和请求
            ctx, cancel := context.WithTimeout(context.Background(), time.Second)
            defer cancel()
            req := &pb.GetDataRequest{
                Id: strconv.Itoa(id),
            }

            // 调用服务端方法
            resp, err := client.GetData(ctx, req)
            if err != nil {
                log.Printf("failed to get data: %v", err)
                return
            }

            // 输出结果
            log.Printf("data: %s", resp.Data)
        }(i)
    }
    
    // 等待所有请求完成
    wg.Wait()
}

上記のコードでは、まず grpc.Dial 関数を使用してサーバーとの接続を作成します。ここでは、例を簡略化するために、安全でない接続モード (Insecure) が使用されています。実際のアプリケーションでは、セキュア接続モード (Secure) を使用することをお勧めします。

次に、サーバー側メソッドを呼び出すための MyServiceClient インスタンスを作成しました。

次に、sync.WaitGroup を使用して同時リクエストを調整します。ループ内で、同時リクエストを開始するための匿名関数を作成します。同時に実行される各リクエストで、コンテキストとリクエスト オブジェクトを作成し、サーバー側メソッド GetData を呼び出します。

最後に、wg.Wait を使用して、すべての同時リクエストが完了するのを待ちます。

3. サーバーを作成する
次に、クライアントのリクエストを受信し、処理されたデータを返すサーバー コードの作成を開始します。

  1. 依存関係のインポート
    server/main.go では、まず gRPC、ログ、ネットなどの関連する依存関係をインポートする必要があります:
package main

import (
    "log"
    "net"

    "google.golang.org/grpc"
    pb "myproject/api" // 导入生成的代码
)
  1. インターフェイスの実装
    handler.go では、定義されたサービス インターフェイスを実装する必要があります。サンプル コードは次のとおりです。
package main

import (
    "context"
)

// 定义服务
type MyServiceServer struct{}

// 实现方法
func (s *MyServiceServer) GetData(ctx context.Context, req *pb.GetDataRequest) (*pb.GetDataResponse, error) {
    // 处理请求
    data := "Hello, " + req.Id

    // 构造响应
    resp := &pb.GetDataResponse{
        Data: data,
    }

    return resp, nil
}

ここでは、MyServiceServer 構造体と GetData メソッドを実装します。このメソッドでは、まずリクエストを処理し、次にレスポンスを構築して返します。

  1. サービスの作成
    main 関数では、gRPC サービスを作成して開始する必要があります。サービスは、grpc.NewServer 関数を使用して作成できます。サンプル コードは次のとおりです。
func main() {
    // 监听TCP端口
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    // 创建gRPC服务
    s := grpc.NewServer()

    // 注册服务
    pb.RegisterMyServiceServer(s, &MyServiceServer{})

    // 启动服务
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

上記のコードでは、まず net.Listen 関数を使用して TCP リスナーを作成し、リスニング ポートを 50051 に指定します。

次に、grpc.NewServer 関数を使用して gRPC サービスを作成し、pb.RegisterMyServiceServer メソッドを使用してサービスに実装したサービスを登録します。

最後に、s.Serve(lis) メソッドを使用してサービスを開始し、指定されたポートをリッスンします。

4. コード例のデモ
以下では、gRPC を使用して Golang で同時データ送信を実装する方法を示す完全な例を使用します。

まず、server/main.go に次のコードを追加する必要があります:

package main

// main函数入口
func main() {
    // 注册服务
    pb.RegisterMyServiceServer(s, &MyServiceServer{})
    
    // 启动服务
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

次に、client/main.go に次のコードを追加します:

package main

// main函数入口
func main() {
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    req := &pb.GetDataRequest{
        Id: "1",
    }

    resp, err := client.GetData(ctx, req)
    if err != nil {
        log.Fatalf("failed to get data: %v", err)
    }

    log.Printf("data: %s", resp.Data)
}

最後にプロジェクトのルート ディレクトリで次のコマンドを実行して、サーバーとクライアントを起動できます。

go run server/main.go
go run client/main.go

実行結果は次のとおりです。

2021/01/01 15:00:00 data: Hello, 1

サーバーが正常に受信したことがわかります。クライアントのリクエストに応じて処理されたデータが返されます。

概要:
この記事では、gRPC を使用して Golang で同時データ送信を実装する方法のベスト プラクティスを紹介します。適切なプロジェクト構造を構築し、接続を作成し、サービス インターフェイスを実装し、サービスを開始することで、同時データ送信に gRPC を簡単に使用できます。この記事が、gRPC を使用している、またはこれから使用する開発者に役立つことを願っています。

以上がgRPC を使用して Golang で同時データ送信を実装するためのベスト プラクティスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。