gRPC-Python - স্ট্রিমিং দিয়ে শুরু করা

1. ভূমিকা

এই কোডল্যাবে, আপনি একটি ক্লায়েন্ট এবং সার্ভার তৈরি করতে gRPC-Python ব্যবহার করবেন যা পাইথনে লেখা একটি রুট-ম্যাপিং অ্যাপ্লিকেশনের ভিত্তি তৈরি করে।

টিউটোরিয়ালের শেষে, আপনার কাছে একটি ক্লায়েন্ট থাকবে যেটি একটি দূরবর্তী সার্ভারের সাথে সংযোগ করে একটি ক্লায়েন্টের রুটের বৈশিষ্ট্য সম্পর্কে তথ্য পেতে, একটি ক্লায়েন্টের রুটের একটি সারাংশ তৈরি করতে এবং সার্ভার এবং অন্যান্য ক্লায়েন্টদের সাথে ট্রাফিক আপডেটের মতো রুটের তথ্য বিনিময় করতে।

পরিষেবাটি একটি প্রোটোকল বাফার ফাইলে সংজ্ঞায়িত করা হয়েছে, যা ক্লায়েন্ট এবং সার্ভারের জন্য বয়লারপ্লেট কোড তৈরি করতে ব্যবহার করা হবে যাতে তারা একে অপরের সাথে যোগাযোগ করতে পারে, সেই কার্যকারিতা বাস্তবায়নে আপনার সময় এবং প্রচেষ্টা বাঁচাতে পারে।

এই তৈরি করা কোডটি সার্ভার এবং ক্লায়েন্টের মধ্যে যোগাযোগের জটিলতাই নয়, ডেটা সিরিয়ালাইজেশন এবং ডিসিরিয়ালাইজেশনেরও যত্ন নেয়।

আপনি কি শিখবেন

  • একটি পরিষেবা API সংজ্ঞায়িত করতে প্রোটোকল বাফারগুলি কীভাবে ব্যবহার করবেন।
  • স্বয়ংক্রিয় কোড জেনারেশন ব্যবহার করে প্রোটোকল বাফার সংজ্ঞা থেকে কীভাবে একটি জিআরপিসি-ভিত্তিক ক্লায়েন্ট এবং সার্ভার তৈরি করবেন।
  • gRPC-এর সাথে ক্লায়েন্ট-সার্ভার স্ট্রিমিং যোগাযোগের একটি বোঝাপড়া।

এই কোডল্যাবের লক্ষ্য হল পাইথন ডেভেলপারদের জন্য যারা gRPC-তে নতুন বা gRPC-এর রিফ্রেশার খুঁজছেন, অথবা অন্য কেউ যারা ডিস্ট্রিবিউটেড সিস্টেম তৈরি করতে আগ্রহী। কোন পূর্ব gRPC অভিজ্ঞতা প্রয়োজন নেই.

2. আপনি শুরু করার আগে

আপনি কি প্রয়োজন হবে

  • Python 3.9 বা উচ্চতর। আমরা পাইথন 3.13 সুপারিশ করি। প্ল্যাটফর্ম-নির্দিষ্ট ইনস্টলেশন নির্দেশাবলীর জন্য, পাইথন সেটআপ এবং ব্যবহার দেখুন। বিকল্পভাবে, uv বা pyenv-এর মতো টুল ব্যবহার করে একটি নন-সিস্টেম পাইথন ইনস্টল করুন।
  • পাইথন প্যাকেজ ইনস্টল করতে pip .
  • venv পাইথন ভার্চুয়াল পরিবেশ তৈরি করতে।

ensurepip এবং venv প্যাকেজগুলি পাইথন স্ট্যান্ডার্ড লাইব্রেরির অংশ এবং সাধারণত ডিফল্টরূপে উপলব্ধ।

যাইহোক, কিছু ডেবিয়ান-ভিত্তিক ডিস্ট্রিবিউশন (উবুন্টু সহ) পাইথন পুনরায় বিতরণ করার সময় তাদের বাদ দিতে পছন্দ করে। প্যাকেজ ইনস্টল করতে, চালান:

sudo apt install python3-pip python3-venv

কোড পান

