gRPC, একটি ওপেন-সোর্স রিমোট প্রসিডিওর কল (RPC) ফ্রেমওয়ার্ক, পরিষেবাগুলির মধ্যে দক্ষ এবং মাপযোগ্য যোগাযোগ সক্ষম করে। জিআরপিসির একটি গুরুত্বপূর্ণ দিক হল সময়সীমার ব্যবস্থাপনা, অনুরোধের সময়সীমা, এবং কাস্টম কাঠামো সহ প্রসঙ্গ প্রচার করা।
এই প্রক্রিয়াগুলি বোঝা নিশ্চিত করতে সাহায্য করে যে পরিষেবাগুলি অবিলম্বে সাড়া দেয়, একটি যুক্তিসঙ্গত সময়সীমা অতিক্রম করে এমন ক্রিয়াকলাপগুলিতে সংস্থানগুলি নষ্ট হয় না এবং কাস্টম মেটাডেটা কার্যকরভাবে প্রেরণ করা হয়।
জিআরপিসি-তে একটি সময়সীমা সর্বাধিক সময় নির্দিষ্ট করে যার মধ্যে একটি অপারেশন সম্পূর্ণ করতে হবে। এই সময়সীমার মধ্যে অপারেশন সম্পন্ন না হলে, এটি স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যাবে। অপ্রতিক্রিয়াশীল বা ধীর পরিষেবার কারণে সিস্টেম সংস্থানগুলি অনির্দিষ্টকালের জন্য বাঁধা না হয় তা নিশ্চিত করার জন্য সময়সীমা অপরিহার্য।
একটি অনুরোধের সময়সীমা এমন একটি সময়কাল যা একজন ক্লায়েন্ট সার্ভার থেকে একটি প্রতিক্রিয়ার জন্য অপেক্ষা করতে ইচ্ছুক। এই সময়ের মধ্যে সার্ভার সাড়া না দিলে, অনুরোধটি বাতিল করা হয়। এই প্রক্রিয়াটি ক্লায়েন্টকে একটি প্রতিক্রিয়ার জন্য অনির্দিষ্টকালের জন্য অপেক্ষা করা থেকে রক্ষা করে।
ক্লায়েন্ট এবং সার্ভার উভয় দিকেই সময়সীমা নির্ধারণ এবং সময়সীমার অনুরোধ করার জন্য 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) } }
জিআরপিসি-তে কনটেক্সট এর মাধ্যমে কাস্টম স্ট্রাকচার পাঠানোর জন্য, আপনাকে প্রেক্ষাপটে ডেটা সংযুক্ত করার আগে সিরিয়ালাইজ করতে হবে এবং তারপর রিসিভিং এন্ডে ডিসিরিয়ালাইজ করতে হবে। এতে আপনার কাস্টম স্ট্রাকচারগুলিকে এমন একটি বিন্যাসে রূপান্তর করা জড়িত যা নেটওয়ার্কের মাধ্যমে প্রেরণ করা যেতে পারে, যেমন 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 পরিষেবাগুলি তৈরি করতে দেয়।