
در پارت اول میخوام یکم درمورد gRPC توضیح بدم و یک gRPC رو با پایتون بیارم بالا و در پارت دوم از طریق اپلیکیشن فلاتری متودی که توی پایتون ساختیم رو با فلاتر فراخوانی کنیم
RPC یا Remote Procedure Call به معنی فراخوانی تابع از راه دور هست که توسعه دهنده ها میتونن بجای ارسال پیام های json که بر پایه http ورژن یک هست بیان و متود ها یا توابع هایی رو تعریف کنند و خیلی راحت فراخوانی کنند.
یک چارچوب یا همون framework متن باز برای سیستم های RPC با کارایی بالا که توسط گوگل توسعه یافته
اول از همه باید با استفاده از زبان پروتکل بافر که با فرمت proto. هست پیام ها و سرویس هامون رو مشخص و دیفاین میکنم
مرحله دوم هم تولید کد های هر زبان هست که زبان های مختلف از جمله دارت و پایتون رو پشتیبانی میکنه که برای تولید کد هر زبان نیاز به ابزار protoc داریم که بیاد این پروتوکلی که نوشتیم رو به زبان های مقصد تبدیل کنه
کارایی بالا که از HTTP/2 استفاده میکنه و مقادیر رو بصورت باینری جابه جا میکنه که حجم داده و سرعت انتقال نسب به json بالاتره
از زبان های مختلف استفاده میکنه، اینطوریه که شما یک proto مینویسید و برای زبان های مختلف خروجی میگرید
معمولا gRPC توی میکروسرویس ها که نیاز به سرعت زیاد جهت جابه جایی انتقال و توی میکروسرویس ها یا هرجایی که از چند زبان برنامه نویسی استفاده میشه gRPC کمک کننده هست چون فقط یک پروتکل داری و استفاده میکنی
خب من فایلی به نامه helloworld.proto رو میسازم و توش پروتکل هامو تعریف میکنم
syntax = "proto3"; package helloworld; service Greeter { rpc SayHello (HelloRequest) returns (HelloReply); } message HelloRequest { string name = 1; } message HelloReply { string message = 1; }
اول از همه اومدم گفتم که از ورژن سه پروتکل بافر استفاده میکنم.
اسم پکیجم رو گفتم که این مورد توی ایمپورت کردن کد تولید شده بهمون کمک میکنه که پکیج ما helloworld هست
اومدم یک سرویس Greeter نوشتم که یک متود rpc به نام SayHello داره که ورودی این متود HelloRequest و خروجی اون HelloReply هست
یک پیام یا بهتره بگم یه ساختار داده به نام HelloRequest تعریف کردم که فقط یک فیلد داره و اون هم name هست از نوع string و ایندکس یک که برای سریالایز شدن استفاده میشه
این ایندکس باید یکتا باشه و بهتره از یک شروع بشه
یک پیام پاسخ به نام HelloReply تعریف کردم که message رو که string هست به عنوان پاسخ بر میگردونه
برای تولید کد اول از همه باید کامپایلر پروتکل بافر یعنی ptoco رو نصب که کنیم که از لینک گیت هاب قابل دانلود هست و بعد برای پایتون پکیج های grpcio, grpcio-tools با دستور pip نصب میکنیم و بعد دستور زیر رو اجرا میکنیم توی همون پوشه ای که helloworld.proto هست
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
-I. میگه که فایل .proto در مسیر جاری هست.
--python_out=. فایلهای protobuf (ساختار پیامها) را تولید میکنه.
--grpc_python_out=. کدهای لازم برای gRPC client/server را تولید میکنه.
helloworld.proto اسم فایل شماست.
بعد از اجرای دستور، دو فایل جدید کنار فایل proto تولید میشن:
helloworld_pb2.py: تعریف پیامها (HelloRequest، HelloReply)
helloworld_pb2_grpc.py: تعریف سرویس gRPC (GreeterStub، GreeterServicer)
این کد راه اندازی هست و خط به خط بهت میگم چیکار کردم
from concurrent import futures import grpc import helloworld_pb2, helloworld_pb2_grpc class Greeter(helloworld_pb2_grpc.GreeterServicer): def SayHello(self, request, context): return helloworld_pb2.HelloReply(message=f"Hello, {request.name}!") def serve(): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server) server.add_insecure_port('[::]:50051') server.start() server.wait_for_termination() if name == '__main__': serve()
تو خط اول ماژول concurrent.futures یکی از ابزارهای استاندارد پایتون برای مدیریت thread و pool از threadهاست.
اینجا برای راهاندازی سرور gRPC با امکان پردازش چند درخواست همزمان (multi-threading) استفاده میشه.
ماژول اصلی grpc به همراه کد های تولید شده رو ایمپورت کردم
یه کلاس ساختم به اسم Greeter و میاد از سرویسی که ساختم توی proto و تولید شده توی فایل helloworld_pb2_grpc که به نام GreeterServicer ارث بری میکنم و متودی که توی proto تعریف کردم رو برای خودم تعریف میکنم که متود SayHello بود
request: شیای از نوع HelloRequest که کلاینت فرستاده.
context: اطلاعات اضافه مربوط به وضعیت فراخوانی (مثلاً deadline، metadata، status و ...).
در پاسخ، یک HelloReply تولید میکنیم و داخلش پیام Hello, {name}! رو قرار میدیم.
مثلاً اگر کلاینت "name = "Adnan Kamali بفرسته، پاسخ سرور میشه: "!Hello, Adnan Kamali"
تابعی به نام serve تعریف شده که کارش راهاندازی سرور gRPC هست و یک شیء سرور gRPC میسازیم و بهش یک thread pool با حداکثر 10 thread میدیم تا بتونه همزمان چند درخواست رو هندل کنه.
توی خط 11 کلاس Greeter که ساختیم رو به سرور gRPC اضافه میکنیم و این خط دقیقا همون لحظه ایه که میگیم اگه کسی RPC به اسم SayHello صدا زد، تابع SayHello رو اجرا کن
خط 12 سرور میاد روی پورت 50051 روی تمامی آی پی های ماشین شنود میشه
خط 13 سرویس شروع و در خط 14 سرور تا زمانی که دستی بسته نشه با همون ctrl+c درحالت اجرا میمونه
امیدوارم تا اینجا مطلب براتون روشن شده باشه و اگر بکند کار نیستید حداقل درمورد gRPC یکم اطلاعاتتون بیشتر شده باشه و در پارت دوم درمورد چطوری فراخوانی تابع SayHello با استفاده از فلاتر رو توضیح میدم