"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > आरपीसी एक्शन ईपीयू प्रोटोबफ़ का उपयोग करना और एक कस्टम प्लगइन बनाना

आरपीसी एक्शन ईपीयू प्रोटोबफ़ का उपयोग करना और एक कस्टम प्लगइन बनाना

2024-09-12 को प्रकाशित
ब्राउज़ करें:160

RPC Action EPUsing Protobuf and Creating a Custom Plugin

पिछले लेख में, मैंने नेट/आरपीसी पैकेज का उपयोग करके एक सरल आरपीसी इंटरफ़ेस लागू किया और गोलंग की कुछ मूल बातें सीखने के लिए नेट/आरपीसी और जेएसओएन एन्कोडिंग के साथ आने वाले गोब एन्कोडिंग को आज़माया। आरपीसी. इस पोस्ट में, मैं नेट/आरपीसी को प्रोटोबफ के साथ जोड़ूंगा और कोड उत्पन्न करने में हमारी सहायता के लिए अपना प्रोटोबफ प्लगइन बनाऊंगा, तो चलिए शुरू करते हैं।

यह लेख पहली बार मीडियम एमपीपी योजना में प्रकाशित हुआ था। यदि आप मीडियम उपयोगकर्ता हैं, तो कृपया मुझे मीडियम पर फ़ॉलो करें। आपका बहुत-बहुत धन्यवाद।

हमने अपने काम के दौरान जीआरपीसी और प्रोटोबफ़ का उपयोग किया होगा, लेकिन वे बाध्य नहीं हैं। GRPC को JSON का उपयोग करके एन्कोड किया जा सकता है, और प्रोटोबफ़ को अन्य भाषाओं में लागू किया जा सकता है।

प्रोटोकॉल बफ़र्स (Protobuf) एक मुफ़्त और ओपन-सोर्स क्रॉस-प्लेटफ़ॉर्म डेटा प्रारूप है जिसका उपयोग संरचित डेटा को क्रमबद्ध करने के लिए किया जाता है। यह ऐसे प्रोग्राम विकसित करने में उपयोगी है जो नेटवर्क पर एक दूसरे के साथ संचार करते हैं या डेटा संग्रहीत करते हैं। विधि में एक इंटरफ़ेस विवरण भाषा शामिल होती है जो कुछ डेटा की संरचना का वर्णन करती है और एक प्रोग्राम जो संरचित डेटा का प्रतिनिधित्व करने वाले बाइट्स की एक स्ट्रीम उत्पन्न करने या पार्स करने के लिए उस विवरण से स्रोत कोड उत्पन्न करता है।

प्रोटोबफ़ का उपयोग करने का एक उदाहरण

सबसे पहले हम एक प्रोटो फ़ाइल hello-service.proto लिखते हैं जो एक संदेश "स्ट्रिंग" को परिभाषित करता है

syntax = "proto3";
package api;
option  go_package="api";

message String {
  string value = 1;
}

फिर संदेश स्ट्रिंग के लिए गो कोड उत्पन्न करने के लिए प्रोटोक उपयोगिता का उपयोग करें

protoc --go_out=. hello-service.proto

फिर हम प्रोटोबफ़ फ़ाइल द्वारा उत्पन्न स्ट्रिंग का उपयोग करने के लिए हैलो फ़ंक्शन के तर्कों को संशोधित करते हैं।

type HelloServiceInterface = interface {  
    Hello(request api.String, reply *api.String) error  
}  

इसका उपयोग करना पहले से अलग नहीं है, यहां तक ​​कि, यह सीधे स्ट्रिंग का उपयोग करने जितना सुविधाजनक नहीं है। तो हमें प्रोटोबफ़ का उपयोग क्यों करना चाहिए? जैसा कि मैंने पहले कहा था, भाषा-स्वतंत्र आरपीसी सेवा इंटरफेस और संदेशों को परिभाषित करने के लिए प्रोटोबफ का उपयोग करना, और फिर विभिन्न भाषाओं में कोड उत्पन्न करने के लिए प्रोटोक टूल का उपयोग करना, जहां इसका वास्तविक मूल्य निहित है । उदाहरण के लिए, gRPC कोड जनरेट करने के लिए आधिकारिक प्लगइन protoc-gen-go का उपयोग करें।