আপনার শিক্ষাকে স্ট্রিমলাইন করতে, এই কোডল্যাবটি আপনাকে শুরু করতে সাহায্য করার জন্য একটি পূর্ব-নির্মিত সোর্স কোড স্ক্যাফোল্ড অফার করে। নিম্নলিখিত পদক্ষেপগুলি আপনাকে grpc_tools.protoc প্রোটোকল বাফার কম্পাইলার প্লাগইন ব্যবহার করে gRPC কোড তৈরি সহ অ্যাপ্লিকেশনটি সম্পূর্ণ করার জন্য গাইড করবে।

grpc-codelabs

এই কোডল্যাবের জন্য স্ক্যাফোল্ড সোর্স কোড codelabs/grpc-python-streaming/start_here ডিরেক্টরিতে পাওয়া যায়। আপনি যদি নিজে কোডটি প্রয়োগ করতে না চান, তাহলে সম্পূর্ণ সোর্স কোডটি completed ডিরেক্টরিতে পাওয়া যায়।

প্রথমে, কোডল্যাব ওয়ার্কিং ডিরেক্টরি তৈরি করুন এবং এটিতে সিডি করুন:

mkdir grpc-python-streaming && cd grpc-python-streaming

কোডল্যাব ডাউনলোড এবং এক্সট্রাক্ট করুন:

curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/v1.tar.gz \
  | tar xvz --strip-components=4 \
  grpc-codelabs-1/codelabs/grpc-python-streaming/start_here

বিকল্পভাবে, আপনি শুধুমাত্র কোডল্যাব ডিরেক্টরি ধারণকারী .zip ফাইলটি ডাউনলোড করতে পারেন এবং ম্যানুয়ালি আনজিপ করতে পারেন।

3. বার্তা এবং পরিষেবা সংজ্ঞায়িত করুন

আপনার প্রথম ধাপ হল প্রোটোকল বাফার ব্যবহার করে অ্যাপ্লিকেশনটির gRPC পরিষেবা, এর RPC পদ্ধতি এবং এর অনুরোধ এবং প্রতিক্রিয়া বার্তার ধরনগুলিকে সংজ্ঞায়িত করা। আপনার পরিষেবা প্রদান করবে:

  • RPC পদ্ধতিগুলিকে ListFeatures , RecordRoute , এবং RouteChat বলা হয় যা সার্ভার প্রয়োগ করে এবং ক্লায়েন্ট কল করে।
  • বার্তার ধরন Point , Feature , Rectangle , RouteNote , এবং RouteSummary , যা RPC পদ্ধতিতে কল করার সময় ক্লায়েন্ট এবং সার্ভারের মধ্যে আদান-প্রদান করা হয়।

এই RPC পদ্ধতি এবং তাদের বার্তার ধরন সবই প্রদত্ত সোর্স কোডের protos/route_guide.proto ফাইলে সংজ্ঞায়িত করা হবে।

প্রোটোকল বাফারগুলি সাধারণত প্রোটোবাফ হিসাবে পরিচিত। gRPC পরিভাষা সম্পর্কে আরও তথ্যের জন্য, gRPC-এর মূল ধারণা, স্থাপত্য, এবং জীবনচক্র দেখুন।

বার্তার ধরন সংজ্ঞায়িত করুন

সোর্স কোডের protos/route_guide.proto ফাইলে, প্রথমে Point বার্তার ধরনটি সংজ্ঞায়িত করুন। একটি Point একটি মানচিত্রে একটি অক্ষাংশ-দ্রাঘিমাংশ স্থানাঙ্ক জুটিকে প্রতিনিধিত্ব করে। এই কোডল্যাবের জন্য, স্থানাঙ্কের জন্য পূর্ণসংখ্যা ব্যবহার করুন:

message Point {
  int32 latitude = 1;
  int32 longitude = 2;
}

1 এবং 2 নম্বরগুলি message কাঠামোর প্রতিটি ক্ষেত্রের জন্য অনন্য আইডি নম্বর।

এর পরে, Feature বার্তার ধরন সংজ্ঞায়িত করুন। একটি Feature একটি Point দ্বারা নির্দিষ্ট একটি অবস্থানে কোনো কিছুর নাম বা ডাক ঠিকানার জন্য একটি string ক্ষেত্র ব্যবহার করে:

message Feature {
  // The name or address of the feature.
  string name = 1;

  // The point where the feature is located.
  Point location = 2;
}

