# Differences Between r-nacos 1.x HTTP API and 2.x gRPC Protocol

> Explore r-nacos 1.x HTTP API vs 2.x gRPC protocol. Understand the shift to protobuf, HTTP/2, and real-time streaming for enhanced performance in your Nacos implementations.

- Repository: [Nacos Group/r-nacos](https://github.com/nacos-group/r-nacos)
- Tags: deep-dive
- Published: 2026-03-07

---

**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`](https://github.com/nacos-group/r-nacos/blob/main/src/web_config.rs), with specific implementations located in [`src/openapi/naming/mod.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/openapi/naming/mod.rs) for service naming and [`src/openapi/config/mod.rs`](https://github.com/nacos-group/r-nacos/blob/main/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/instance` for 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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/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 `Payload` message structure in [`src/grpc/nacos_proto.rs`](https://github.com/nacos-group/r-nacos/blob/main/src/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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/naming_route.rs), [`naming_instance.rs`](https://github.com/nacos-group/r-nacos/blob/main/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:

```bash

# Retrieve configuration

curl "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=t001&group=foo"

```

Register a service instance:

```bash
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:

```rust
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:

```rust
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 and `src/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`](https://github.com/nacos-group/r-nacos/blob/main/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`](https://github.com/nacos-group/r-nacos/blob/main/src/openapi/naming/mod.rs) and gRPC services in [`src/grpc/server.rs`](https://github.com/nacos-group/r-nacos/blob/main/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.