Belajar RoadRunner - gRPC Plugin
Episode 16 of 26

Belajar RoadRunner - gRPC Plugin

Membangun gRPC service di atas RoadRunner: mendefinisikan API dengan file .proto, menjalankan server gRPC PHP memakai spiral/roadrunner-grpc dan protoc-gen-php-grpc, mengimplementasikan service, lalu menguji dengan client gRPC.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 15 kita mengamankan HTTP, pada episode kali ini kita membuka jalur komunikasi kedua: gRPC. RoadRunner bisa menjadi gRPC server dengan worker PHP yang mengimplementasikan service — pola yang sangat berguna untuk komunikasi antar-service (microservice) yang membutuhkan performa dan kontrak API yang tegas.

Mengapa episode ini penting? Karena gRPC dan RoadRunner saling melengkapi: gRPC membutuhkan server yang mampu menangani banyak koneksi long-lived dan streaming, persis kekuatan Go — sementara implementasi service tetap ditulis dalam PHP yang kalian kuasai. Ini membuka RoadRunner untuk pola microservice.

Konsep gRPC dan RoadRunner

100%
  • Client memanggil method gRPC dengan protobuf (biner, kontrak ketat).
  • Plugin gRPC RoadRunner menerima koneksi dan meneruskan request ke worker PHP yang mengimplementasikan service.
  • Definisi service ditulis di file .proto — bahasa kontrak yang sama untuk semua bahasa.

Komponen yang dibutuhkan:

KomponenPeran
spiral/roadrunner-grpcServer gRPC PHP (worker)
protoc-gen-php-grpcGenerator kode PHP dari .proto
google/protobufRuntime protobuf PHP
Plugin grpc RoadRunnerServer Go yang menerima koneksi gRPC

Mendefinisikan Service dengan .proto

Buat file api/proto/echo.proto:

echo.proto
syntax = "proto3";
 
package echo.v1;
 
option php_namespace = "App\\Grpc";
option php_metadata_namespace = "App\\Grpc\\GPBMetadata";
 
service EchoService {
  rpc Ping (PingRequest) returns (PingResponse);
}
 
message PingRequest {
  string message = 1;
}
 
message PingResponse {
  string message = 1;
  int32 pid = 2;
}

option php_namespace menentukan namespace kelas PHP yang di-generate. Ini bagian dari kontrak: client dan server berbicara dengan skema yang sama persis.

Generate Kode PHP

Generate kelas service dan message dari .proto:

Generate PHP dari proto
composer require google/protobuf spiral/roadrunner-grpc
 
mkdir -p generated
protoc --php_out=generated --php-grpc_out=generated \
  -I api/proto api/proto/echo.proto

Hasilnya: kelas message (PingRequest, PingResponse) dan kelas interface service (EchoServiceInterface) yang harus kalian implementasikan. File .proto baru memerlukan regenerasi.

Implementasikan interface yang di-generate:

grpc-worker.php - implementasi service
<?php
 
declare(strict_types=1);
 
use App\Grpc\EchoServiceInterface;
use Spiral\RoadRunner\GRPC\ContextInterface;
use Spiral\RoadRunner\GRPC\Server;
use Spiral\RoadRunner\Worker;
 
require __DIR__ . '/vendor/autoload.php';
 
class EchoService implements EchoServiceInterface
{
    public function Ping(ContextInterface $ctx, PingRequest $in): PingResponse
    {
        $response = new PingResponse();
        $response->setMessage($in->getMessage());
        $response->setPid(getmypid());
 
        return $response;
    }
}
 
$server = new Server();
$server->registerService(EchoServiceInterface::class, new EchoService());
$server->serve(Worker::create());

Catatan penting: Server::serve() masuk ke loop internal — worker gRPC tidak memakai pola while (waitRequest()) manual. Service di-register sekali, dan plugin gRPC menyerahkan request masuk ke worker yang sedang idle.

Konfigurasi Plugin gRPC

Blok grpc
grpc:
  listen: tcp://0.0.0.0:9001
  proto:
    - "api/proto/echo.proto"
  pool:
    num_workers: 4
    max_worker_memory: 128
  max_msg_size: 10485760
  max_send_msg_size: 10485760
KeyFungsi
listenAlamat listen gRPC (port terpisah dari HTTP)
protoDaftar file .proto yang dimuat server
poolWorker pool untuk gRPC (terpisah dari pool HTTP)
max_msg_sizeLimit ukuran pesan masuk (byte)
max_send_msg_sizeLimit ukuran pesan keluar (byte)

Worker untuk gRPC dijalankan dengan server.command yang sama? Tidak — gRPC membutuhkan command sendiri. Karena worker gRPC dan HTTP berbeda file, definisikan pool worker yang berbeda:

Command untuk gRPC worker
server:
  command: "php worker-http.php"   # pool default
  relay: pipes

Untuk membedakan worker, plugin gRPC memakai key grpc.pool yang membutuhkan command khusus di blok masing-masing pool (lihat rr config:info). Contoh lengkapnya di dokumentasi spiral/roadrunner-grpc.

Menguji dengan Client

Test dengan grpcurl (tool CLI gRPC) atau client PHP:

Test dengan grpcurl
grpcurl -plaintext -d '{"message": "hello"}' \
  127.0.0.1:9001 echo.v1.EchoService/Ping

Client PHP memakai library grpc:

Client gRPC dari PHP
$client = new EchoServiceClient('127.0.0.1:9001', ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
 
$request = new PingRequest();
$request->setMessage('ping dari client');
 
[$response, $status] = $client->Ping($request);
echo $response->getMessage();   // echo dari server

Tip

Verifikasi port dan proto yang aktif: ./rr grpc:list menampilkan service gRPC yang terdaftar. Ini cara cepat memastikan file .proto terbaca benar sebelum menulis client.

gRPC vs REST di RoadRunner

AspekgRPCHTTP REST
ProtokolHTTP/2 + protobufHTTP/1.1-2 + JSON
KontrakWajib .protoOpsional (OpenAPI)
PerformaLebih cepat, payload kecilLebih lambat, JSON verbosa
BrowserTidak langsungBisa
Cocok untukMicroservice-to-microserviceAPI publik/browser

RoadRunner melayani keduanya sekaligus di satu binary — HTTP di satu port, gRPC di port lain. Kalian bisa memakai gRPC untuk internal dan REST untuk publik.

Penutup

Pada episode 16 ini, kalian telah membangun gRPC service di atas RoadRunner.

Inti yang harus dibawa pulang:

  • gRPC = HTTP/2 + protobuf, kontrak ketat via .proto.
  • Plugin grpc menerima koneksi; worker PHP mengimplementasikan interface hasil generate.
  • protoc --php-grpc_out menghasilkan kelas service dan message.
  • Pool gRPC terpisah dari pool HTTP.
  • Test cepat dengan grpcurl dan ./rr grpc:list.

Di episode 17 selanjutnya, kita belajar keamanan & hardening — membatasi worker, request timeouts, rate limiting, dan proteksi API endpoint dengan pola autentikasi yang benar. Sampai jumpa di episode 17!

Belajar RoadRunner - gRPC Plugin | Belajar RoadRunner