যাতে একটি এলাকার মধ্যে একাধিক পয়েন্ট একটি ক্লায়েন্টের কাছে স্ট্রিম করা যায়, আপনার একটি Rectangle বার্তার প্রয়োজন হবে যা একটি অক্ষাংশ-দ্রাঘিমাংশের আয়তক্ষেত্রকে প্রতিনিধিত্ব করে, যা দুটি তির্যক বিপরীত বিন্দু lo এবং hi হিসাবে উপস্থাপিত হয়:

message Rectangle {
  // One corner of the rectangle.
  Point lo = 1;

  // The other corner of the rectangle.
  Point hi = 2;
}

এছাড়াও, একটি RouteNote বার্তা যা প্রদত্ত বিন্দুতে প্রেরিত একটি বার্তা প্রতিনিধিত্ব করে:

message RouteNote {
  // The location from which the message is sent.
  Point location = 1;

  // The message to be sent.
  string message = 2;
}

অবশেষে, আপনার একটি RouteSummary বার্তার প্রয়োজন হবে। এই বার্তাটি একটি RecordRoute RPC-এর প্রতিক্রিয়া হিসাবে গৃহীত হয়েছে, যা পরবর্তী বিভাগে ব্যাখ্যা করা হয়েছে। এতে প্রাপ্ত পৃথক পয়েন্টের সংখ্যা, সনাক্ত করা বৈশিষ্ট্যের সংখ্যা এবং প্রতিটি বিন্দুর মধ্যে দূরত্বের ক্রমবর্ধমান সমষ্টি হিসাবে আচ্ছাদিত মোট দূরত্ব রয়েছে।

message RouteSummary {
  // The number of points received.
  int32 point_count = 1;

  // The number of known features passed while traversing the route.
  int32 feature_count = 2;

  // The distance covered in metres.
  int32 distance = 3;

  // The duration of the traversal in seconds.
  int32 elapsed_time = 4;
}

সেবা পদ্ধতি সংজ্ঞায়িত করুন

একটি পরিষেবা সংজ্ঞায়িত করতে, আপনি আপনার .proto ফাইলে একটি নামযুক্ত পরিষেবা নির্দিষ্ট করুন৷ route_guide.proto ফাইলটিতে RouteGuide নামে একটি service কাঠামো রয়েছে যা অ্যাপ্লিকেশনটির পরিষেবা দ্বারা প্রদত্ত এক বা একাধিক পদ্ধতিকে সংজ্ঞায়িত করে৷

যখন আপনি আপনার পরিষেবার সংজ্ঞার মধ্যে RPC পদ্ধতিগুলি সংজ্ঞায়িত করেন, আপনি তাদের অনুরোধ এবং প্রতিক্রিয়া প্রকারগুলি নির্দিষ্ট করেন। কোডল্যাবের এই বিভাগে, আসুন সংজ্ঞায়িত করা যাক:

তালিকা বৈশিষ্ট্য

প্রদত্ত Rectangle মধ্যে উপলব্ধ Feature বস্তুগুলি প্রাপ্ত করে। ফলাফলগুলি একবারে ফেরত দেওয়ার পরিবর্তে স্ট্রিম করা হয় কারণ আয়তক্ষেত্রটি একটি বড় এলাকা কভার করতে পারে এবং এতে বিপুল সংখ্যক বৈশিষ্ট্য থাকতে পারে।

এই অ্যাপ্লিকেশনটির জন্য, আপনি একটি সার্ভার-সাইড স্ট্রিমিং RPC ব্যবহার করবেন: ক্লায়েন্ট সার্ভারে একটি অনুরোধ পাঠায় এবং বার্তাগুলির একটি ক্রম পড়ার জন্য একটি স্ট্রিম পায়৷ ক্লায়েন্ট প্রত্যাবর্তিত স্ট্রীম থেকে পাঠ করে যতক্ষণ না আর কোনো বার্তা নেই। আপনি যেমন আমাদের উদাহরণে দেখতে পাচ্ছেন, আপনি প্রতিক্রিয়া প্রকারের আগে স্ট্রিম কীওয়ার্ড স্থাপন করে একটি সার্ভার-সাইড স্ট্রিমিং পদ্ধতি নির্দিষ্ট করেন।

rpc ListFeatures(Rectangle) returns (stream Feature) {}

রেকর্ডরুট

