1. บทนำ
ในโค้ดแล็บนี้ คุณจะได้ใช้ gRPC-Python เพื่อสร้างไคลเอ็นต์และเซิร์ฟเวอร์ซึ่งเป็นรากฐานของแอปพลิเคชันการแมปเส้นทางที่เขียนด้วย Python
เมื่อจบบทแนะนำนี้ คุณจะมีไคลเอ็นต์ที่เชื่อมต่อกับเซิร์ฟเวอร์ระยะไกลโดยใช้ gRPC เพื่อรับชื่อหรือที่อยู่ไปรษณีย์ของสิ่งที่อยู่ ณ พิกัดที่เฉพาะเจาะจงบนแผนที่ แอปพลิเคชันที่สมบูรณ์อาจใช้การออกแบบไคลเอ็นต์-เซิร์ฟเวอร์นี้เพื่อแจงนับหรือสรุปจุดที่น่าสนใจตามเส้นทาง
บริการนี้กำหนดไว้ในไฟล์ Protocol Buffers ซึ่งจะใช้เพื่อสร้างโค้ดมาตรฐานสำหรับไคลเอ็นต์และเซิร์ฟเวอร์เพื่อให้สื่อสารกันได้ ซึ่งจะช่วยประหยัดเวลาและแรงในการติดตั้งใช้งานฟังก์ชันดังกล่าว
โค้ดที่สร้างขึ้นนี้ไม่เพียงแต่จัดการความซับซ้อนของการสื่อสารระหว่างเซิร์ฟเวอร์และไคลเอ็นต์เท่านั้น แต่ยังจัดการการซีเรียลไลซ์และการดีซีเรียลไลซ์ข้อมูลด้วย
สิ่งที่คุณจะได้เรียนรู้
- วิธีใช้ Protocol Buffers เพื่อกำหนด API ของบริการ
 - วิธีสร้างไคลเอ็นต์และเซิร์ฟเวอร์ที่ใช้ gRPC จากคำจำกัดความของ Protocol Buffers โดยใช้การสร้างโค้ดอัตโนมัติ
 - ความเข้าใจเกี่ยวกับการสื่อสารระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์ด้วย gRPC
 
