1. مقدمه
در این کد لبه، شما از gRPC-Python برای ایجاد یک کلاینت و سرور استفاده خواهید کرد که پایه و اساس برنامه نقشه برداری مسیر نوشته شده در پایتون را تشکیل می دهد.
در پایان آموزش، یک کلاینت خواهید داشت که با استفاده از gRPC به یک سرور راه دور متصل می شود تا نام یا آدرس پستی آنچه در مختصات خاصی روی نقشه قرار دارد را دریافت کند. یک برنامه کاربردی کاملاً پیشرفته ممکن است از این طراحی سرویس گیرنده-سرور برای برشمردن یا خلاصه کردن نقاط مورد علاقه در طول مسیر استفاده کند.
این سرویس در یک فایل Protocol Buffers تعریف شده است که از آن برای تولید کد boilerplate برای کلاینت و سرور استفاده می شود تا بتوانند با یکدیگر ارتباط برقرار کنند و در زمان و تلاش شما در اجرای آن عملکرد صرفه جویی شود.
این کد تولید شده نه تنها از پیچیدگی های ارتباط بین سرور و کلاینت، بلکه سریال سازی و سریال سازی داده ها نیز مراقبت می کند.
چیزی که یاد خواهید گرفت
- نحوه استفاده از بافرهای پروتکل برای تعریف API سرویس.
- نحوه ساخت یک کلاینت و سرور مبتنی بر gRPC از تعریف بافرهای پروتکل با استفاده از تولید کد خودکار.
- درک ارتباط مشتری-سرور با gRPC.
این کد لبه برای توسعه دهندگان Python که تازه به gRPC می پردازند یا به دنبال یک تجدید کننده gRPC هستند یا هر فرد دیگری که علاقه مند به ساختن سیستم های توزیع شده است، طراحی شده است. هیچ تجربه قبلی gRPC مورد نیاز نیست.
2. قبل از شروع
آنچه شما نیاز دارید
- پایتون 3.9 یا بالاتر. ما پایتون 3.13 را توصیه می کنیم. برای دستورالعملهای نصب پلتفرم خاص، تنظیمات و استفاده پایتون را ببینید. روش دیگر، نصب پایتون غیر سیستمی با استفاده از ابزارهایی مانند uv یا pyenv .
- pip برای نصب بسته های پایتون.
- venv برای ایجاد محیط های مجازی پایتون.
بسته های ensurepip
و venv
بخشی از کتابخانه استاندارد پایتون هستند و معمولاً به طور پیش فرض در دسترس هستند.
با این حال، برخی از توزیعهای مبتنی بر دبیان (از جمله اوبونتو) هنگام توزیع مجدد پایتون، آنها را حذف میکنند. برای نصب بسته ها، اجرا کنید:
sudo apt install python3-pip python3-venv
کد را دریافت کنید
برای سادهسازی یادگیری شما، این Codelab یک داربست کد منبع از پیش ساخته شده برای کمک به شما برای شروع ارائه میکند. مراحل زیر شما را در تکمیل برنامه، از جمله تولید کد gRPC با استفاده از افزونه کامپایلر grpc_tools.protoc
Protocol Buffer راهنمایی می کند.
grpc-codelabs
کد منبع داربست برای این کد لبه در دایرکتوری codelabs/grpc-python-getting-started/start_here موجود است. اگر ترجیح می دهید خودتان کد را پیاده سازی نکنید، کد منبع تکمیل شده در فهرست completed
موجود است.
ابتدا پوشه کاری codelab و cd را در آن ایجاد کنید:
mkdir grpc-python-getting-started && cd grpc-python-getting-started
کد لبه را دانلود و استخراج کنید:
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-getting-started/start_here
یا می توانید فایل .zip را که فقط شامل دایرکتوری Codelab است دانلود کرده و به صورت دستی آن را از حالت فشرده خارج کنید.
3. سرویس را تعریف کنید
اولین قدم شما این است که سرویس gRPC برنامه، روش RPC آن، و انواع پیام درخواست و پاسخ آن را با استفاده از زبان تعریف رابط پروتکل بافر تعریف کنید. خدمات شما ارائه خواهد کرد:
- یک روش RPC به نام
GetFeature
که سرور پیاده سازی می کند و کلاینت فراخوانی می کند. - نوع پیام
Point
وFeature
ساختارهای داده ای هستند که هنگام استفاده از روشGetFeature
بین مشتری و سرور رد و بدل می شوند. مشتری مختصات نقشه را به عنوان یکPoint
در درخواستGetFeature
خود به سرور ارائه می دهد و سرور با یکFeature
مربوطه پاسخ می دهد که هر چیزی را که در آن مختصات قرار دارد را توصیف می کند.
این روش 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
از یک فیلد string
برای نام یا آدرس پستی چیزی در مکانی مشخص شده توسط یک Point
استفاده می کند:
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
روش سرویس دهی
فایل route_guide.proto
دارای یک ساختار service
به نام RouteGuide
است که یک یا چند روش ارائه شده توسط سرویس برنامه را تعریف می کند.
روش rpc
GetFeature
در تعریف RouteGuide
اضافه کنید. همانطور که قبلاً توضیح داده شد، این روش نام یا آدرس یک مکان را از مجموعه مختصات معینی جستجو می کند، بنابراین از GetFeature
بخواهید یک Feature
برای یک Point
داده شده برگرداند:
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
این یک روش RPC یکنواخت است: یک RPC ساده که در آن کلاینت درخواستی را به سرور ارسال می کند و منتظر می ماند تا یک پاسخ بازگردد، درست مانند یک فراخوانی تابع محلی.
4. کد کلاینت و سرور را تولید کنید
سپس، کد gRPC را برای مشتری و سرور از فایل .proto
با استفاده از کامپایلر بافر پروتکل تولید کنید.
برای تولید کد gRPC پایتون، ابزارهای grpcio را ایجاد کردیم. شامل:
- کامپایلر پروتک معمولی که کد پایتون را از تعاریف
message
تولید می کند. - پلاگین gRPC protobuf که کد پایتون (خرد مشتری و سرور) را از تعاریف
service
تولید می کند.
ما بسته پایتون grpcio-tools
با استفاده از pip نصب می کنیم. بیایید یک محیط مجازی پایتون جدید (venv) ایجاد کنیم تا وابستگی های پروژه شما را از بسته های سیستم جدا کنیم:
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
تعریف کردیم ایجاد میکند:
-
route_guide_pb2.py
حاوی کدی است که به صورت پویا کلاس های تولید شده از تعاریفmessage
را ایجاد می کند. -
route_guide_pb2.pyi
یک "فایل خرد" یا "نوع فایل راهنمایی" است که از تعاریفmessage
ایجاد شده است. فقط شامل امضاهایی است که هیچ اجرائی ندارند. فایلهای Stub را میتوان توسط IDEها برای تکمیل خودکار و تشخیص خطا بهتر استفاده کرد. -
route_guide_pb2_grpc.py
از تعاریفservice
تولید می شود و شامل کلاس ها و توابع خاص gRPC است.
کد مخصوص gRPC شامل:
-
RouteGuideStub
، که می تواند توسط یک کلاینت gRPC برای فراخوانی RouteGuide RPC استفاده شود. -
RouteGuideServicer
، که رابط را برای پیاده سازی سرویسRouteGuide
تعریف می کند. - تابع
add_RouteGuideServicer_to_server
که برای ثبت یکRouteGuideServicer
در سرور gRPC استفاده می شود.
5. سرویس را ایجاد کنید
ابتدا اجازه دهید نحوه ایجاد سرور RouteGuide
را بررسی کنیم. ایجاد و اجرای سرور RouteGuide
به دو مورد تقسیم می شود:
- پیاده سازی رابط سرویس دهنده تولید شده از تعریف سرویس ما با توابعی که "کار" واقعی سرویس را انجام می دهند.
- اجرای یک سرور gRPC در یک پورت خاص برای گوش دادن به درخواست های مشتریان و ارسال پاسخ ها.
میتوانید سرور RouteGuide
اولیه را در start_here/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 را با جزئیات بررسی کنیم. متد GetFeature
یک Point
از مشتری دریافت می کند و اطلاعات ویژگی مربوطه را از پایگاه داده خود در Feature
برمی گرداند.
def GetFeature(self, request, context):
feature = get_feature(self.db, request)
if feature is None:
return route_guide_pb2.Feature(name="", location=request)
else:
return feature
این روش یک درخواست route_guide_pb2.Point
برای RPC، و یک شی grpc.ServicerContext
ارسال میشود که اطلاعات خاص RPC مانند محدودیتهای مهلت زمانی را ارائه میدهد. پاسخ route_guide_pb2.Feature
را برمی گرداند.
راه اندازی سرور
هنگامی که تمام روشهای 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. مشتری ایجاد کنید
در این بخش، ایجاد یک کلاینت برای سرویس RouteGuide
خود را بررسی خواهیم کرد. میتوانید کد مشتری اولیه را در start_here/route_guide_client.py
ببینید.
یک خرد ایجاد کنید
برای فراخوانی روش های سرویس، ابتدا باید یک خرد ایجاد کنیم.
ما کلاس RouteGuideStub
ماژول route_guide_pb2_grpc
را که از .proto
ما در داخل فایل route_guide_client.py
تولید شده است، نمونه سازی می کنیم.
channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
روش های خدمات تماس
برای روشهای RPC که یک پاسخ واحد را برمیگردانند – معروف به روشهای پاسخ-یونری – gRPC Python از معناشناسی جریان کنترل همزمان (مسدودکننده) و ناهمزمان (غیر مسدودکننده) پشتیبانی میکند.
RPC ساده
ابتدا بیایید یک Point
برای فراخوانی سرویس تعریف کنیم. این باید به سادگی نمونهبرداری از یک شی از بسته route_guide_pb2
با برخی ویژگیها باشد:
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
فراخوانی همزمان با RPC GetFeature
ساده تقریباً به اندازه فراخوانی یک متد محلی است. فراخوانی RPC منتظر می ماند تا سرور پاسخ دهد و یا پاسخی را برمی گرداند یا استثنایی ایجاد می کند. می توانیم متد را فراخوانی کنیم و پاسخ را به صورت زیر ببینیم:
feature = stub.GetFeature(point)
print(feature)
میتوانید فیلدهای شی Feature را بررسی کنید و نتیجه درخواست را به دست آورید:
if feature.name:
print(f"Feature called '{feature.name}' at {format_point(feature.location)}")
else:
print(f"Found no feature at at {format_point(feature.location)}")
7. آن را امتحان کنید
سرور را اجرا کنید:
python route_guide_server.py
از یک ترمینال دیگر، دوباره محیط مجازی را فعال کنید، سپس کلاینت را اجرا کنید:
python route_guide_client.py
خروجی را به صورت زیر مشاهده خواهید کرد که برای وضوح از مهرهای زمانی حذف شده است:
name: "16 Old Brook Lane, Warwick, NY 10990, USA" location { latitude: 412346009 longitude: -744026814 } Feature called '16 Old Brook Lane, Warwick, NY 10990, USA' at latitude: 412346009, longitude: -744026814
8. بعدی چه خواهد شد
- نحوه عملکرد gRPC را در مقدمه مفاهیم gRPC و Core بیاموزید
- از طریق آموزش اصول کار کنید
- مرجع Python API را کاوش کنید