ট্র্যাভার্সাল করা রুটে পয়েন্টের একটি স্ট্রীম গ্রহণ করে, যখন ট্রাভার্সাল সম্পূর্ণ হয় তখন একটি RouteSummary ফেরত দেয়।

একটি ক্লায়েন্ট-সাইড স্ট্রিমিং RPC এই ক্ষেত্রে উপযুক্ত: ক্লায়েন্ট বার্তাগুলির একটি ক্রম লেখে এবং সার্ভারে পাঠায়, আবার একটি প্রদত্ত স্ট্রিম ব্যবহার করে। একবার ক্লায়েন্ট বার্তাগুলি লেখা শেষ করলে, এটি সার্ভারের জন্য সেগুলি পড়ার জন্য এবং তার প্রতিক্রিয়া ফেরত দেওয়ার জন্য অপেক্ষা করে। আপনি অনুরোধের প্রকারের আগে স্ট্রিম কীওয়ার্ড স্থাপন করে একটি ক্লায়েন্ট-সাইড স্ট্রিমিং পদ্ধতি নির্দিষ্ট করুন।

rpc RecordRoute(stream Point) returns (RouteSummary) {}

রুটচ্যাট

অন্যান্য RouteNotes গ্রহণ করার সময় (যেমন অন্যান্য ব্যবহারকারীদের কাছ থেকে) একটি রুট অতিক্রম করার সময় প্রেরিত RouteNotes এর একটি স্ট্রীম গ্রহণ করে৷

দ্বিমুখী স্ট্রিমিংয়ের জন্য এটি ঠিক একই ধরণের ব্যবহারকেস। একটি দ্বিমুখী স্ট্রিমিং RPC যেখানে উভয় পক্ষই একটি পাঠ-লেখা স্ট্রীম ব্যবহার করে বার্তাগুলির একটি ক্রম প্রেরণ করে। দুটি স্ট্রীম স্বাধীনভাবে কাজ করে, তাই ক্লায়েন্ট এবং সার্ভার তাদের পছন্দ অনুযায়ী পড়তে এবং লিখতে পারে: উদাহরণস্বরূপ, সার্ভার তার প্রতিক্রিয়া লেখার আগে সমস্ত ক্লায়েন্ট বার্তা পাওয়ার জন্য অপেক্ষা করতে পারে, বা এটি বিকল্পভাবে একটি বার্তা পড়তে পারে তারপর একটি বার্তা লিখতে পারে, বা পঠিত এবং লেখার অন্য কিছু সংমিশ্রণ। প্রতিটি প্রবাহে বার্তার ক্রম সংরক্ষিত হয়। আপনি অনুরোধ এবং প্রতিক্রিয়া উভয়ের আগে স্ট্রিম কীওয়ার্ড স্থাপন করে এই ধরনের পদ্ধতি নির্দিষ্ট করুন।

rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}

4. ক্লায়েন্ট এবং সার্ভার কোড তৈরি করুন

এরপর, প্রোটোকল বাফার কম্পাইলার ব্যবহার করে .proto ফাইল থেকে ক্লায়েন্ট এবং সার্ভার উভয়ের জন্য বয়লারপ্লেট gRPC কোড তৈরি করুন।

gRPC পাইথন কোড জেনারেশনের জন্য, আমরা grpcio-টুল তৈরি করেছি। এটি অন্তর্ভুক্ত:

  1. নিয়মিত প্রোটোক কম্পাইলার যা message সংজ্ঞা থেকে পাইথন কোড তৈরি করে।
  2. gRPC প্রোটোবাফ প্লাগইন যা service সংজ্ঞা থেকে পাইথন কোড (ক্লায়েন্ট এবং সার্ভার স্টাব) তৈরি করে।

আমরা পিপ ব্যবহার করে grpcio-tools Python প্যাকেজ ইনস্টল করব। সিস্টেম প্যাকেজ থেকে আপনার প্রকল্পের নির্ভরতা বিচ্ছিন্ন করতে একটি নতুন পাইথন ভার্চুয়াল পরিবেশ (ভেনভি) তৈরি করা যাক:

python3 -m venv --upgrade-deps .venv

bash/zsh শেলে ভার্চুয়াল পরিবেশ সক্রিয় করতে:

source .venv/bin/activate

উইন্ডোজ এবং অ-মানক শেলগুলির জন্য, https://docs.python.org/3/library/venv.html#how-venvs-work- এ টেবিলটি দেখুন।

এরপরে, grpcio-tools ইনস্টল করুন (এটি grpcio প্যাকেজও ইনস্টল করে):

pip install grpcio-tools

পাইথন বয়লারপ্লেট কোড তৈরি করতে নিম্নলিখিত কমান্ডটি ব্যবহার করুন:

python -m grpc_tools.protoc --proto_path=./protos  \
 --python_out=. --pyi_out=. --grpc_python_out=. \
 ./protos/route_guide.proto

আমরা route_guide.proto এ সংজ্ঞায়িত ইন্টারফেসের জন্য এটি নিম্নলিখিত ফাইলগুলি তৈরি করবে:

  1. route_guide_pb2.py এমন কোড রয়েছে যা গতিশীলভাবে message সংজ্ঞা থেকে উৎপন্ন ক্লাস তৈরি করে
  2. route_guide_pb2.pyi হল একটি "স্টাব ফাইল" বা "টাইপ ইঙ্গিত ফাইল" message সংজ্ঞা থেকে তৈরি। এটিতে শুধুমাত্র কোন বাস্তবায়ন ছাড়া স্বাক্ষর রয়েছে। ভাল স্বয়ংসম্পূর্ণতা এবং ত্রুটি সনাক্তকরণ প্রদান করতে স্টাব ফাইলগুলি IDE দ্বারা ব্যবহার করা যেতে পারে।
  3. route_guide_pb2_grpc.py service সংজ্ঞা থেকে তৈরি করা হয়েছে এবং এতে gRPC-নির্দিষ্ট ক্লাস এবং ফাংশন রয়েছে।

gRPC-নির্দিষ্ট কোডে রয়েছে:

  1. RouteGuideStub , যা একটি gRPC ক্লায়েন্ট দ্বারা RouteGuide RPC গুলি ব্যবহার করতে পারে৷
  2. RouteGuideServicer , যা RouteGuide পরিষেবার বাস্তবায়নের জন্য ইন্টারফেস সংজ্ঞায়িত করে।
  3. add_RouteGuideServicer_to_server ফাংশন যা একটি GRPC সার্ভারে একটি RouteGuideServicer নিবন্ধন করতে ব্যবহৃত হয়।

5. সার্ভার তৈরি করুন

প্রথমে দেখা যাক কিভাবে আপনি একটি RouteGuide সার্ভার তৈরি করেন। একটি RouteGuide সার্ভার তৈরি এবং চালানো দুটি কাজের আইটেমে বিভক্ত:

  • পরিষেবার প্রকৃত "কাজ" সম্পাদন করে এমন ফাংশনগুলির সাথে আমাদের পরিষেবার সংজ্ঞা থেকে উত্পন্ন সার্ভিসার ইন্টারফেস বাস্তবায়ন করা।
  • ক্লায়েন্টদের কাছ থেকে অনুরোধ শোনার জন্য একটি gRPC সার্ভার চালানো এবং প্রতিক্রিয়া প্রেরণ করা।

আসুন route_guide_server.py দেখুন।

RouteGuide বাস্তবায়ন করুন

route_guide_server.py একটি RouteGuideServicer ক্লাস রয়েছে যা জেনারেট করা ক্লাস route_guide_pb2_grpc.RouteGuideServicer সাবক্লাস করে :

# RouteGuideServicer provides an implementation of the methods of the RouteGuide service.
class RouteGuideServicer(route_guide_pb2_grpc.RouteGuideServicer):

RouteGuideServicer সমস্ত RouteGuide পরিষেবা পদ্ধতি প্রয়োগ করে।

সার্ভার-সাইড স্ট্রিমিং RPC

ListFeatures হল একটি রেসপন্স-স্ট্রিমিং RPC যা ক্লায়েন্টকে একাধিক Feature পাঠায়:

def ListFeatures(self, request, context):
    """List all features contained within the given Rectangle."""
    left = min(request.lo.longitude, request.hi.longitude)
    right = max(request.lo.longitude, request.hi.longitude)
    top = max(request.lo.latitude, request.hi.latitude)
    bottom = min(request.lo.latitude, request.hi.latitude)
    for feature in self.db:
        lat, lng = feature.location.latitude, feature.location.longitude
        if left <= lng <= right and bottom <= lat <= top:
            yield feature

এখানে অনুরোধ বার্তা হল একটি route_guide_pb2.Rectangle যার মধ্যে ক্লায়েন্ট Feature s খুঁজে পেতে চায়। একটি একক প্রতিক্রিয়া ফেরত দেওয়ার পরিবর্তে পদ্ধতিটি শূন্য বা তার বেশি প্রতিক্রিয়া দেয়।

ক্লায়েন্ট-সাইড স্ট্রিমিং RPC

অনুরোধ-স্ট্রিমিং পদ্ধতি RecordRoute অনুরোধের মানগুলির একটি পুনরাবৃত্তিকারী ব্যবহার করে এবং একটি একক প্রতিক্রিয়া মান প্রদান করে।

def RecordRoute(self, request_iterator, context):
    """Calculate statistics about the trip composed of Points."""
    point_count = 0
    feature_count = 0
    distance = 0.0
    prev_point = None

    start_time = time.time()
    for point in request_iterator:
        point_count += 1
        if get_feature(self.db, point):
            feature_count += 1
        if prev_point:
            distance += get_distance(prev_point, point)
        prev_point = point

    elapsed_time = time.time() - start_time
    return route_guide_pb2.RouteSummary(
        point_count=point_count,
        feature_count=feature_count,
        distance=int(distance),
        elapsed_time=int(elapsed_time),
    )

দ্বিমুখী স্ট্রিমিং RPC

অবশেষে, আসুন আমাদের দ্বিমুখী স্ট্রিমিং RPC RouteChat() : দেখুন

def RouteChat(self, request_iterator, context):
    """
    Receive a stream of message/location pairs, and responds with
    a stream of all previous messages for the given location.
    """
    prev_notes = []
    for new_note in request_iterator:
        for prev_note in prev_notes:
            if prev_note.location == new_note.location:
                yield prev_note
        prev_notes.append(new_note)

এই পদ্ধতির শব্দার্থবিদ্যা হল অনুরোধ-স্ট্রিমিং পদ্ধতি এবং প্রতিক্রিয়া-স্ট্রিমিং পদ্ধতির সংমিশ্রণ। এটি অনুরোধ মানগুলির একটি পুনরাবৃত্তিকারী পাস করা হয়েছে এবং এটি নিজেই প্রতিক্রিয়া মানগুলির একটি পুনরাবৃত্তিকারী।

সার্ভার শুরু করুন

একবার আপনি সমস্ত RouteGuide পদ্ধতি প্রয়োগ করলে, পরবর্তী ধাপ হল একটি gRPC সার্ভার শুরু করা যাতে ক্লায়েন্টরা আসলে আপনার পরিষেবা ব্যবহার করতে পারে:

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    route_guide_pb2_grpc.add_RouteGuideServicer_to_server(
        RouteGuideServicer(),
        server,
    )
    listen_addr = "localhost:50051"
    server.add_insecure_port(listen_addr)
    print(f"Starting server on {listen_addr}")
    server.start()
    server.wait_for_termination()

সার্ভার start() পদ্ধতিটি অ-ব্লকিং। অনুরোধগুলি পরিচালনা করার জন্য একটি নতুন থ্রেড ইনস্ট্যান্ট করা হবে। থ্রেড কলিং server.start() এর মধ্যে প্রায়ই অন্য কোন কাজ থাকে না। এই ক্ষেত্রে, সার্ভার বন্ধ না হওয়া পর্যন্ত কলিং থ্রেডটি পরিষ্কারভাবে ব্লক করতে আপনি server.wait_for_termination() কল করতে পারেন।

6. ক্লায়েন্ট তৈরি করুন

আসুন route_guide_client.py দেখি।

একটি স্টাব তৈরি করুন

পরিষেবা পদ্ধতি কল করার জন্য, আমাদের প্রথমে একটি স্টাব তৈরি করতে হবে।

আমরা আমাদের .proto. route_guide_pb2_grpc মডিউলের RouteGuideStub ক্লাসটি ইনস্ট্যান্টিয়েট করি। run() পদ্ধতিতে:

with grpc.insecure_channel("localhost:50051") as channel:
    stub = route_guide_pb2_grpc.RouteGuideStub(channel)

মনে রাখবেন যে এখানে channel একটি প্রসঙ্গ ব্যবস্থাপক হিসাবে ব্যবহৃত হয়েছে, এবং দোভাষী যখন ব্লক with চলে যাবে তখন স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যাবে।

কল পরিষেবা পদ্ধতি

RPC পদ্ধতিগুলির জন্য যেগুলি একটি একক প্রতিক্রিয়া ("response-unary" পদ্ধতিগুলি) প্রদান করে, gRPC Python উভয় সিঙ্ক্রোনাস (ব্লকিং) এবং অ্যাসিঙ্ক্রোনাস (নন-ব্লকিং) নিয়ন্ত্রণ প্রবাহ শব্দার্থকে সমর্থন করে। প্রতিক্রিয়া-স্ট্রিমিং RPC পদ্ধতির জন্য, কল অবিলম্বে প্রতিক্রিয়া মানগুলির একটি পুনরাবৃত্তিকারী প্রদান করে। যে পুনরাবৃত্তিকারীর next() মেথড ব্লকে কল করা হবে যতক্ষণ না ইটারেটর থেকে পাওয়া প্রতিক্রিয়া পাওয়া যায়।

সার্ভার-সাইড স্ট্রিমিং RPC

রেসপন্স-স্ট্রিমিং ListFeatures কল করা সিকোয়েন্স টাইপের সাথে কাজ করার মতই:

def guide_list_features(stub):
    _lo = route_guide_pb2.Point(latitude=400000000, longitude=-750000000)
    _hi = route_guide_pb2.Point(latitude=420000000, longitude=-730000000)
    rectangle = route_guide_pb2.Rectangle(
        lo=_lo,
        hi=_hi,
    )
    print("Looking for features between 40, -75 and 42, -73")

    features = stub.ListFeatures(rectangle)
    for feature in features:
        print(
            f"Feature called '{feature.name}'"
            f" at {format_point(feature.location)}"
        )

ক্লায়েন্ট-সাইড স্ট্রিমিং RPC

অনুরোধ-স্ট্রিমিং RecordRoute কল করা একটি স্থানীয় পদ্ধতিতে একটি পুনরাবৃত্তিকারী পাস করার অনুরূপ। উপরের সাধারণ RPC এর মত যা একটি একক প্রতিক্রিয়াও দেয়, এটিকে সিঙ্ক্রোনাস বলা যেতে পারে:

def guide_record_route(stub):
    feature_list = route_guide_resources.read_route_guide_database()
    route_iterator = generate_route(feature_list)

    route_summary = stub.RecordRoute(route_iterator)
    print(f"Finished trip with {route_summary.point_count} points")
    print(f"Passed {route_summary.feature_count} features")
    print(f"Traveled {route_summary.distance} meters")
    print(f"It took {route_summary.elapsed_time} seconds")

দ্বিমুখী স্ট্রিমিং RPC

দ্বিমুখী-স্ট্রিমিং RouteChat কল করার জন্য অনুরোধ-স্ট্রিমিং এবং প্রতিক্রিয়া-স্ট্রিমিং শব্দার্থবিদ্যার সমন্বয় রয়েছে (যেমনটি পরিষেবা-সাইডে হয়)।

অনুরোধ বার্তা তৈরি করুন, এবং yield ব্যবহার করে একে একে পাঠান।

def generate_notes():
    home = route_guide_pb2.Point(latitude=1, longitude=1)
    work = route_guide_pb2.Point(latitude=2, longitude=2)
    notes = [
        make_route_note("Departing from home", home),
        make_route_note("Arrived at work", work),
        make_route_note("Having lunch at work", work),
        make_route_note("Departing from work", work),
        make_route_note("Arrived home", home),
    ]
    for note in notes:
        print(
            f"Sending RouteNote for {format_point(note.location)}:"
            f" {note.message}"
        )
        yield note
        # Sleep to simulate moving from one point to another.
        # Only for demonstrating the order of the messages.
        time.sleep(0.1)

সার্ভারের প্রতিক্রিয়া গ্রহণ এবং প্রক্রিয়া করুন:

def guide_route_chat(stub):
    responses = stub.RouteChat(generate_notes())
    for response in responses:
        print(
            "< Found previous note at"
            f" {format_point(response.location)}: {response.message}"
        )

সাহায্যকারী পদ্ধতি কল

চলমান অবস্থায়, আমরা এইমাত্র তৈরি করা পদ্ধতিগুলি চালান এবং সেগুলিকে stub করে দিন।

