This page details the gRPC service implementation for the Agent Infrastructure, covering client channel configuration, service definitions, method handlers, and generated stub factories. It serves as the primary communication layer between the control plane and distributed agents, facilitating both standard RPC calls and bidirectional streaming.
Architecture Overview
The gRPC implementation is divided into two main components: the Spring-managed client configuration that establishes the connection, and the generated service stubs that define the API contract.
Client Configuration
The GrpcConfiguration class provides a Spring-managed ManagedChannel bean using Netty. It handles connection establishment, security interceptors, and lifecycle management.
Channel Setup
The channel is built using NettyChannelBuilder and relies on application properties for routing.
@Configuration
public class GrpcConfiguration {
private ManagedChannel channel;
@Value("${grpc.server.address}")
private String serverAddress;
@Value("${grpc.server.port}")
private Integer serverPort;
@Bean
public ManagedChannel managedChannel() throws SSLException {
this.channel = NettyChannelBuilder
.forAddress(serverAddress, serverPort)
.intercept(new GrpcInterceptor())
.sslContext(GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build())
.build();
return this.channel;
}
@PreDestroy
public void shutdownChannel() {
this.channel.shutdown();
}
}Security Notice: The current configuration uses InsecureTrustManagerFactory.INSTANCE, which blindly trusts all SSL certificates. This is suitable for development or internal cluster communication but must be replaced with a proper trust manager containing valid CA certificates before deploying to production environments.
The @PreDestroy annotation ensures that the ManagedChannel is gracefully shut down when the Spring application context closes, preventing resource leaks and dangling connections.
Configuration Properties
Ensure the following properties are set in your application.yml or environment variables:
Service Definition (AgentService)
The AgentService defines the contract for agent lifecycle management and command execution. The service name is registered internally as agent.AgentService.
Available RPC Methods
Client Stubs
The generated AgentServiceGrpc class provides three types of client stubs to accommodate different asynchronous programming models.
Class: AgentServiceBlockingStub
Used for standard, synchronous execution where the calling thread blocks until the server responds. Ideal for simple scripts or background workers where thread blocking is acceptable.
AgentServiceBlockingStub stub = AgentServiceGrpc.newBlockingStub(channel);
AuthResponse response = stub.registerAgent(agentRequest);Class: AgentServiceStub
Used for fully asynchronous, non-blocking execution using StreamObserver callbacks. This is required for the AgentStream bidirectional streaming method.
AgentServiceStub asyncStub = AgentServiceGrpc.newStub(channel);
asyncStub.registerAgent(agentRequest, new StreamObserver<AuthResponse>() {
@Override
public void onNext(AuthResponse response) { /* Handle success */ }
@Override
public void onError(Throwable t) { /* Handle error */ }
@Override
public void onCompleted() { /* Handle completion */ }
});Class: AgentServiceFutureStub
Returns a Guava ListenableFuture. Useful when integrating gRPC calls into existing reactive pipelines or when you need to chain multiple asynchronous operations together.
AgentServiceFutureStub futureStub = AgentServiceGrpc.newFutureStub(channel);
ListenableFuture<AuthResponse> future = futureStub.registerAgent(agentRequest);Consuming the Service
To consume the AgentService within your Spring application, follow these steps:
Ensure the GrpcConfiguration is loaded in your context, and autowire the ManagedChannel into your service class.
Create the appropriate stub (Blocking, Async, or Future) using the injected channel. It is recommended to do this during bean initialization rather than per-request.
Build your protobuf request objects (e.g., AgentRequest.newBuilder().build()).
Invoke the method on the stub. The GrpcInterceptor will automatically attach any necessary authentication headers or tracing IDs to the outgoing request.
Server Implementation Details
If you are implementing the server side of this contract, you must extend the generated AgentServiceImplBase class and override the default methods.
By default, all methods in AgentServiceImplBase throw an UNIMPLEMENTED gRPC status exception. You must explicitly override and implement the logic for each method you intend to support.
@GrpcService
public class AgentServiceImpl extends AgentServiceGrpc.AgentServiceImplBase {
@Override
public void registerAgent(AgentRequest request, StreamObserver<AuthResponse> responseObserver) {
// 1. Process the request
// 2. Build the response
AuthResponse response = AuthResponse.newBuilder().setToken("...").build();
// 3. Send response and complete
responseObserver.onNext(response);
responseObserver.onCompleted();
}
// Implement other methods...
}