Differences Between r-nacos 1.x HTTP API and 2.x gRPC Protocol
r-nacos implements both a traditional 1.x HTTP OpenAPI using JSON payloads and a modern 2.x gRPC protocol using binary protobuf over HTTP/2, with the latter offering bi-directional streaming for real-time updates and superior throughput.
The r-nacos project is a Rust-based reimplementation of the Nacos server that maintains full compatibility with official Nacos SDKs. When integrating with r-nacos, you must choose between the legacy HTTP-based protocol or the newer gRPC-based protocol, each offering distinct architectural trade-offs for service discovery and configuration management.
Transport Layer and Protocol Architecture
1.x HTTP Implementation
The 1.x protocol uses standard HTTP/HTTPS transport with JSON payloads handled by the actix-web framework. Route definitions are registered under the /nacos/v1/... path prefix in src/web_config.rs, with specific implementations located in src/openapi/naming/mod.rs for service naming and src/openapi/config/mod.rs for configuration management.
Key endpoints include:
- Configuration:
GET /nacos/v1/cs/configs?dataId={id}&group={group} - Service naming:
POST /nacos/v1/ns/instancefor instance registration
2.x gRPC Implementation
The 2.x protocol operates over binary gRPC using HTTP/2, typically exposed on port 9848 (HTTP port 8848 + 1000). The server implementation in src/grpc/server.rs registers two core services: Request for unary calls and BiRequestStream for bi-directional streaming. Protobuf message definitions reside in src/grpc/nacos_proto.rs, where the Payload type serves as the core request/response container.
Message Format and Serialization
The protocols differ fundamentally in data serialization:
-
HTTP 1.x: Uses human-readable JSON request/response bodies with URL-encoded query parameters for GET requests and form-data or JSON for POST requests.
-
gRPC 2.x: Uses compact protobuf binary serialization. The
Payloadmessage structure insrc/grpc/nacos_proto.rs(lines 60-66) encapsulates all request metadata and body content, reducing wire size and parsing overhead compared to JSON.
Feature Set and Real-Time Capabilities
HTTP 1.x Limitations
The HTTP protocol provides full CRUD operations for configuration and naming but operates on simple request/response semantics. According to the source documentation, the 1.x implementation does not support UDP-based instance change notifications, limiting its ability to push real-time updates to clients.
gRPC 2.x Advantages
The gRPC protocol reimplements all 1.x APIs while adding bi-directional streaming capabilities via the BiRequestStream service defined in src/grpc/nacos_proto.rs (lines 66-73). This enables:
- Real-time instance change subscriptions
- Connection-based heartbeats (more efficient than per-instance HTTP calls)
- MCP (Microservice Configuration Protocol) message streaming
Performance Characteristics
Performance benchmarks documented in book/src/performance.md reveal significant throughput differences:
-
HTTP 1.x: Achieves approximately 4.8×10⁴ QPS for instance registration. Heartbeat operations are limited because each instance requires individual HTTP requests, creating overhead under high concurrency.
-
gRPC 2.x: Achieves >8×10⁴ QPS for heartbeats because heartbeats are connection-based rather than per-instance HTTP calls. The binary protobuf serialization and HTTP/2 multiplexing reduce latency and connection overhead for high-throughput workloads.
Server Implementation Structure
The r-nacos codebase maintains a clear separation between protocol implementations:
HTTP handlers reside under src/openapi/* and are mounted to the Actix application in src/web_config.rs via functions like config_v1_route and naming_v1_route.
gRPC handlers are organized under src/grpc/handler/* (e.g., naming_route.rs, naming_instance.rs). These handlers communicate with the core NamingActor through message passing defined in src/naming/*, ensuring business logic remains decoupled from transport concerns.
Client SDK Usage Examples
HTTP 1.x API Examples
Query a configuration using standard HTTP requests:
# Retrieve configuration
curl "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=t001&group=foo"
Register a service instance:
curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance" \
-d 'port=8000&ip=10.0.0.5&serviceName=demo.service&groupName=DEFAULT'
gRPC 2.x Client Configuration
The Rust nacos_rust_client SDK (version ≥0.3.0) supports protocol selection at build time:
use nacos_rust_client::{ClientBuilder, Protocol};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Configure for gRPC protocol on port 9848
let client = ClientBuilder::new()
.address("127.0.0.1:9848")
.protocol(Protocol::Grpc) // Selects 2.x gRPC stack
.build()
.await?;
// Fetch configuration (same logical API as HTTP)
let config = client.get_config("t001", "DEFAULT", None).await?;
println!("config content: {}", config.content);
// Register instance with automatic heartbeat streaming
client.register_instance(
"demo.service",
"DEFAULT",
"10.0.0.5".into(),
8000,
true,
).await?;
Ok(())
}
Subscribe to real-time instance changes using bi-directional streaming:
use nacos_rust_client::{ClientBuilder, Protocol};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = ClientBuilder::new()
.address("127.0.0.1:9848")
.protocol(Protocol::Grpc)
.build()
.await?;
// Stream yields InstanceChange events as they occur
let mut stream = client.subscribe_service("demo.service", "DEFAULT").await?;
while let Some(change) = stream.next().await {
println!("instance change: {:?}", change);
}
Ok(())
}
Summary
- r-nacos runs both protocols simultaneously, allowing gradual migration from HTTP to gRPC without breaking existing clients.
- 1.x HTTP uses JSON over standard HTTP ports (8848) with simple request/response semantics but lacks real-time push capabilities.
- 2.x gRPC uses binary protobuf over HTTP/2 (port 9848) with bi-directional streaming via
BiRequestStream, supporting real-time subscriptions and higher throughput (>8×10⁴ QPS vs ~4.8×10⁴ QPS). - Server implementations are separated into
src/openapi/*for HTTP andsrc/grpc/*for gRPC, both interfacing with the same core actors.
Frequently Asked Questions
Which protocol should I use for new microservices?
Use the 2.x gRPC protocol for new development if your SDK supports it. The binary serialization reduces latency, and the bi-directional streaming capability in src/grpc/nacos_proto.rs provides efficient real-time service discovery updates without polling.
Can HTTP and gRPC clients interact with the same r-nacos server simultaneously?
Yes. The r-nacos server exposes both protocols concurrently. HTTP routes defined in src/openapi/naming/mod.rs and gRPC services in src/grpc/server.rs operate on the same underlying NamingActor and configuration store, ensuring consistency across protocol boundaries.
What port does the gRPC protocol use by default?
Port 9848. The gRPC service runs on the HTTP port plus 1000 (e.g., 8848 for HTTP becomes 9848 for gRPC). This offset is standard across Nacos implementations and is configurable in client SDKs like nacos_rust_client via the address parameter.
Does the HTTP API support configuration or service change notifications?
No. The 1.x HTTP implementation in src/openapi/* handles only request/response patterns. Real-time change notifications require the 2.x gRPC protocol's BiRequestStream service, which maintains persistent HTTP/2 connections for server push capabilities.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →