Hello World - Basic Unary RPC
This is the simplest gRPCServer.jl example, demonstrating a basic unary RPC (single request, single response).
What You'll Learn
- Defining a proto service with a single RPC method
- Implementing a unary RPC handler
- Registering a handler with the generated codegen registration function
- Starting a gRPC server with health check and reflection
Proto Definition
// greeter.proto
syntax = "proto3";
package helloworld;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}This defines:
- A
Greeterservice in thehelloworldpackage - A single
SayHellomethod that takes a name and returns a greeting
Generate Julia Types
Load both gRPCServer and gRPCClient so one protojl run emits the messages, the client stub, and the registration functions together:
using ProtoBufusing gRPCServerimport gRPCClientmkdir("generated") # protojl requires the output directory to pre-existprotojl("greeter.proto", ".", "generated"; always_use_modules = true, add_kwarg_constructors = true)This creates the helloworld module in generated/helloworld/ with HelloRequest/HelloReply message types, the Greeter_SayHello_Client client stub, and register_Greeter!/register_Greeter_SayHello! registration functions.
Server Implementation
using gRPCServer# Include generated typesinclude("generated/helloworld/helloworld.jl")using .helloworld# Run serverfunction main() server = GRPCServer("127.0.0.1", 50051; enable_health_check = true, enable_reflection = true ) register_Greeter!(server; SayHello = (ctx, req) -> HelloReply("Hello, $(req.name)!")) @info "gRPC server starting" host="127.0.0.1" port=50051 run(server)endmain()Equivalent form — the per-RPC do-block registration registers the same RPC:
register_Greeter_SayHello!(server) do ctx, req HelloReply("Hello, $(req.name)!")endKey Concepts
Handler Function
The handler receives:
ctx::ServerContext- Request context with metadata, deadlines, and cancellationrequest::HelloRequest- The deserialized request message
The handler returns the response type directly.
Registration
The generated register_Greeter! (aggregate form) and register_Greeter_SayHello! (per-RPC form) build a MethodDescriptor and call register_method! on the server's dispatcher. Handler signatures are validated at registration time — a mismatched shape throws ArgumentError. For the underlying runtime interface (descriptors, register!, register_method!), see the API Reference.
Testing
Run the Server
cd examples/01_hello_world
julia --project=../.. server.jlCall SayHello from Julia
In a second terminal, same directory, using the generated client stub (call gRPCClient.grpc_init() once before any call):
using gRPCServerinclude("generated/helloworld/helloworld.jl")using .helloworldimport gRPCClientgRPCClient.grpc_init()client = helloworld.Greeter_SayHello_Client("127.0.0.1", 50051)resp = gRPCClient.grpc_sync_request(client, helloworld.HelloRequest("Julia"))@assert resp.message == "Hello, Julia!"println("Got: ", resp.message)List Services
grpcurl -plaintext localhost:50051 listExpected output:
grpc.health.v1.Health
grpc.reflection.v1alpha.ServerReflection
helloworld.GreeterCall SayHello
grpcurl -plaintext -d '{"name": "Julia"}' localhost:50051 helloworld.Greeter/SayHelloExpected output:
{
"message": "Hello, Julia!"
}Next Steps
Proceed to Hello Stream to learn about server streaming RPC.