Codelab นี้มีไว้สำหรับนักพัฒนา Python ที่เพิ่งเริ่มใช้ gRPC หรือต้องการทบทวน gRPC หรือผู้ที่สนใจสร้างระบบแบบกระจาย ไม่จำเป็นต้องมีประสบการณ์เกี่ยวกับ gRPC มาก่อน
2. ก่อนเริ่มต้น
สิ่งที่คุณต้องมี
- Python 3.9 ขึ้นไป เราขอแนะนำให้ใช้ Python 3.13 ดูวิธีการติดตั้งเฉพาะแพลตฟอร์มได้ที่การตั้งค่าและการใช้งาน 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
grpc-codelabs
ซอร์สโค้ดโครงร่างสำหรับ Codelab นี้อยู่ในไดเรกทอรี codelabs/grpc-python-getting-started/start_here หากไม่ต้องการติดตั้งใช้งานโค้ดด้วยตนเอง คุณจะดูซอร์สโค้ดที่เสร็จสมบูรณ์ได้ในไดเรกทอรี completed
ก่อนอื่น ให้สร้างไดเรกทอรีการทำงานของ Codelab แล้วใช้คำสั่ง cd เพื่อเข้าไปในไดเรกทอรีดังกล่าว
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 ของซอร์สโค้ดที่ระบุ
Protocol Buffers เรียกกันโดยทั่วไปว่า 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 ซึ่งกำหนดวิธีการอย่างน้อย 1 วิธีที่บริการของแอปพลิเคชันมีให้
เพิ่มrpc method 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 โดยใช้คอมไพเลอร์ Protocol Buffer
เราได้สร้าง grpcio-tools สำหรับการสร้างโค้ด gRPC Python แอปประกอบด้วย
- คอมไพเลอร์ protoc ปกติที่สร้างโค้ด Python จากคำจำกัดความ 
message - ปลั๊กอิน Protobuf ของ gRPC ที่สร้างโค้ด Python (ต้นขั้วไคลเอ็นต์และเซิร์ฟเวอร์) จาก
service 
เราจะติดตั้งgrpcio-toolsแพ็กเกจ Python โดยใช้ pip มาสร้างสภาพแวดล้อมเสมือนของ Python (venv) ใหม่เพื่อแยกการอ้างอิงของโปรเจ็กต์ออกจากแพ็กเกจของระบบกัน
python3 -m venv --upgrade-deps .venv
วิธีเปิดใช้งานสภาพแวดล้อมเสมือนใน Bash/Zsh Shell
source .venv/bin/activate
สำหรับ Windows และเชลล์ที่ไม่ใช่แบบมาตรฐาน โปรดดูตารางที่ https://docs.python.org/3/library/venv.html#how-venvs-work
จากนั้นติดตั้ง grpcio-tools (ซึ่งจะติดตั้งแพ็กเกจ grpcio ด้วย)
pip install grpcio-tools
ใช้คำสั่งต่อไปนี้เพื่อสร้างโค้ดบอยเลอร์เพลต 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มีโค้ดที่สร้างคลาสแบบไดนามิกซึ่งสร้างจากคำจำกัดความของmessageroute_guide_pb2.pyiคือ "ไฟล์ Stub" หรือ "ไฟล์คำแนะนำประเภท" ที่สร้างจากคำจำกัดความของmessageโดยจะมีเฉพาะลายเซ็นที่ไม่มีการติดตั้งใช้งาน IDE สามารถใช้ไฟล์ Stub เพื่อให้การเติมข้อความอัตโนมัติและการตรวจหาข้อผิดพลาดดียิ่งขึ้นroute_guide_pb2_grpc.pyสร้างขึ้นจากคำจำกัดความของserviceและมีคลาสและฟังก์ชันเฉพาะของ gRPC
โค้ดเฉพาะ gRPC มีดังนี้
RouteGuideStubซึ่งไคลเอ็นต์ gRPC สามารถใช้เพื่อเรียกใช้ RPC ของ RouteGuide ได้RouteGuideServicerซึ่งกำหนดอินเทอร์เฟซสำหรับการใช้งานบริการRouteGuideadd_RouteGuideServicer_to_serverฟังก์ชันที่ใช้เพื่อลงทะเบียนRouteGuideServicerกับ เซิร์ฟเวอร์ gRPC
5. สร้างบริการ
ก่อนอื่นมาดูวิธีสร้างRouteGuideเซิร์ฟเวอร์กัน การสร้างและเรียกใช้RouteGuideเซิร์ฟเวอร์แบ่งออกเป็น 2 รายการงาน ดังนี้
- การติดตั้งใช้งานอินเทอร์เฟซผู้ให้บริการที่สร้างขึ้นจากคำจำกัดความของบริการของเราด้วยฟังก์ชันที่ทำ "งาน" จริงของบริการ
 - เรียกใช้เซิร์ฟเวอร์ 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
สร้าง 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 รองรับทั้งซีแมนทิกส์ของโฟลว์การควบคุมแบบซิงโครนัส (บล็อก) และแบบไม่พร้อมกัน (ไม่บล็อก)
RPC อย่างง่าย
ก่อนอื่น มากำหนด Point เพื่อเรียกใช้บริการกัน ซึ่งควรจะง่ายเหมือนกับการสร้างออบเจ็กต์จากแพ็กเกจ route_guide_pb2 ที่มีพร็อพเพอร์ตี้บางอย่าง ดังนี้
point = route_guide_pb2.Point(latitude=412346009, longitude=-744026814)
การเรียกแบบซิงโครนัสไปยัง RPC อย่างง่าย GetFeature นั้นแทบจะตรงไปตรงมาเหมือนกับการเรียกเมธอดในเครื่อง การเรียก 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