protoc --go_out=plugins=grpc. hello-service.proto

प्रोटोक के लिए प्लगइन सिस्टम

प्रोटोबफ़ फ़ाइलों से कोड उत्पन्न करने के लिए, हमें प्रोटोक स्थापित करना होगा, लेकिन प्रोटोक को यह नहीं पता है कि हमारी लक्ष्य भाषा क्या है, इसलिए हमें कोड उत्पन्न करने में सहायता के लिए प्लगइन्स की आवश्यकता है। प्रोटोक का प्लगइन सिस्टम कैसे काम करता है? उदाहरण के तौर पर उपरोक्त जीआरपीसी को लें।

यहां एक --go_out पैरामीटर है। चूँकि जिस प्लगइन को हम कॉल कर रहे हैं वह protoc-gen-go है, पैरामीटर को go_out कहा जाता है; यदि नाम XXX था, तो पैरामीटर को XXX_out कहा जाएगा।

जब प्रोटोक चल रहा होता है, तो यह पहले प्रोटोबफ़ फ़ाइल को पार्स करेगा और प्रोटोकॉल बफ़र्स-एन्कोडेड वर्णनात्मक डेटा का एक सेट उत्पन्न करेगा। यह पहले यह निर्धारित करेगा कि गो प्लगइन प्रोटोक में शामिल है या नहीं, और फिर यह $PATH में प्रोटोक-जेन-गो को खोजने का प्रयास करेगा, और यदि यह इसे नहीं ढूंढ पाता है, तो यह एक त्रुटि की रिपोर्ट करेगा, और फिर यह प्रोटोक-जेन-गो चलाएगा। protoc-gen-go कमांड और विवरण डेटा को stdin के माध्यम से प्लगइन कमांड पर भेजता है। प्लगइन फ़ाइल सामग्री उत्पन्न करने के बाद, यह विशिष्ट फ़ाइल उत्पन्न करने के लिए प्रोटोक को बताने के लिए प्रोटोकॉल बफ़र्स एन्कोडेड डेटा को स्टडआउट में इनपुट करता है।

प्लगइन्स = जीआरपीसी एक प्लगइन है जो इसे लागू करने के लिए प्रोटोक-जेन-गो के साथ आता है। यदि आप इसका उपयोग नहीं करते हैं, तो यह केवल गो में एक संदेश उत्पन्न करेगा, लेकिन आप जीआरपीसी-संबंधित कोड उत्पन्न करने के लिए इस प्लगइन का उपयोग कर सकते हैं।

एक प्रोटोक प्लगइन को अनुकूलित करें

यदि हम प्रोटोबफ़ में हैलो इंटरफ़ेस टाइमिंग जोड़ते हैं, तो क्या हम सीधे कोड उत्पन्न करने के लिए एक प्रोटोक प्लगइन को अनुकूलित कर सकते हैं?

syntax = "proto3";  
package api;  
option  go_package="./api";  
service HelloService {  
  rpc Hello (String) returns (String) {}  
}  
message String {  
  string value = 1;
}

उद्देश्य

इस लेख के लिए, मेरा लक्ष्य एक प्लगइन बनाना था जिसका उपयोग आरपीसी सर्वर-साइड और क्लाइंट-साइड कोड उत्पन्न करने के लिए किया जाएगा जो कुछ इस तरह दिखेगा।

// HelloService_rpc.pb.go
type HelloServiceInterface interface {  
    Hello(String, *String) error  
}  

func RegisterHelloService(  
    srv *rpc.Server, x HelloServiceInterface,  
) error {  
    if err := srv.RegisterName("HelloService", x); err != nil {  
       return err  
    }  
    return nil  
}  

type HelloServiceClient struct {  
    *rpc.Client  
}  

var _ HelloServiceInterface = (*HelloServiceClient)(nil)  

