0Pricing
PHP Academy · บทเรียน

การสื่อสารระหว่างบริการ: REST และ gRPC

เชื่อมต่อบริการแบบทำงานพร้อมกันอย่างมีประสิทธิภาพ

การสื่อสารระหว่างบริการ: REST และ gRPC เป็นบทเรียน PHP Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน PHP Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

REST และ gRPC

บริการจำเป็นต้องสื่อสารกันแบบทำงานพร้อมรอผล: ส่งคำขอออกไป แล้วได้รับคำตอบกลับมา ตัวเลือกหลักสองแบบคือ REST ผ่าน HTTP/JSON และ gRPC ผ่าน HTTP/2 + Protobuf แต่ละแบบเหมาะกับเป้าหมายต่างกัน — REST เหมาะกับการเข้าถึงได้กว้างและใช้งานเข้าใจง่าย ส่วน gRPC เหมาะกับความเร็วและสัญญาที่เข้มงวด

บทเรียนนี้จะแสดงทั้งสองแบบจากมุมมองของ PHP และอธิบายว่าควรเลือกใช้แบบใด

REST: ภาษากลาง

REST จัดทรัพยากรไว้ภายใต้ URL และใช้กริยา HTTP กับรหัสสถานะเพื่อสื่อความหมาย จุดเด่นคือมีเครื่องมือรองรับทั่วไป แคชได้ แก้จุดบกพร่องด้วย curl ได้ และไม่ต้องใช้ไคลเอนต์พิเศษ จุดด้อยคือ JSON มีรายละเอียดมาก ไม่มีสคีมาบังคับใช้ และรองรับเฉพาะคำขอกับการตอบกลับ

สำหรับ API สาธารณะและจุดปลายทางที่เบราว์เซอร์เรียกใช้ REST มักเป็นตัวเลือกที่เหมาะสมที่สุด

การเรียกใช้บริการ REST

ใช้ไคลเอนต์ HTTP ตามมาตรฐาน PSR-18 (ตัวอย่างนี้ใช้ Guzzle) ควรกำหนด ระยะหมดเวลาการเชื่อมต่อและการร้องขอเสมอ — การเรียกที่ไม่มีขอบเขตเวลาไปยังบริการเพื่อนบ้านที่ช้าอาจใช้กระบวนการทำงานของ PHP-FPM จนหมด และทำให้ระบบขัดข้องลุกลาม

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;

$http = new Client([
    'base_uri'        => 'http://customers-svc/',
    'connect_timeout' => 1.0,  // never block forever on connect
    'timeout'         => 3.0,  // total request budget
    'http_errors'     => false,
]);

$res = $http->get('customers/42', ['headers' => ['Accept' => 'application/json']]);
if ($res->getStatusCode() === 200) {
    $customer = json_decode((string) $res->getBody(), true);
    echo $customer['email'] . "\n";
}

รหัสสถานะคือสัญญา

ในการสื่อสาร REST ระหว่างบริการ รหัสสถานะ HTTP คือโพรโทคอลข้อผิดพลาดของคุณ จงจัดการโดยตั้งใจ:

  • 2xx สำเร็จ; 4xx เป็นความผิดของผู้เรียก (อย่าลองใหม่โดยไม่พิจารณา); 5xx/หมดเวลาเป็นกรณีที่ควรลองใหม่
  • ใช้ 409 สำหรับข้อขัดแย้ง 422 สำหรับการตรวจสอบข้อมูล และ 429 สำหรับการจำกัดอัตรา (ให้ปฏิบัติตาม Retry-After)

การลองใหม่เมื่อได้ 400 มีแต่จะทำให้เสียการเรียกใช้โดยเปล่าประโยชน์ ส่วนการลองใหม่เมื่อได้ 503 โดยเพิ่มช่วงหน่วงนั้นถูกต้อง

<?php
function isRetryable(int $status): bool {
    return $status === 0          // timeout/connection error
        || $status === 429
        || ($status >= 500 && $status !== 501);
}
var_dump(isRetryable(503)); // true
var_dump(isRetryable(400)); // false

gRPC: เริ่มจากสัญญาและรวดเร็ว

gRPC ใช้ โปรโตคอลบัฟเฟอร์: คุณกำหนดบริการและข้อความในไฟล์ .proto แล้วสร้างสตับไคลเอนต์/เซิร์ฟเวอร์ที่มีชนิดข้อมูลชัดเจน เมื่อทำงานผ่าน HTTP/2 ด้วย Protobuf แบบไบนารี จะมีขนาดกะทัดรัดกว่าและมีเวลาแฝงต่ำกว่า JSON มาก อีกทั้งยังรองรับการสตรีมข้อมูล

