# Service-to-Service Communication in KCloud-Platform-IoT: HTTP vs gRPC Implementation Guide

> Explore KCloud-Platform-IoT service to service communication. Master HTTP REST APIs and gRPC binary protocols with Nacos service discovery for efficient internal traffic routing. Learn implementation details.

- Repository: [laokou/kcloud-platform-iot](https://github.com/koushenhai/kcloud-platform-iot)
- Tags: how-to-guide
- Published: 2026-03-05

---

**KCloud-Platform-IoT employs a hybrid communication strategy that exposes public APIs via HTTP/REST while routing internal high-throughput traffic through gRPC binary protocols integrated with Nacos service discovery.**

The KCloud-Platform-IoT repository implements a sophisticated dual-protocol architecture that enables microservices to communicate efficiently across distributed IoT environments. Understanding the specific implementation patterns for **HTTP REST endpoints** versus **gRPC binary channels** is critical for optimizing performance in this Spring-based ecosystem. This article examines the source code structure, configuration mechanisms, and service discovery integration that power inter-service communication throughout the platform.

## HTTP REST Implementation with Spring MVC

The platform exposes external-facing APIs through standard Spring MVC controllers using text-based JSON payloads. These endpoints follow conventional REST patterns without built-in service discovery mechanisms.

**Transport and Protocol**  
HTTP communication relies on Spring MVC over TCP ports (typically 80 or 8080), utilizing the standard `server.port` configuration in [`application.yml`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/application.yml). Controllers are annotated with `@RestController` and handle JSON serialization through Jackson automatically.

**Service Discovery Limitations**  
Unlike the gRPC implementation, HTTP services do not leverage automatic service discovery. Services must be addressed via hard-coded URLs or environment-based host/port values, making this approach suitable for edge-facing APIs rather than internal mesh communication.

**Key Implementation Files**  
Standard REST controllers reside in service-specific web packages, such as [`laokou-service/laokou-iot/laokou-iot-adapter/src/main/java/org/laokou/iot/web/DevicesController.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/laokou-service/laokou-iot/laokou-iot-adapter/src/main/java/org/laokou/iot/web/DevicesController.java), which exposes device management endpoints to external consumers.

## gRPC Binary Communication Architecture

For internal service-to-service calls requiring low latency and high throughput, KCloud-Platform-IoT implements gRPC over HTTP/2 using Protocol Buffers for strongly typed, compact message serialization.

**Core Components**  
The gRPC stack utilizes the Spring gRPC starter (version 1.0.2) and Netty as the underlying transport. Server implementations extend generated stub classes from `*.proto` definitions, while clients inject proxies using the `@GrpcClient` annotation.

**Server-Side Implementation**  
gRPC services are exposed through classes annotated with `@GrpcService`. For example, [`GrpcServerService.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/GrpcServerService.java) demonstrates the pattern where services extend generated base classes (e.g., `SimpleGrpc.SimpleImplBase`) and implement RPC methods using `StreamObserver` for response handling.

**Configuration Properties**  
The gRPC server listens on a dedicated port configured via `spring.grpc.server.port` (defaulting to 9090). To avoid port conflicts with the HTTP server, the configuration typically sets `spring.grpc.server.servlet.enabled: false` and assigns a specific Netty port (e.g., 10111) as documented in `archive/docs/00.二开指南/02.指南/19.gRPC配置.md`.

## Nacos Service Discovery Integration

The gRPC implementation features tight integration with Nacos for dynamic service resolution, eliminating the need for hard-coded endpoint addresses.

**DiscoveryNameResolver Mechanism**  
When the application starts, [`GrpcClientConfig.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/GrpcClientConfig.java) registers a `DiscoveryNameResolverProvider` with the gRPC name resolver registry. This provider intercepts logical service names formatted as `discovery://laokou-auth` and queries Nacos for physical addresses.

**Metadata-Driven Port Resolution**  
Each gRPC server registers with Nacos including a custom metadata entry `grpc_port`. The [`DiscoveryNameResolver.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/DiscoveryNameResolver.java) class extracts this metadata to construct the complete socket address, enabling clients to resolve services without knowing the specific port numbers beforehand.

**Channel Factory Creation**  
The [`DiscoveryGrpcChannelFactory.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/DiscoveryGrpcChannelFactory.java) creates Netty channels using the resolved addresses, applying any configured `ClientInterceptors` and `GrpcChannelBuilderCustomizer` implementations for TLS or retry policies.

## Client-Side Injection Pattern

Developers consume gRPC services through dependency injection managed by [`GrpcClientBeanPostProcessor.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/GrpcClientBeanPostProcessor.java).

**Annotation-Based Stub Injection**  
Fields annotated with `@GrpcClient(serviceId = "laokou-common-grpc")` trigger the post-processor to create concrete blocking or async stubs. The processor resolves the service ID through the discovery mechanism and constructs the channel using the factory beans defined in [`GrpcClientConfig.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/GrpcClientConfig.java).

```java
@Service
public class GreetingClient {
    @GrpcClient(serviceId = "laokou-common-grpc")
    private SimpleGrpc.SimpleBlockingStub helloStub;

    public String greet(String name) {
        var req = HelloWorldProto.Request.newBuilder().setName(name).build();
        var resp = helloStub.hello(req);
        return resp.getMessage();
    }
}

```

## Performance and Use Case Comparison

The platform deliberately separates traffic based on consumption patterns and performance requirements.

**HTTP/JSON Characteristics**  
- **Latency**: Higher due to text-based JSON parsing and HTTP/1.1 framing overhead  
- **Payload Size**: Larger text representations increase network bandwidth  
- **Tooling**: Standard Swagger integration for API documentation and browser compatibility  
- **Use Cases**: Public APIs, UI-oriented services, and simple CRUD operations exposed to external clients

**gRPC/Protobuf Characteristics**  
- **Latency**: Lower through binary serialization and HTTP/2 multiplexing  
- **Flow Control**: Built-in backpressure management via HTTP/2 windowing  
- **Type Safety**: Strongly typed contracts via Protocol Buffer definitions  
- **Use Cases**: High-throughput internal calls such as distributed ID generation, real-time telemetry ingestion, and inter-service orchestration requiring sub-millisecond response times

## Configuration Examples

**HTTP Server Configuration**  

```yaml
server:
  port: 8080

```

**gRPC Server Configuration**  

```yaml
spring:
  grpc:
    server:
      port: 9090
      servlet:
        enabled: false

```

**gRPC Service Implementation**  

```java
@GrpcService
public class HelloWorldService extends SimpleGrpc.SimpleImplBase {
    @Override
    public void hello(HelloWorldProto.Request request,
                      StreamObserver<HelloWorldProto.Response> responseObserver) {
        responseObserver.onNext(
            HelloWorldProto.Response.newBuilder()
                .setMessage("Hello, " + request.getName())
                .build());
        responseObserver.onCompleted();
    }
}

```

**Discovery Configuration**  

```java
@Configuration(proxyBeanMethods = false)
public class GrpcClientConfig {

    @Bean
    GrpcClientBeanPostProcessor grpcClientBeanPostProcessor(
            GrpcClientFactory factory,
            DiscoveryClient discoveryClient,
            ExecutorService executor) {
        NameResolverRegistry.getDefaultRegistry()
            .register(new DiscoveryNameResolverProvider(discoveryClient, executor));
        return new GrpcClientBeanPostProcessor(factory);
    }

    @Bean
    DiscoveryGrpcChannelFactory discoveryGrpcChannelFactory(
            List<GrpcChannelBuilderCustomizer<NettyChannelBuilder>> customizers,
            ClientInterceptorsConfigurer interceptors) {
        return new DiscoveryGrpcChannelFactory(customizers, interceptors);
    }
}

```

## Summary

- **KCloud-Platform-IoT** implements a dual-protocol architecture using HTTP for external APIs and gRPC for internal service mesh communication.
- **HTTP endpoints** reside in standard Spring MVC controllers (`*Controller.java`) without automatic service discovery, relying on explicit URL configuration.
- **gRPC services** use `@GrpcService` annotated classes with Protocol Buffer contracts, listening on dedicated ports (default 9090 or custom 10111) via Netty.
- **Nacos integration** enables dynamic service resolution through [`DiscoveryNameResolver.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/DiscoveryNameResolver.java), which extracts `grpc_port` metadata to route requests to the correct endpoint.
- **Client injection** relies on `@GrpcClient` annotations processed by [`GrpcClientBeanPostProcessor.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/GrpcClientBeanPostProcessor.java) to create type-safe stubs bound to logical service names like `discovery://laokou-auth`.
- The architecture optimizes for both developer experience (HTTP/JSON for external integration) and runtime performance (gRPC binary for internal high-throughput scenarios).

## Frequently Asked Questions

### When should I use HTTP versus gRPC for service-to-service communication in KCloud-Platform-IoT?

Use **HTTP REST** when exposing APIs to external clients, browser-based UIs, or third-party integrations where human-readable JSON and standard HTTP tooling are required. Use **gRPC** for internal microservice calls requiring high throughput, low latency, or strongly typed contracts—particularly for IoT device telemetry processing and distributed transaction coordination.

### How does gRPC service discovery work with Nacos in this platform?

The `DiscoveryNameResolverProvider` registers a custom resolver that intercepts URLs prefixed with `discovery://`. When a client requests a connection to `discovery://laokou-auth`, the `DiscoveryNameResolver` queries Nacos for instances of that service, extracts the `grpc_port` from each instance's metadata, and returns the socket addresses to the gRPC channel builder.

### What ports are typically used in KCloud-Platform-IoT for HTTP and gRPC services?

HTTP services typically use port **8080** (configured via `server.port`), while gRPC servers default to port **9090** (via `spring.grpc.server.port`). For dedicated Netty deployment without servlet container interference, the platform often configures port **10111** with `spring.grpc.server.servlet.enabled: false`.

### How do I implement a gRPC client in my Spring service?

Annotate a field with `@GrpcClient(serviceId = "target-service-name")` where the service ID matches the Nacos-registered name. Ensure your configuration class imports [`GrpcClientConfig.java`](https://github.com/koushenhai/kcloud-platform-iot/blob/main/GrpcClientConfig.java) to register the discovery resolver. The `GrpcClientBeanPostProcessor` automatically creates and injects a blocking or async stub instance using the generated protobuf classes from the service's `*.proto` definitions.