func DialHelloService(network, address string) (  
    *HelloServiceClient, error,  
) {  
    c, err := rpc.Dial(network, address)  
    if err != nil {  
       return nil, err  
    }  
    return &HelloServiceClient{Client: c}, nil  
}  

func (p *HelloServiceClient) Hello(  
    in String, out *String,  
) error {  
    return p.Client.Call("HelloService.Hello", in, out)  
}

इससे हमारा व्यवसाय कोड इस प्रकार बदल जाएगा

// service
func main() {  
    listener, err := net.Listen("tcp", ":1234")  
    if err != nil {  
       log.Fatal("ListenTCP error:", err)  
    }  
    _ = api.RegisterHelloService(rpc.DefaultServer, new(HelloService))  
    for {  
       conn, err := listener.Accept()  
       if err != nil {  
          log.Fatal("Accept error:", err)  
       }  
       go rpc.ServeConn(conn)  
    }  
}  

type HelloService struct{}  

func (p *HelloService) Hello(request api.String, reply *api.String) error {  
    log.Println("HelloService.proto Hello")  
    *reply = api.String{Value: "Hello:"   request.Value}  
    return nil  
}
// client.go
func main() {  
    client, err := api.DialHelloService("tcp", "localhost:1234")  
    if err != nil {  
       log.Fatal("net.Dial:", err)  
    }  
    reply := &api.String{}  
    err = client.Hello(api.String{Value: "Hello"}, reply)  
    if err != nil {  
       log.Fatal(err)  
    }  
    log.Println(reply)  
}

जनरेट किए गए कोड के आधार पर, हमारा कार्यभार पहले से ही बहुत कम है और त्रुटि की संभावना पहले से ही बहुत कम है। का शुभारंभ।

उपरोक्त एपीआई कोड के आधार पर, हम एक टेम्पलेट फ़ाइल निकाल सकते हैं:

const tmplService = `  
import (  
    "net/rpc")  
type {{.ServiceName}}Interface interface {  
func Register{{.ServiceName}}(  
    if err := srv.RegisterName("{{.ServiceName}}", x); err != nil {        return err    }    return nil}  
    *rpc.Client}  
func Dial{{.ServiceName}}(network, address string) (  
{{range $_, $m := .MethodList}}  
    return p.Client.Call("{{$root.ServiceName}}.{{$m.MethodName}}", in, out)}  
`

पूरा टेम्प्लेट स्पष्ट है, और इसमें कुछ प्लेसहोल्डर हैं, जैसे मेथडनेम, सर्विसनेम, आदि, जिन्हें हम बाद में कवर करेंगे।

प्लग-इन कैसे विकसित करें?

Google ने गो भाषा एपीआई 1 जारी किया, जो एक नया पैकेज google.golang.org/protobuf/compile R/protogen पेश करता है, जो प्लगइन्स विकास की कठिनाई को काफी कम कर देता है:

  1. सबसे पहले, हम एक गो भाषा प्रोजेक्ट बनाते हैं, जैसे कि प्रोटोक-जेन-गो-एसपीपीआरपीसी
  2. फिर हमें एक protogen.Options को परिभाषित करने की आवश्यकता है, फिर इसकी रन विधि को कॉल करें, और एक func(*protogen.Plugin) त्रुटि कॉलबैक पास करें। यह मुख्य प्रक्रिया कोड का अंत है।
  3. हम प्रोटोजेन.ऑप्शंस का पैरामफंक पैरामीटर भी सेट कर सकते हैं, ताकि प्रोटोजेन स्वचालित रूप से हमारे लिए कमांड लाइन द्वारा पारित पैरामीटर को पार्स कर सके। मानक इनपुट से प्रोटोबफ जानकारी को पढ़ने और डिकोड करने, इनपुट जानकारी को प्रोटोबफ में एन्कोड करने और स्टडआउट लिखने जैसे संचालन सभी प्रोटोजन द्वारा नियंत्रित किए जाते हैं। कोड जनरेशन लॉजिक को लागू करने के लिए हमें protogen.Plugin के साथ इंटरैक्ट करना होगा।

प्रत्येक सेवा के लिए सबसे महत्वपूर्ण बात सेवा का नाम है, और फिर प्रत्येक सेवा में तरीकों का एक सेट होता है। सेवा द्वारा परिभाषित विधि के लिए, सबसे महत्वपूर्ण बात विधि का नाम, साथ ही इनपुट पैरामीटर का नाम और आउटपुट पैरामीटर प्रकार है। आइए सबसे पहले सेवा की मेटा जानकारी का वर्णन करने के लिए एक सर्विसडेटा को परिभाषित करें:

// ServiceData 
type ServiceData struct {  
    PackageName string  
    ServiceName string  
    MethodList  []Method  
}
// Method 
type Method struct {  
    MethodName     string  
    InputTypeName  string  
    OutputTypeName string  
}

फिर मुख्य तर्क, और कोड जनरेशन तर्क, और अंत में कोड उत्पन्न करने के लिए tmpl को कॉल आता है।

func main() {  
    protogen.Options{}.Run(func(gen *protogen.Plugin) error {  
       for _, file := range gen.Files {  
          if !file.Generate {  
             continue  
          }  
          generateFile(gen, file)  
       }  
       return nil  
    })  
}  

// generateFile function definition
func generateFile(gen *protogen.Plugin, file *protogen.File) {  
    filename := file.GeneratedFilenamePrefix   "_rpc.pb.go"  
    g := gen.NewGeneratedFile(filename, file.GoImportPath)  
    tmpl, err := template.New("service").Parse(tmplService)  
    if err != nil {  
       log.Fatalf("Error parsing template: %v", err)  
    }  
    packageName := string(file.GoPackageName)  
// Iterate over each service to generate code
    for _, service := range file.Services {  
       serviceData := ServiceData{  
          ServiceName: service.GoName,  
          PackageName: packageName,  
       }  
       for _, method := range service.Methods {  
          inputType := method.Input.GoIdent.GoName  
          outputType := method.Output.GoIdent.GoName  

          serviceData.MethodList = append(serviceData.MethodList, Method{  
             MethodName:     method.GoName,  
             InputTypeName:  inputType,  
             OutputTypeName: outputType,  
          })  
       }  
// Perform template rendering
       err = tmpl.Execute(g, serviceData)  
       if err != nil {  
          log.Fatalf("Error executing template: %v", err)  
       }  
    }  
}

डीबग प्लगइन

अंत में, हम संकलित बाइनरी निष्पादन फ़ाइल protoc-gen-go-spprpc को $PATH में डालते हैं, और फिर जो कोड हम चाहते हैं उसे उत्पन्न करने के लिए protoc चलाते हैं।

protoc --go_out=.. --go-spprpc_out=.. HelloService.proto

क्योंकि protoc-gen-go-spprpc को चलाने के लिए protoc पर निर्भर रहना पड़ता है, इसलिए इसे डीबग करना थोड़ा मुश्किल है। हम इसका उपयोग कर सकते हैं

fmt.Fprintf(os.Stderr, "Fprintln: %v\n", err)

डीबग करने के लिए त्रुटि लॉग को प्रिंट करने के लिए।

सारांश

इस लेख में बस इतना ही है। हमने पहले प्रोटोबफ का उपयोग करके एक आरपीसी कॉल लागू की और फिर कोड उत्पन्न करने में हमारी सहायता के लिए एक प्रोटोबफ प्लगइन बनाया। यह हमारे लिए प्रोटोबफ़ आरपीसी सीखने का द्वार खोलता है, और जीआरपीसी की संपूर्ण समझ के लिए हमारा मार्ग है। मुझे उम्मीद है कि हर कोई इस तकनीक में महारत हासिल कर सकता है।

संदर्भ

  1. https://taoshu.in/go/create-protoc-plugin.html
  2. https://chai2010.cn/advanced-go-programming-book/ch4-rpc/ch4-02-pb-intro.html
विज्ञप्ति वक्तव्य यह आलेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/huizhou92/rpc-action-ep2-using-protobuf-and-creating-a-custom-plugin-2j9j?1 यदि कोई उल्लंघन है, तो कृपया स्टडी_गोलंग@163 से संपर्क करें इसे हटाने के लिए .com
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3