syntax = "proto3";
package customers;

service Customers {
  rpc GetCustomer (GetCustomerRequest) returns (Customer);
}

message GetCustomerRequest { string id = 1; }
message Customer {
  string id = 1;
  string email = 2;
  int32  loyalty_points = 3;
}

การสร้างสตับ PHP

ติดตั้งส่วนขยาย gRPC ของ PHP และปลั๊กอิน protoc จากนั้นสร้างคลาสไคลเอนต์จากไฟล์ .proto PHP สามารถทำหน้าที่เป็น ไคลเอนต์ gRPC ที่มีความสามารถครบถ้วนผ่าน ext-grpc ได้ ส่วนการทำงานเป็น เซิร์ฟเวอร์ gRPC แบบ PHP โดยตรงโดยทั่วไปต้องใช้ Roadrunner หรือ Swoole

pecl install grpc
composer require grpc/grpc google/protobuf

protoc --proto_path=. \
  --php_out=./generated \
  --grpc_out=./generated \
  --plugin=protoc-gen-grpc=$(which grpc_php_plugin) \
  customers.proto

การเรียกใช้จากไคลเอนต์ gRPC

สตับที่สร้างขึ้นจะมอบคำขอและคำตอบที่มีชนิดข้อมูลกำกับ การเรียก gRPC จะส่งคืนข้อความและออบเจ็กต์ status — ควรตรวจสอบรหัสสถานะทุกครั้งก่อนเชื่อถือคำตอบ

<?php
require 'vendor/autoload.php';
use Customers\CustomersClient;
use Customers\GetCustomerRequest;
use Grpc\ChannelCredentials;

$client = new CustomersClient('customers-svc:50051', [
    'credentials' => ChannelCredentials::createInsecure(),
]);

$req = (new GetCustomerRequest())->setId('42');
[$reply, $status] = $client->GetCustomer($req)->wait();

if ($status->code === \Grpc\STATUS_OK) {
    echo $reply->getEmail(), "\n";
} else {
    fwrite(STDERR, "gRPC error: {$status->details}\n");
}

การพัฒนาสคีมา

Protobuf สร้างขึ้นเพื่อรองรับความเข้ากันได้ไปข้างหน้าและย้อนหลัง — หากคุณปฏิบัติตามกฎของมัน:

  • ห้ามนำหมายเลขฟิลด์กลับมาใช้ซ้ำหรือเปลี่ยนแปลง ให้เพิ่มฟิลด์ใหม่ด้วยหมายเลขใหม่
  • ทำเครื่องหมายฟิลด์ที่ลบออกด้วย reserved เพื่อไม่ให้หมายเลขนั้นถูกนำกลับมาใช้ใหม่
  • ไคลเอนต์รุ่นเก่าจะข้ามฟิลด์ที่ไม่รู้จัก ส่วนฟิลด์ที่ไม่มีค่าจะใช้ค่าเริ่มต้นของชนิดข้อมูล

JSON/REST ไม่มีสิ่งเหล่านี้ให้โดยอัตโนมัติ — คุณต้องบังคับใช้ความเข้ากันได้ด้วยข้อตกลง และควรมีสคีมา OpenAPI ที่ใช้ร่วมกันพร้อมการทดสอบสัญญา

message Customer {
  string id = 1;
  string email = 2;
  reserved 3;            // old 'loyalty_points', never reuse 3
  reserved "loyalty_points";
  string display_name = 4; // new field, safe additive change
}

การสตรีมข้อมูล

gRPC รองรับการเรียกสี่ประเภท ส่วน REST รองรับโดยตรงเพียงประเภทแรก:

  • แบบคำขอเดียว–คำตอบเดียว — หนึ่งคำขอ หนึ่งคำตอบ
  • การสตรีมจากเซิร์ฟเวอร์ — หนึ่งคำขอและคำตอบต่อเนื่อง (เช่น การอัปเดตแบบสด)
  • การสตรีมจากไคลเอนต์ — คำขอต่อเนื่องและคำตอบเดียว (เช่น การอัปโหลดจำนวนมาก)
  • สองทิศทาง — ทั้งสองฝ่ายสตรีมพร้อมกัน

หากกรณีใช้งานของคุณเป็นการส่งข้อมูลจากเซิร์ฟเวอร์หรือการไหลของข้อมูลที่มีอายุยาวนาน การสตรีมของ gRPC เหมาะกว่าการสำรวจจุดปลายทาง REST เป็นระยะ

การส่งต่อบริบทและกำหนดเวลาสิ้นสุด

การเรียกแบบทำงานพร้อมรอผลจะก่อตัวเป็นห่วงโซ่ ดังนั้นทุกคำขอต้องส่งข้อมูลสองอย่างไปด้วย: รหัสสหสัมพันธ์/การติดตามสำหรับการติดตามตั้งแต่ต้นจนจบ และ กำหนดเวลาสิ้นสุดเพื่อไม่ให้บริการปลายทางที่ช้าทำให้ห่วงโซ่ทั้งหมดค้าง gRPC รองรับกำหนดเวลาสิ้นสุดโดยตรง ส่วน REST จำลองสิ่งนี้ด้วยงบระยะหมดเวลาที่ลดลงและส่งต่อไปยังบริการถัดไป

<?php
// REST: shrink the remaining budget as the call chain deepens
function forwardHeaders(array $incoming, float $remainingMs): array {
    return [
        'X-Correlation-Id' => $incoming['X-Correlation-Id'] ?? bin2hex(random_bytes(8)),
        // downstream must finish within what's left of our budget
        'X-Timeout-Ms'     => (string) max(0, (int) $remainingMs),
    ];
}
print_r(forwardHeaders(['X-Correlation-Id' => 'trace-9'], 1500));

การเลือกระหว่างสองแบบ

แนวทางตัดสินใจที่ใช้ได้จริง:

  • REST สำหรับ API สาธารณะ/พาร์ทเนอร์ ไคลเอนต์เบราว์เซอร์ การดำเนินการพื้นฐานกับข้อมูล การแก้จุดบกพร่องที่ง่าย และการรองรับแคชอย่างกว้างขวาง
  • gRPC สำหรับการเรียกใช้ระหว่างบริการภายในที่มีปริมาณสูงและเวลาแฝงต่ำ สัญญาที่กำหนดชนิดข้อมูลอย่างเข้มงวด และการสตรีมข้อมูล

หลายระบบใช้ทั้งสองแบบ: ใช้ gRPC หลังเกตเวย์ระหว่างบริการ และใช้ REST ที่ขอบระบบสำหรับโลกภายนอก อย่าบังคับให้เครื่องมือหนึ่งทำงานของอีกเครื่องมือ

ตรวจสอบอย่างรวดเร็ว

การจับคู่โพรโทคอลกับกรณีใช้งาน

สรุปทบทวน

การสื่อสารระหว่างบริการแบบทำงานพร้อมรอผล:

  • REST/JSON — ใช้งานได้ทั่วไป แก้จุดบกพร่องได้ และใช้แคชได้ รหัสสถานะคือสัญญา ควรกำหนดระยะหมดเวลาเสมอ
  • gRPC/Protobuf — เริ่มจากสัญญา ขนาดกะทัดรัด รวดเร็ว และรองรับการสตรีม สร้างสตับ PHP ที่มีชนิดข้อมูลกำกับ
  • ตัดสิน ความสามารถในการลองใหม่จากรหัสสถานะ/รหัส gRPC และอย่าลองใหม่กับข้อผิดพลาดจากผู้เรียก
  • พัฒนาสคีมาด้วยการเพิ่มเท่านั้น — ห้ามนำหมายเลขฟิลด์ Protobuf กลับมาใช้ซ้ำ
  • การใช้ REST ที่ขอบระบบและ gRPC ระหว่างบริการภายในเป็นการแบ่งหน้าที่ที่พบได้บ่อยและเหมาะสม

ถัดไป: การกำหนดเส้นทางและค้นหาตำแหน่งบริการทั้งหมดด้วยเกตเวย์และการค้นหาบริการ

คำถามที่พบบ่อย

บทเรียน “การสื่อสารระหว่างบริการ: REST และ gRPC” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การสื่อสารระหว่างบริการ: REST และ gRPC” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส PHP Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส PHP Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การสื่อสารระหว่างบริการ: REST และ gRPC”

เชื่อมต่อบริการแบบทำงานพร้อมกันอย่างมีประสิทธิภาพ คุณปฏิบัติ PHP Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน PHP Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน PHP Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การสื่อสารระหว่างบริการ: REST และ gRPC” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน PHP Academy นี้ได้ไหม

ได้ บทเรียน PHP Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. จากโมโนลิทสู่ไมโครเซอร์วิส
  2. การสื่อสารระหว่างบริการ: REST และ gRPC
  3. เกตเวย์ API และการค้นพบบริการ
  4. ความทนทาน: ตัวตัดวงจรและการลองใหม่
← กลับไปที่ PHP Academy