1. Pengantar
Dalam codelab ini, Anda akan menggunakan gRPC-Rust untuk membuat klien dan server yang menjadi dasar aplikasi pemetaan rute yang ditulis dalam Rust.
Pada akhir tutorial ini, Anda akan memiliki klien yang terhubung ke server jarak jauh menggunakanImplementasi resmi Rust dari protokol gRPC untuk mengambil nama atau alamat pos suatu lokasi pada koordinat tertentu di peta. Aplikasi yang lengkap mungkin menggunakan desain klien-server ini untuk menghitung atau meringkas titik-titik menarik di sepanjang suatu rute.
Layanan tersebut didefinisikan dalam file Protocol Buffers, yang akan digunakan untuk menghasilkan kode dasar untuk klien dan server sehingga mereka dapat berkomunikasi satu sama lain, menghemat waktu dan upaya Anda dalam mengimplementasikan fungsionalitas tersebut.
Kode yang dihasilkan ini tidak hanya menangani kompleksitas komunikasi antara server dan klien, tetapi juga serialisasi dan deserialisasi data.
Yang akan Anda pelajari
- Cara menggunakan Protocol Buffers untuk mendefinisikan API layanan.
- Cara membangun klien berbasis gRPC dari definisi Protocol Buffer menggunakan pembuatan kode otomatis.
- Pemahaman tentang komunikasi klien-server dengan gRPC.
Codelab ini ditujukan bagi pengembang Rust yang baru mengenal gRPC atau ingin menyegarkan kembali pengetahuan mereka tentang gRPC, atau siapa pun yang tertarik membangun sistem terdistribusi. Tidak diperlukan pengalaman gRPC sebelumnya.
2. Sebelum memulai
Prasyarat
Pastikan Anda telah menginstal hal-hal berikut:
- GCC. Ikuti petunjuk di sini.
- Git: petunjuk instalasi di sini.
- Karat, versi 1.88.0. Ikuti petunjuk instalasi di sini.
Mendapatkan kode
Agar Anda tidak perlu memulai semuanya dari awal, codelab ini menyediakan kerangka kode sumber aplikasi untuk Anda lengkapi. Langkah-langkah berikut akan menunjukkan kepada Anda cara menyelesaikan aplikasi, termasuk menggunakan plugin kompilator protokol buffer untuk menghasilkan kode gRPC dasar.
Pertama, buat direktori kerja codelab dan masuk ke dalamnya:
mkdir grpc-rust-getting-started && cd grpc-rust-getting-started
Unduh dan ekstrak codelab:
curl -sL https://github.com/grpc-ecosystem/grpc-codelabs/archive/refs/heads/2026.tar.gz \
| tar xvz --strip-components=4 \
grpc-codelabs-2026/codelabs/grpc-rust-getting-started/start_here
Alternatifnya, Anda dapat mengunduh file .zip yang hanya berisi direktori codelab dan mengekstraknya secara manual.
Kode sumber lengkapnya tersedia di GitHub jika Anda ingin melewatkan pengetikan implementasi.
3. Definisikan layanan tersebut
Langkah pertama Anda adalah mendefinisikan layanan gRPC aplikasi, metode RPC-nya, dan tipe pesan permintaan dan responsnya menggunakan Protocol Buffers. Layanan Anda akan menyediakan:
- Metode RPC bernama
GetFeatureyang diimplementasikan oleh server dan dipanggil oleh klien. - Tipe pesan
PointdanFeatureyang merupakan struktur data yang dipertukarkan antara klien dan server saat menggunakan metodeGetFeature. Klien memberikan koordinat peta sebagaiPointdalam permintaanGetFeatureke server, dan server membalas denganFeatureyang sesuai yang menjelaskan apa pun yang terletak di koordinat tersebut.
Metode RPC ini dan tipe pesannya akan didefinisikan dalam file proto/routeguide.proto dari kode sumber yang disediakan.
Protocol Buffers umumnya dikenal sebagai protobufs. Untuk informasi lebih lanjut mengenai terminologi gRPC, lihat Konsep inti, arsitektur, dan siklus hidup gRPC.
Metode layanan
Pertama, mari kita tentukan metode layanan, lalu tentukan jenis pesan Point dan Feature. File proto/routeguide.proto memiliki struktur service bernama RouteGuide yang mendefinisikan satu atau lebih metode yang disediakan oleh layanan aplikasi.
Tambahkan metode rpc GetFeature di dalam definisi RouteGuide. Seperti yang dijelaskan sebelumnya, metode ini akan mencari nama atau alamat suatu lokasi dari sekumpulan koordinat yang diberikan, sehingga GetFeature mengembalikan Feature untuk Point yang diberikan:
service RouteGuide {
// Definition of the service goes here
// Obtains the feature at a given position.
rpc GetFeature(Point) returns (Feature) {}
}
Ini adalah metode RPC unary: sebuah RPC sederhana di mana klien mengirimkan permintaan ke server dan menunggu respons kembali, sama seperti panggilan fungsi lokal.
Jenis pesan
Dalam berkas proto/routeguide.proto kode sumber, pertama-tama definisikan tipe pesan Point. A Point mewakili pasangan koordinat lintang-bujur pada peta. Untuk codelab ini, gunakan bilangan bulat untuk koordinat:
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
Angka 1 dan 2 adalah nomor ID unik untuk setiap bidang dalam struktur message.
Selanjutnya, tentukan tipe pesan Feature. Sebuah Feature menggunakan bidang string untuk nama atau alamat pos sesuatu di lokasi yang ditentukan oleh sebuah Point:
message Feature {
// The name or address of the feature.
string name = 1;
// The point where the feature is located.
Point location = 2;
}
4. Buat kode klien dan server
Kami telah memberikan kode yang dihasilkan dari file .proto di direktori generated/, termasuk semua tambahan yang Anda buat di atas. Namun, kami ingin meluangkan waktu sejenak untuk menjelaskan cara kerja pembuatan kode.
File .proto kami menjelaskan semua struktur dan fungsi yang digunakan oleh klien atau server. Kami menggunakan skrip pembuatan Cargo (build.rs) bersama dengan crate grpc-protobuf-build untuk secara otomatis menghasilkan kode ini.
Di Cargo.toml kita menambahkan grpc-protobuf-build di bawah [build-dependencies].
Di build.rs, kita mengkonfigurasi grpc_protobuf_build::CodeGen untuk mengkompilasi proto/routeguide.proto ke dalam direktori generated/. Berikut poin-poin pentingnya:
grpc_protobuf_build::CodeGen::new()
.include("proto")
.input("routeguide.proto")
.output_dir("generated")
.compile()
.unwrap();
Ini memanggil pembuatan kode crate grpc_protobuf_build, dengan meneruskan routeguide.proto kepadanya. Kami telah membungkus ini dalam beberapa kode agar hanya berjalan ketika sebuah feature flag dilewatkan, sehingga hanya akan dibuat ulang saat Anda menginginkannya. Anda tidak perlu menjalankannya sekarang, karena kami sudah membuatkan kodenya untuk Anda.
cargo build --bin routeguide-server --features regenerate_proto
Saat Anda menjalankan cargo build, build.rs mengkompilasi definisi buffer protokol ke dalam direktori generate/, termasuk:
- Definisi struktur untuk tipe pesan
PointdanFeature. - Salah satu ciri layanan Tonic yang perlu kita implementasikan untuk server:
route_guide_server::RouteGuide. - Tipe klien gRPC-Rust yang akan kita gunakan untuk memanggil server:
route_guide_client::RouteGuideClient<T>.
Anda dapat merujuk ke protoc-gen-rust-grpc guide untuk informasi lebih lanjut.
Selanjutnya, kita akan mengimplementasikan metode layanan di server.
5. Menerapkan layanan
Di src/server/server.rs, kita dapat membawa kode yang dihasilkan ke dalam cakupan melalui makro include_generated_proto! gRPC dan mengimpor trait RouteGuide dan Point.
mod grpc_pb {
grpc::include_generated_proto!("generated", "routeguide");
}
use grpc_pb::{
route_guide_server::{RouteGuideServer, RouteGuide},
Point, Feature,
};
Kita bisa mulai dengan mendefinisikan sebuah struct untuk mewakili layanan kita, kita bisa melakukannya pada src/server/server.rs untuk saat ini:
#[derive(Debug)]
pub struct RouteGuideService {
features: Vec<Feature>,
}
Sekarang, kita perlu mengimplementasikan trait route_guide_server::RouteGuide dari kode yang dihasilkan.
RPC Unary Sederhana
RouteGuideService mengimplementasikan semua metode layanan kami. Fungsi get_feature di sisi server adalah tempat pekerjaan utama dilakukan: fungsi ini menerima pesan Point dari klien dan mengembalikan informasi lokasi yang sesuai dari daftar tempat yang dikenal dalam pesan Feature. Berikut implementasi fungsi tersebut di src/server/server.rs:
#[tonic::async_trait]
impl RouteGuide for RouteGuideService {
async fn get_feature(&self, request: Request<Point>) -> Result<Response<Feature>, Status> {
println!("GetFeature = {:?}", request);
let requested_point = request.get_ref();
for feature in self.features.iter() {
if feature.location().latitude() == requested_point.latitude() {
if feature.location().longitude() == requested_point.longitude(){
return Ok(Response::new(feature.clone()))
};
};
}
Ok(Response::new(Feature::default()))
}
}
Setelah kita menerapkan metode ini, kita juga perlu menjalankan server gRPC agar klien dapat menggunakan layanan kita. Ganti main()dengan ini.
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let addr = "[::1]:10000".parse().unwrap();
println!("RouteGuideServer listening on: {addr}");
let route_guide = RouteGuideService {
features: load(),
};
let svc = RouteGuideServer::new(route_guide);
Server::builder().add_service(svc).serve(addr).await?;
Ok(())
}
Berikut yang terjadi di main(), langkah demi langkah:
- Tentukan port yang ingin kita gunakan untuk mendengarkan permintaan klien.
- Buat
RouteGuideServicedengan fitur yang dimuat dengan memanggil fungsi pembantuload() - Buat instance server gRPC menggunakan
RouteGuideServer::new()dengan menggunakan layanan yang telah kita buat. - Daftarkan implementasi layanan kami ke server gRPC.
- Panggil
serve()pada server dengan detail port kita untuk melakukan penantian pemblokiran hingga proses dihentikan.
6. Buat klien
Di bagian ini, kita akan melihat cara membuat klien Rust untuk layanan RouteGuide kita di src/client/client.rs.
Seperti yang kita lakukan di src/server/server.rs, kita dapat membawa kode yang dihasilkan ke dalam cakupan melalui makro include_generated_proto! gRPC dan mengimpor tipe RouteGuideClient.
mod grpc_pb {
grpc::include_generated_proto!("generated", "routeguide");
}
use grpc_pb::{
route_guide_client::RouteGuideClient,
Point,
};
Metode layanan panggilan
Dalam gRPC-Rust, RPC bersifat asinkron dan non-blocking, menggunakan sintaks async/await Rust untuk menunggu respons dari server.
Untuk memanggil metode layanan, pertama-tama kita membuat Channel menggunakan Channel::builder(), dengan menentukan alamat server (dns:///[::1]:10000) dan kredensial koneksi (LocalChannelCredentials). Kemudian kita meneruskan saluran tersebut ke RouteGuideClient::new() untuk menginstansiasi klien kita:
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new gRPC channel
let channel = Channel::builder(
"dns:///[::1]:10000",
Arc::new(LocalChannelCredentials::new()),
)
.build();
// Create a new client
let client = RouteGuideClient::new(channel);
}
Dalam fungsi ini, RouteGuideClient::new() mengikat saluran generik ke stub klien yang dihasilkan yang mengimplementasikan metode yang didefinisikan dalam definisi layanan .proto kita.
RPC Sederhana
Memanggil RPC sederhana GetFeature sama mudahnya dengan memanggil metode lokal. Tambahkan ini di main():
println!("*** SIMPLE RPC ***");
let point = proto!(Point {
latitude: 409_146_138,
longitude: -746_188_906,
});
let response = client
.get_feature(point)
.await
.expect("RPC error");
Dalam gRPC-Rust, kita meneruskan pesan protobuf Point langsung ke client.get_feature(point). Menunggu future yang dikembalikan akan menghasilkan respons Feature secara langsung, tanpa perlu panggilan metode lebih lanjut.
Selanjutnya, cetak kolom-kolom dari respons tersebut:
println!(
"Response = Name = \"{}\", Latitude = {}, Longitude = {}",
response.name(),
response.location().latitude(),
response.location().longitude()
);
Secara keseluruhan, fungsi main() klien seharusnya terlihat seperti ini:
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Create a new gRPC channel
let channel = Channel::builder(
"dns:///[::1]:10000",
Arc::new(LocalChannelCredentials::new()),
)
.build();
// 2. Instantiate the generated RouteGuideClient
let client = RouteGuideClient::new(channel);
println!("*** SIMPLE RPC ***");
let point = proto!(Point {
latitude: 409_146_138,
longitude: -746_188_906,
});
let response = client
.get_feature(point)
.await
.expect("RPC error");
println!(
"Response = Name = \"{}\", Latitude = {}, Longitude = {}",
response.name(),
response.location().latitude(),
response.location().longitude()
);
Ok(())
}
7. Cobalah
Untuk menjalankan klien dan server Anda, pertama-tama verifikasi bahwa kedua target biner telah didefinisikan di Cargo.toml:
[[bin]]
name = "routeguide-server"
path = "src/server/server.rs"
[[bin]]
name = "routeguide-client"
path = "src/client/client.rs"
Kemudian, jalankan perintah-perintah berikut dari direktori kerja kita:
- Jalankan server di satu terminal:
cargo run --bin routeguide-server
- Jalankan klien dari terminal lain:
cargo run --bin routeguide-client
Anda akan melihat output seperti ini, dengan stempel waktu yang dihilangkan agar lebih jelas:
*** SIMPLE RPC ***
Response = Name = "Berkshire Valley Management Area Trail, Jefferson, NJ, USA", Latitude = 409146138, Longitude = -746188906
8. Langkah berikutnya
- Lanjutkan ke codelab Mulai Menggunakan gRPC-Rust (Streaming).
- Pelajari Repositori gRPC-Rust resmi.
- Pelajari arsitektur gRPC lebih lanjut di Konsep Inti.
- Lihat dokumentasi gRPC-Rust di gRPC.io.
9. Kontributor Codelab ini
- Cathy Zhao
- Lucio Franco
- Arvind Bright
- Nathaniel Ford