Maison  >  Article  >  développement back-end  >  Meilleures pratiques d'utilisation de gRPC pour implémenter la transmission simultanée de données dans Golang

Meilleures pratiques d'utilisation de gRPC pour implémenter la transmission simultanée de données dans Golang

WBOY
WBOYoriginal
2023-07-18 22:17:082381parcourir

Bonnes pratiques d'utilisation de gRPC pour mettre en œuvre la transmission simultanée de données dans Golang

Introduction :
Avec le développement du cloud computing et de la technologie du big data, la demande de transmission de données devient de plus en plus urgente. En tant que framework d'appel de procédure à distance hautes performances open source de Google, gRPC est devenu le premier choix de nombreux développeurs en raison de son efficacité, de sa flexibilité et de ses fonctionnalités multilingues. Cet article présentera les meilleures pratiques d'utilisation de gRPC pour réaliser une transmission simultanée de données dans Golang, y compris la construction de la structure du projet, l'utilisation de pools de connexions et la gestion des erreurs, etc.

1. Construire la structure du projet
Avant de commencer à utiliser gRPC, nous devons construire une structure de projet appropriée pour rendre l'organisation et la gestion du programme plus claires.

  1. Créer un répertoire de projet
    Tout d'abord, nous devons créer un répertoire de projet pour stocker le code et les fichiers de ressources liés à gRPC. Il peut être organisé selon la structure de répertoires suivante :
myproject
├── api
│   └── myservice.proto
│
├── client
│   ├── client.go
│   └── main.go
│
└── server
    ├── server.go
    ├── handler.go
    └── main.go

Parmi eux, le répertoire api est utilisé pour stocker la définition de l'interface du service gRPC, le répertoire client stocke le code et la fonction principale liés au client, et le répertoire serveur stocke code lié au serveur et fonction principale.

  1. Définir l'interface de service
    Créez un fichier nommé myservice.proto dans le répertoire api pour définir notre interface de service. L'exemple de code est le suivant :
syntax = "proto3";

package myproject;

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

message GetDataRequest {
    string id = 1;
}

message GetDataResponse {
    string data = 1;
}

Un service nommé MyService est défini ici, comprenant une méthode RPC nommée GetData, qui reçoit un paramètre GetDataRequest et renvoie un paramètre GetDataResponse.

  1. Générer le code
    Exécutez la commande suivante dans le répertoire racine du projet pour générer le fichier de code Golang :
protoc --proto_path=./api --go_out=plugins=grpc:./api ./api/myservice.proto 

Cela générera un fichier nommé myservice.pb.go dans le répertoire api, qui contient le service gRPC et Définition du message et autres codes associés.

2. Créez le client
Ensuite, nous commencerons à écrire le code client pour envoyer des requêtes simultanées au serveur et recevoir les données renvoyées.

  1. Importer les dépendances
    Dans client/main.go, nous devons d'abord importer les dépendances associées, y compris gRPC, le contexte et la synchronisation, etc. :
package main

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

    "google.golang.org/grpc"
    pb "myproject/api" // 导入生成的代码
)
  1. Créer une connexion
    Dans la fonction principale, nous devons créer un connexion avec le serveur. Les connexions peuvent être créées à l'aide de la fonction grpc.Dial. L'exemple de code est le suivant : 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来等待所有的并发请求完成。

三、创建服务端
接下来我们将开始编写服务端的代码,用于接收客户端的请求并返回处理后的数据。

  1. 导入依赖
    在server/main.go中,我们首先需要导入相关的依赖,包括gRPC、log和net等:
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)

package main

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

Dans le code ci-dessus, nous utilisons d'abord la fonction grpc.Dial pour créer une connexion avec le serveur. Le mode de connexion non sécurisée (Insecure) est utilisé ici pour simplifier l'exemple. Dans les applications pratiques, il est recommandé d'utiliser le mode de connexion sécurisée (Secure).

Ensuite, nous avons créé une instance MyServiceClient pour appeler les méthodes côté serveur.

Ensuite, nous utilisons sync.WaitGroup pour coordonner les demandes simultanées. Dans la boucle, nous créons une fonction anonyme pour lancer des requêtes simultanées. Dans chaque requête exécutée simultanément, nous créons un contexte et un objet de requête, puis appelons la méthode côté serveur GetData.

Enfin, nous utilisons wg.Wait pour attendre que toutes les requêtes simultanées se terminent.

3. Créez le serveur

Ensuite, nous commencerons à écrire le code du serveur pour recevoir la demande du client et renvoyer les données traitées.

Importer les dépendances

Dans server/main.go, nous devons d'abord importer les dépendances associées, y compris gRPC, log et net, etc. :

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)
}
🎜🎜Implémenter l'interface🎜Dans handler.go, nous devons implémenter le interface de services définie. L'exemple de code est le suivant : 🎜🎜
go run server/main.go
go run client/main.go
🎜Ici, nous implémentons la structure MyServiceServer et implémentons la méthode GetData. Dans cette méthode, nous traitons d’abord la demande, puis construisons la réponse et la renvoyons. 🎜🎜🎜Créer un service🎜Dans la fonction principale, nous devons créer et démarrer le service gRPC. Les services peuvent être créés à l'aide de la fonction grpc.NewServer. L'exemple de code est le suivant : 🎜🎜
2021/01/01 15:00:00 data: Hello, 1
🎜Dans le code ci-dessus, nous utilisons d'abord la fonction net.Listen pour créer un écouteur TCP et spécifier le port d'écoute comme 50051. 🎜🎜Ensuite, nous utilisons la fonction grpc.NewServer pour créer un service gRPC, et utilisons la méthode pb.RegisterMyServiceServer pour enregistrer le service que nous avons implémenté dans le service. 🎜🎜Enfin, nous utilisons la méthode s.Serve(lis) pour démarrer le service et écouter le port spécifié. 🎜🎜4. Démonstration d'un exemple de code🎜 Ci-dessous, nous utilisons un exemple complet pour démontrer comment utiliser gRPC pour implémenter la transmission simultanée de données dans Golang. 🎜🎜Tout d'abord, nous devons ajouter le code suivant dans server/main.go : 🎜rrreee🎜Ensuite, ajoutez le code suivant dans client/main.go : 🎜rrreee🎜Enfin, nous pouvons exécuter la commande suivante dans le répertoire racine du projet pour démarrer le serveur et le client : 🎜rrreee🎜Les résultats d'exécution sont les suivants : 🎜rrreee🎜On peut voir que le serveur a reçu avec succès la demande du client et a renvoyé les données traitées. 🎜🎜Résumé : 🎜Cet article présente les meilleures pratiques sur la façon d'utiliser gRPC pour implémenter le transfert de données simultané dans Golang. En créant une structure de projet appropriée, en créant des connexions, en implémentant des interfaces de service et en démarrant des services, nous pouvons facilement utiliser gRPC pour la transmission simultanée de données. J'espère que cet article pourra aider les développeurs qui utilisent ou utiliseront gRPC. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn