gRPC, एक ओपन-सोर्स रिमोट प्रोसीजर कॉल (RPC) फ्रेमवर्क है, जो सेवाओं के बीच कुशल और स्केलेबल संचार को सक्षम बनाता है। gRPC का एक महत्वपूर्ण पहलू समय-सीमाओं, अनुरोध समय-सीमाओं और कस्टम संरचनाओं सहित संदर्भ के प्रसार का प्रबंधन है।
इन तंत्रों को समझने से यह सुनिश्चित करने में मदद मिलती है कि सेवाएं शीघ्र प्रतिक्रिया दें, संसाधनों को उचित समय सीमा से अधिक समय तक चलने वाले कार्यों पर बर्बाद न किया जाए, तथा कस्टम मेटाडेटा को प्रभावी ढंग से प्रेषित किया जाए।
gRPC में समय-सीमा वह अधिकतम समय निर्दिष्ट करती है जिसके भीतर किसी ऑपरेशन को पूरा किया जाना चाहिए। यदि ऑपरेशन इस समय-सीमा के भीतर पूरा नहीं होता है, तो इसे स्वचालित रूप से समाप्त कर दिया जाएगा। समय-सीमा यह सुनिश्चित करने के लिए आवश्यक है कि सिस्टम संसाधन अनुत्तरदायी या धीमी सेवाओं के कारण अनिश्चित काल तक बंधे न रहें।
अनुरोध टाइमआउट वह अवधि है जिसके दौरान क्लाइंट सर्वर से प्रतिक्रिया के लिए प्रतीक्षा करने को तैयार रहता है। यदि सर्वर इस अवधि के भीतर प्रतिक्रिया नहीं देता है, तो अनुरोध निरस्त कर दिया जाता है। यह तंत्र क्लाइंट को प्रतिक्रिया के लिए अनिश्चित काल तक प्रतीक्षा करने से बचाता है।
gRPC क्लाइंट और सर्वर दोनों तरफ़ डेडलाइन सेट करने और टाइमआउट का अनुरोध करने के लिए लचीले विकल्प प्रदान करता है। यहाँ बताया गया है कि आप इसे Go में कैसे कर सकते हैं:
import ( "context" "log" "time" "google.golang.org/grpc" pb "path/to/your/protobuf/package" ) func main() { conn, err := grpc.Dial("server_address", grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() client := pb.NewYourServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() resp, err := client.YourMethod(ctx, &pb.YourRequest{}) if err != nil { log.Fatalf("could not call method: %v", err) } log.Printf("Response: %v", resp) }
सर्वर साइड पर, gRPC आपको समय-सीमा लागू करने और ऐसे परिदृश्यों को संभालने की अनुमति देता है जहां क्लाइंट द्वारा निर्दिष्ट समय-सीमा पार हो जाती है:
import ( "context" "log" "net" "time" "google.golang.org/grpc" pb "path/to/your/protobuf/package" ) type server struct { pb.UnimplementedYourServiceServer } func (s *server) YourMethod(ctx context.Context, req *pb.YourRequest) (*pb.YourResponse, error) { select { case <-time.After(10 * time.Second): return &pb.YourResponse{}, nil case <-ctx.Done(): return nil, ctx.Err() } } func main() { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer() pb.RegisterYourServiceServer(s, &server{}) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }
gRPC में संदर्भ के माध्यम से कस्टम संरचनाएँ भेजने के लिए, आपको संदर्भ में संलग्न करने से पहले डेटा को क्रमबद्ध करना होगा और फिर प्राप्त करने वाले छोर पर इसे अक्रमबद्ध करना होगा। इसमें आपके कस्टम संरचनाओं को एक ऐसे प्रारूप में परिवर्तित करना शामिल है जिसे नेटवर्क पर प्रसारित किया जा सकता है, जैसे JSON या प्रोटोकॉल बफ़र्स, और फिर इस क्रमबद्ध डेटा को संदर्भ मेटाडेटा में जोड़ना।
type CustomStruct struct { Field1 string Field2 int }
चरण 2: संरचना को क्रमबद्ध करें
import ( "context" "encoding/json" "fmt" "google.golang.org/grpc/metadata" ) func serializeCustomStruct(customStruct CustomStruct) (string, error) { data, err := json.Marshal(customStruct) if err != nil { return "", err } return string(data), nil }
चरण 3: संदर्भ से जुड़ें
func attachCustomStructToContext(ctx context.Context, customStruct CustomStruct) (context.Context, error) { serializedData, err := serializeCustomStruct(customStruct) if err != nil { return nil, err } md := metadata.Pairs("custom-struct", serializedData) ctx = metadata.NewOutgoingContext(ctx, md) return ctx, nil }
चरण 4: संचारित करें
func main() { conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() client := pb.NewYourServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() customStruct := CustomStruct{Field1: "value1", Field2: 42} ctx, err = attachCustomStructToContext(ctx, customStruct) if err != nil { log.Fatalf("could not attach custom struct to context: %v", err) } resp, err := client.YourMethod(ctx, &pb.YourRequest{}) if err != nil { log.Fatalf("could not call method: %v", err) } log.Printf("Response: %v", resp) }
चरण 5: सर्वर पर एक्सट्रेक्ट और डिसेरीलाइज़ करें
func deserializeCustomStruct(data string) (CustomStruct, error) { var customStruct CustomStruct err := json.Unmarshal([]byte(data), &customStruct) if err != nil { return CustomStruct{}, err } return customStruct, nil } func extractCustomStructFromContext(ctx context.Context) (CustomStruct, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return CustomStruct{}, fmt.Errorf("no metadata found in context") } serializedData := md["custom-struct"] if len(serializedData) == 0 { return CustomStruct{}, fmt.Errorf("no custom struct found in metadata") } return deserializeCustomStruct(serializedData[0]) } func (s *server) YourMethod(ctx context.Context, req *pb.YourRequest) (*pb.YourResponse, error) { customStruct, err := extractCustomStructFromContext(ctx) if err != nil { return nil, err } log.Printf("Received custom struct: %+v", customStruct) select { case <-time.After(10 * time.Second): return &pb.YourResponse{}, nil case <-ctx.Done(): return nil, ctx.Err() } }
सभी gRPC कॉल में कस्टम संरचनाओं सहित संदर्भ प्रसार को संभालने के लिए, आप इंटरसेप्टर का उपयोग कर सकते हैं। इंटरसेप्टर मिडलवेयर हैं जो अनुरोधों और प्रतिक्रियाओं को संसाधित करते हैं, लॉगिंग, मॉनिटरिंग और संदर्भ मेटाडेटा हैंडलिंग जैसी कार्यक्षमता जोड़ते हैं।
विभिन्न प्रकार के RPC कॉलों को प्रबंधित करने के लिए आपको यूनरी और स्ट्रीमिंग दोनों इंटरसेप्टर की आवश्यकता होती है:
क्लाइंट-साइड यूनरी इंटरसेप्टर:
func unaryClientInterceptor( ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption, ) error { customStruct, ok := ctx.Value("customStruct").(CustomStruct) if ok { ctx, err := attachCustomStructToContext(ctx, customStruct) if err != nil { return err } } return invoker(ctx, method, req, reply, cc, opts...) }
सर्वर-साइड यूनरी इंटरसेप्टर:
func unaryServerInterceptor( ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler, ) (interface{}, error) { customStruct, err := extractCustomStructFromContext(ctx) if err != nil { return nil, err } ctx = context.WithValue(ctx, "customStruct", customStruct) return handler(ctx, req) }
क्लाइंट-साइड स्ट्रीमिंग इंटरसेप्टर:
func streamClientInterceptor( ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption, ) (grpc.ClientStream, error) { customStruct, ok := ctx.Value("customStruct").(CustomStruct) if ok { ctx, err := attachCustomStructToContext(ctx, customStruct) if err != nil { return nil, err } } return
सर्वर-साइड स्ट्रीमिंग इंटरसेप्टर:
import ( "context" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) // StreamServerInterceptor handles server-side streaming func streamServerInterceptor( srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler, ) error { ctx := ss.Context() customStruct, err := extractCustomStructFromContext(ctx) if err != nil { return err } // Add custom struct to context for server handling newCtx := context.WithValue(ctx, "customStruct", customStruct) wrapped := grpc_middleware.WrapServerStream(ss) wrapped.WrappedContext = newCtx // Handle the request return handler(srv, wrapped) } // Example of using the interceptor in a gRPC server setup func main() { lis, err := net.Listen("tcp", ":50051") if err != nil { log.Fatalf("failed to listen: %v", err) } // Register the interceptors server := grpc.NewServer( grpc.UnaryInterceptor(unaryServerInterceptor), grpc.StreamInterceptor(streamServerInterceptor), ) // Register your gRPC service implementations here pb.RegisterYourServiceServer(server, &yourServiceServer{}) if err := server.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }
यूनेरी और स्ट्रीमिंग इंटरसेप्टर बनाकर और पंजीकृत करके, आप यह सुनिश्चित कर सकते हैं कि कस्टम संरचनाओं सहित संदर्भ प्रसार, सभी gRPC कॉल में लगातार संभाला जाता है। यह दृष्टिकोण सुनिश्चित करता है कि आपका कस्टम मेटाडेटा ठीक से प्रबंधित और प्रसारित किया जाता है, जिससे आप मजबूत और लचीली gRPC सेवाएँ बना सकते हैं।