print("-------------- ListFeatures --------------")
guide_list_features(stub)
print("-------------- RecordRoute --------------")
guide_record_route(stub)
print("-------------- RouteChat --------------")
guide_route_chat(stub)

7. এটা চেষ্টা করে দেখুন

সার্ভার চালান:

python route_guide_server.py

একটি ভিন্ন টার্মিনাল থেকে, ভার্চুয়াল পরিবেশ আবার সক্রিয় করুন ( source .venv/bin/activate) , তারপর ক্লায়েন্ট চালান:

python route_guide_client.py

চলুন আউটপুট কটাক্ষপাত করা যাক.

তালিকা বৈশিষ্ট্য

প্রথমত, আপনি বৈশিষ্ট্যের তালিকা পাবেন। প্রতিটি বৈশিষ্ট্য সার্ভার থেকে স্ট্রিম করা হয় ( সার্ভার-সাইড স্ট্রিমিং RPC ) কারণ এটি সেগুলিকে অনুরোধ করা আয়তক্ষেত্রের মধ্যে আবিষ্কার করে:

-------------- ListFeatures --------------
Looking for features between 40, -75 and 42, -73
Feature called 'Patriots Path, Mendham, NJ 07945, USA' at (lat=407838351, lng=-746143763)
Feature called '101 New Jersey 10, Whippany, NJ 07981, USA' at (lat=408122808, lng=-743999179)
Feature called 'U.S. 6, Shohola, PA 18458, USA' at (lat=413628156, lng=-749015468)
Feature called '5 Conners Road, Kingston, NY 12401, USA' at (lat=419999544, lng=-740371136)
...

রেকর্ডরুট

দ্বিতীয়ত, RecordRoute ক্লায়েন্ট থেকে সার্ভারে স্ট্রিম করা এলোমেলোভাবে পরিদর্শন করা পয়েন্টগুলির তালিকা প্রদর্শন করে (ক্লায়েন্ট-সাইড স্ট্রিমিং RPC) :

-------------- RecordRoute --------------
Visiting point (lat=410395868, lng=-744972325)
Visiting point (lat=404310607, lng=-740282632)
Visiting point (lat=403966326, lng=-748519297)
Visiting point (lat=407586880, lng=-741670168)
Visiting point (lat=406589790, lng=-743560121)
Visiting point (lat=410322033, lng=-747871659)
Visiting point (lat=415464475, lng=-747175374)
Visiting point (lat=407586880, lng=-741670168)
Visiting point (lat=402647019, lng=-747071791)
Visiting point (lat=414638017, lng=-745957854)

ক্লায়েন্ট পরিদর্শন করা সমস্ত পয়েন্ট স্ট্রিমিং শেষ করার পরে, এটি সার্ভার থেকে একটি নন-স্ট্রিমিং প্রতিক্রিয়া ( একটি ইউনারী RPC ) পাবে। এই প্রতিক্রিয়াটিতে ক্লায়েন্টের সম্পূর্ণ রুটে সম্পাদিত গণনার সারাংশ থাকবে।

Finished trip with 10 points
Passed 10 features
Traveled 654743 meters
It took 0 seconds

রুটচ্যাট

শেষ, RouteChat আউটপুট দ্বি-দিকনির্দেশক স্ট্রিমিং প্রদর্শন করে। যখন ক্লায়েন্ট home বা work পয়েন্ট "ভিজিট" করে, তখন এটি সার্ভারে একটি RouteNote পাঠিয়ে পয়েন্টের জন্য একটি নোট রেকর্ড করে। যখন একটি পয়েন্ট ইতিমধ্যে পরিদর্শন করা হয়েছে, সার্ভার এই পয়েন্টের জন্য সমস্ত পূর্ববর্তী নোটগুলিকে ফিরিয়ে আনে।

-------------- RouteChat --------------
Sending RouteNote for (lat=1, lng=1): Departing from home
Sending RouteNote for (lat=2, lng=2): Arrived at work
Sending RouteNote for (lat=2, lng=2): Having lunch at work
< Found previous note at (lat=2, lng=2): Arrived at work
Sending RouteNote for (lat=2, lng=2): Departing from work
< Found previous note at (lat=2, lng=2): Arrived at work
< Found previous note at (lat=2, lng=2): Having lunch at work
Sending RouteNote for (lat=1, lng=1): Arrived home
< Found previous note at (lat=1, lng=1): Departing from home

8. পরবর্তী কি