Introduction à Protobuf
Protobuf est l'abréviation de Protocol Buffers. C'est un langage de description de données développé par Google. Lorsqu'il a été ouvert en 2008, il était similaire à XML, JSON et à d'autres langages de description. Il a généré du code et réalisé la fonction des données structurées à travers les outils d'accompagnement, mais nous sommes plus préoccupés par Ce qui est Protobuf comme langage de description de la spécification d'interface peut être utilisé comme un outil de base pour concevoir une interface RPC cross-language sécurisée.
Débuter avec Protobuf
Pour ceux qui n'ont pas utilisé Protobuf, il est recommandé de comprendre d'abord l'utilisation de base du site officiel. Ci-dessous, nous utilisons Protobuf et RPC ensemble pour utiliser Protobuf afin de garantir les spécifications et la sécurité de l'interface RPC. L'unité de données la plus élémentaire de Protobuf est le message, qui est similaire à l'existence d'une structure en langage Go. Un message ou d'autres membres de type de données de base peuvent être imbriqués dans le message.
Exemple simple
Répertoire de fichiers
--- rpc_demo │ client.go │ go.mod │ go.sum │ service.go │ └─proto hello.pb.go hello.proto
Créez d'abord un répertoire proto sous le répertoire du projet pour stocker le fichier proto et créez un simple fichier helllo.proto:
syntax = "proto3"; // Déclarer la syntaxe package proto; // Peut être personnalisé en fonction de la structure de votre package actuel message String {// Le mot clé message définit un type String et il n'y a qu'un seul membre de valeur du type string. Le numéro de membre est 1 au lieu du nom. C'est pourquoi le protobuf est petit et d'autres langages de description de données (json, xml) sont identifiés par le nom du membre et Portobuf est numéroté de façon unique, mais il n'est pas facile de s'y référer valeur de chaîne = 1; }
Entrez dans le répertoire du fichier proto et utilisez la commande suivante pour générer le script de langue correspondant: protocol --go_out =. Hello.proto Générez le fichier d'interface correspondant. Ensuite, nous pouvons écrire le code serveur et client en fonction du fichier go généré, et écrire d'abord le code serveur.
Remarque: Le code de base de Protobuf est écrit en C ++ et le langage Go n'est pas pris en charge dans le compilateur officiel de protobuf. Pour générer le code go correspondant basé sur le fichier hello.proto, nous devons télécharger le plugin correspondant: aller chercher github.com/ l'installation de la commande golang / protobuf / protocole-gen-go, et enfin via le protocole --go_out =. hello.proto générera le code du fichier go correspondant
paquet principal importer ( "Journal" "net" "net / rpc" "rpc_protobuf / proto" ) tapez la structure HelloService {} // La méthode spécifique de mise en œuvre du service rpc, faites attention aux paramètres acceptés pour répondre aux exigences de la norme d'interface, car l'appel en cours est une structure, donc les paramètres du pointeur func (p * HelloService) Erreur Hello (demande * proto.String, réponse * proto.String) { reply.Value = "hello:" + request.GetValue () retour nul } func main () { // Enregistrer le service rpc rpc.RegisterName ("HelloService", nouveau (HelloService)) // Surveiller le service TCP listenr, err: = net.Listen ("tcp", ": 1234") si err! = nil { log.Fatal ("Erreur d'écoute:", err) } log.Println ("démarrage du service ....") // Acceptez la demande de données pertinente et joignez-la au service rpc conn, err: = listenr.Accept () si err! = nil { log.Fatal ("Accepter l'erreur", err) } rpc.ServeConn (conn) }
Enfin, écrivez le code client:
paquet principal importer ( "fmt" "Journal" "net / rpc" "rpc_protobuf / proto" ) func main () { // Composez le service de port 1234 à l'extrémité locale client, err: = rpc.Dial ("tcp", "localhost: 1234") si err! = nil { log.Fatal ("Erreur TCP:", err) } // Adoptez uniformément les paramètres fournis par l'interface et les paramètres de requête var answer = & proto.String {} var param = & proto.String { Valeur: "Wang", } // Appeler le service à distance err = client.Call ("HelloService.Hello", & param, & reply) si err! = nil { log.Fatal (err) } fmt.Println (réponse) }
(Remarque: lorsque vous utilisez l'EDI Goland, si nous utilisons le mod go, activez le mode d'intégration et de vente Go Moudle (vgo) dans l'option Go modules dans le paramètre doit être ajusté en cas de problème avec le package de guide)
Nous pouvons démarrer le serveur et le client pour voir les résultats correspondants. Ici, nous utilisons simplement rpc et protobuf. Plus tard, nous vous expliquerons comment télécharger le protocole, protobuf, etc.
Analyse:
Ci-dessous, nous analysons le fichier hello.pb.go généré (partie interception):
package proto // nom du package .... // Implémentation d'un type de caractère, généré selon le fichier proto type String struct { Chaîne de valeur `protobuf:" octets, 1, opt, nom = valeur, proto3 "json:" valeur, omitempty "` XXX_NoUnkeyedLiteral struct {} `json:" - "` XXX_unrecognized [] octet `json:" - "` XXX_sizecache int32 `json:" - "` } .... // Utilisé pour obtenir la valeur du type String, le service peut être utilisé pour obtenir des paramètres via cette méthode, chaque membre aura une méthode Get func (m * String) GetValue () string { si m! = nil { return m.Value } revenir "" }
La vraie valeur
Nous avons expliqué ci-dessus qu'en combinant rpc et protobuf à travers des opérations complexes, nous utilisons protobuf pour définir les paramètres d'entrée et de sortie et la structure de l'implémentation, mais avez-vous constaté qu'il n'y a pas de fonction de service dans le hello.pb.go généré Seulement avec quelques contraintes d'interface, pouvons-nous également définir les services en RPC dans Protobuf? De cette façon, nous avons réalisé l' interface de service RPC indépendante de la langue avec Protobuf, qui est la vraie valeur.
Cela fait partie de l'étendue de la personnalisation de Portobuf. Si vous êtes intéressé, vous pouvez lire "Go Language Advanced Programming". Certains des articles précédents sont également tirés de ce livre.