1. מבוא
ב-codelab הזה תשתמשו ב-gRPC-Python כדי ליצור לקוח ושרת שיהוו את הבסיס לאפליקציה למיפוי מסלולים שנכתבה ב-Python.
בסוף המדריך יהיה לכם לקוח שמתחבר לשרת מרוחק באמצעות gRPC כדי לקבל את השם או את הכתובת למשלוח דואר של מה שנמצא בקואורדינטות ספציפיות במפה. אפליקציה מפותחת יכולה להשתמש בעיצוב הזה של לקוח-שרת כדי למנות או לסכם נקודות עניין לאורך מסלול.
השירות מוגדר בקובץ Protocol Buffers, שישמש ליצירת קוד boilerplate ללקוח ולשרת, כדי שהם יוכלו לתקשר זה עם זה. כך תוכלו לחסוך זמן ומאמץ בהטמעת הפונקציונליות הזו.
הקוד שנוצר מטפל לא רק במורכבויות של התקשורת בין השרת ללקוח, אלא גם בסריאליזציה ובדה-סריאליזציה של הנתונים.
מה תלמדו
- איך משתמשים ב-Protocol Buffers כדי להגדיר API של שירות.
- איך ליצור לקוח ושרת מבוססי gRPC מהגדרה של Protocol Buffers באמצעות יצירת קוד אוטומטית.
- הבנה של תקשורת בין שרתים ללקוחות באמצעות gRPC.
ה-codelab הזה מיועד למפתחי Python שחדשים ב-gRPC או שרוצים לרענן את הידע שלהם ב-gRPC, או לכל מי שמעוניין ליצור מערכות מבוזרות. לא נדרש ניסיון קודם ב-gRPC.
2. לפני שמתחילים
מה נדרש
- Python בגרסה 3.9 ואילך. מומלץ להשתמש ב-Python 3.13. הוראות התקנה ספציפיות לפלטפורמה מופיעות במאמר Python Setup and Usage (הגדרה ושימוש ב-Python). אפשר גם להתקין Python שאינו מערכת באמצעות כלים כמו uv או pyenv.
- pip להתקנת חבילות Python.
- venv כדי ליצור סביבות וירטואליות של Python.
החבילות ensurepip
ו-venv
הן חלק מהספרייה הרגילה של Python, ובדרך כלל הן זמינות כברירת מחדל.
עם זאת, חלק מההפצות שמבוססות על Debian (כולל Ubuntu) בוחרות להחריג אותן כשמפיצים מחדש את Python. כדי להתקין את החבילות, מריצים את הפקודה:
sudo apt install python3-pip python3-venv
קבל את הקוד
כדי לייעל את הלמידה, ב-Codelab הזה מוצעת מסגרת קוד מקור מוכנה מראש שתעזור לכם להתחיל. בשלבים הבאים מוסבר איך להשלים את הבקשה, כולל יצירת קוד gRPC באמצעות התוסף grpc_tools.protoc
Protocol Buffer compiler.
grpc-codelabs
קוד המקור של ה-scaffold ל-codelab הזה זמין בספרייה codelabs/grpc-python-getting-started/start_here. אם אתם מעדיפים לא להטמיע את הקוד בעצמכם, קוד המקור המלא זמין בספרייה completed
.
קודם יוצרים את ספריית העבודה של ה-codelab ועוברים אליה:
mkdir grpc-python-getting-started && cd grpc-python-getting-started
מורידים ומחלצים את ה-Codelab:
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 ואת סוגי ההודעות של הבקשה והתגובה באמצעות שפת הגדרת הממשק של Protocol Buffers. השירות שלכם יספק:
- שיטת RPC שנקראת
GetFeature
, שהשרת מטמיע והלקוח מפעיל. - סוגי ההודעות
Point
ו-Feature
הם מבני נתונים שמועברים בין הלקוח לשרת כשמשתמשים בשיטהGetFeature
. הלקוח מספק קואורדינטות של מפה כ-Point
בבקשתGetFeature
שלו לשרת, והשרת משיב עםFeature
תואם שמתאר את מה שנמצא בקואורדינטות האלה.
שיטת ה-RPC הזו וסוגי ההודעות שלה יוגדרו בקובץ protos/route_guide.proto
של קוד המקור שסופק.
פרוטוקול באפרס ידוע בדרך כלל כ-protobuf. מידע נוסף על המינוח של gRPC זמין במאמר מושגי ליבה, ארכיטקטורה ומחזור חיים של gRPC.
סוגי הודעות
בקובץ protos/route_guide.proto
של קוד המקור, מגדירים קודם את סוג ההודעה Point
. הסמל Point
מייצג זוג קואורדינטות של קו רוחב וקו אורך במפה. ב-codelab הזה, משתמשים במספרים שלמים לקואורדינטות:
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
באמצעות מהדר פרוטוקול ה-Buffer.
יצרנו את grpcio-tools ליצירת קוד gRPC Python. היא כוללת:
- הקומפיילר הרגיל protoc שיוצר קוד Python מהגדרות
message
. - תוסף gRPC protobuf שיוצר קוד Python (stub של לקוח ושרת) מההגדרות של
service
.
נתקין את חבילת Python grpcio-tools
באמצעות pip. כדאי ליצור סביבה וירטואלית של Python (venv) כדי לבודד את התלות של הפרויקט בחבילות המערכת:
python3 -m venv --upgrade-deps .venv
כדי להפעיל את הסביבה הווירטואלית במעטפת bash/zsh:
source .venv/bin/activate
במערכות Windows ובמעטפות לא סטנדרטיות, אפשר לעיין בטבלה שבכתובת https://docs.python.org/3/library/venv.html#how-venvs-work.
בשלב הבא, מתקינים את grpcio-tools (הפעולה הזו מתקינה גם את החבילה grpcio):
pip install grpcio-tools
כדי ליצור את קוד ה-boilerplate של Python, משתמשים בפקודה הבאה:
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
הוא קובץ stub או קובץ רמזים לגבי סוגים שנוצר מההגדרות שלmessage
. הוא מכיל רק את החתימות ללא הטמעה. סביבות פיתוח משולבות (IDE) יכולות להשתמש בקובצי stub כדי לספק השלמה אוטומטית טובה יותר וזיהוי שגיאות. -
route_guide_pb2_grpc.py
נוצר מההגדרות שלservice
ומכיל מחלקות ופונקציות ספציפיות ל-gRPC.
קוד ספציפי ל-gRPC מכיל:
-
RouteGuideStub
, שאפשר להשתמש בו בלקוח gRPC כדי להפעיל קריאות RPC של RouteGuide. -
RouteGuideServicer
, שמגדיר את הממשק להטמעות של שירותRouteGuide
. - הפונקציה
add_RouteGuideServicer_to_server
שמשמשת לרישוםRouteGuideServicer
ב-gRPC server.
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
ואובייקט 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
.
יצירת דף stub
כדי לקרוא לשיטות של שירות, קודם צריך ליצור stub.
אנחנו יוצרים מופע של המחלקה RouteGuideStub
מהמודול route_guide_pb2_grpc
, שנוצר מ-.proto
שלנו בתוך הקובץ route_guide_client.py
.
channel = grpc.insecure_channel("localhost:50051")
stub = route_guide_pb2_grpc.RouteGuideStub(channel)
שיטות של שירותי שיחות
בשיטות RPC שמחזירות תגובה יחידה – שיטות שנקראות response-unary – gRPC Python תומך בסמנטיקה של זרימת בקרה סינכרונית (חסימה) ואסינכרונית (לא חסימה).
Simple RPC
קודם כול, נגדיר Point
כדי להתקשר לשירות. הפעולה הזו פשוטה יחסית, וכוללת יצירת מופע של אובייקט מהחבילה route_guide_pb2
עם כמה מאפיינים:
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
קריאה סינכרונית ל-RPC הפשוט GetFeature
היא פשוטה כמעט כמו קריאה ל-method מקומית. הקריאה ל-RPC ממתינה לתגובת השרת, ותחזיר תגובה או תעלה חריגה. אפשר להתקשר לשיטה ולראות את התגובה כך:
feature = stub.GetFeature(point)
print(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 ומושגי ליבה.
- עוברים על המדריך למתחילים
- עיון במקורות מידע בנושא Python API