Quarkus gRPC extension that enables implementing and consuming gRPC services with reactive and imperative programming models.
—
Server and client configuration with customization hooks for advanced use cases including TLS, load balancing, and performance tuning. The configuration system provides comprehensive control over gRPC behavior.
Allows customization of gRPC server building process. Implement this interface to customize server configuration beyond what's available through standard configuration properties.
/**
* Allow for customization of Server building.
* Implement the customize method, depending on which ServerBuilder implementation you're going to use,
* e.g. Vert.x or Netty.
* This is an experimental API, subject to change.
*/
public interface ServerBuilderCustomizer<T extends ServerBuilder<T>> {
/**
* Customize a ServerBuilder instance.
*
* @param config server's configuration
* @param builder Server builder instance
*/
default void customize(GrpcServerConfiguration config, T builder) {
}
/**
* Customize a GrpcServerOptions instance.
*
* @param config server's configuration
* @param options GrpcServerOptions instance
*/
default void customize(GrpcServerConfiguration config, GrpcServerOptions options) {
}
/**
* Priority by which the customizers are applied.
* Higher priority is applied later.
*
* @return the priority
*/
default int priority() {
return 0;
}
}Usage Examples:
import io.quarkus.grpc.api.ServerBuilderCustomizer;
import io.grpc.netty.NettyServerBuilder;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class CustomServerBuilder implements ServerBuilderCustomizer<NettyServerBuilder> {
@Override
public void customize(GrpcServerConfiguration config, NettyServerBuilder builder) {
// Customize Netty server builder
builder.maxInboundMessageSize(4 * 1024 * 1024) // 4MB
.maxInboundMetadataSize(8 * 1024) // 8KB
.keepAliveTime(30, TimeUnit.SECONDS)
.keepAliveTimeout(10, TimeUnit.SECONDS)
.permitKeepAliveWithoutCalls(true)
.maxConnectionIdle(5, TimeUnit.MINUTES);
}
@Override
public void customize(GrpcServerConfiguration config, GrpcServerOptions options) {
// Customize Vert.x gRPC server options
options.setMaxMessageSize(4 * 1024 * 1024);
options.setKeepAliveTime(30000); // 30 seconds
options.setKeepAliveTimeout(10000); // 10 seconds
}
@Override
public int priority() {
return 100; // Higher priority than default customizers
}
}Allows customization of gRPC channel building process for clients. Implement this interface to customize client configuration beyond standard configuration options.
/**
* Allow for customization of Channel building.
* Implement the customize method, depending on which Channel implementation you're going to use,
* e.g. Vert.x or Netty.
* This is an experimental API, subject to change.
*/
public interface ChannelBuilderCustomizer<T extends ManagedChannelBuilder<T>> {
/**
* Customize a ManagedChannelBuilder instance.
*
* @param name gRPC client name
* @param config client's configuration
* @param builder Channel builder instance
* @return map of config properties to be used as default service config against the builder
*/
default Map<String, Object> customize(String name,
GrpcClientConfiguration config,
T builder) {
return Map.of();
}
/**
* Customize a GrpcClientOptions instance.
*
* @param name gRPC client name
* @param config client's configuration
* @param options GrpcClientOptions instance
*/
default void customize(String name,
GrpcClientConfiguration config,
GrpcClientOptions options) {
}
/**
* Priority by which the customizers are applied.
* Higher priority is applied later.
*
* @return the priority
*/
default int priority() {
return 0;
}
}Usage Examples:
import io.quarkus.grpc.api.ChannelBuilderCustomizer;
import io.grpc.netty.NettyChannelBuilder;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.Map;
@ApplicationScoped
public class CustomChannelBuilder implements ChannelBuilderCustomizer<NettyChannelBuilder> {
@Override
public Map<String, Object> customize(String name,
GrpcClientConfiguration config,
NettyChannelBuilder builder) {
// Customize based on client name
if ("high-throughput-service".equals(name)) {
builder.maxInboundMessageSize(16 * 1024 * 1024) // 16MB
.maxInboundMetadataSize(16 * 1024) // 16KB
.keepAliveTime(15, TimeUnit.SECONDS)
.keepAliveWithoutCalls(true);
} else {
builder.maxInboundMessageSize(4 * 1024 * 1024) // 4MB
.keepAliveTime(30, TimeUnit.SECONDS);
}
// Return service config for load balancing
return Map.of(
"loadBalancingConfig", Map.of(
"round_robin", Map.of()
),
"retryPolicy", Map.of(
"maxAttempts", 3,
"initialBackoff", "1s",
"maxBackoff", "10s",
"backoffMultiplier", 2.0,
"retryableStatusCodes", List.of("UNAVAILABLE", "DEADLINE_EXCEEDED")
)
);
}
@Override
public void customize(String name,
GrpcClientConfiguration config,
GrpcClientOptions options) {
// Customize Vert.x gRPC client options
options.setMaxMessageSize(4 * 1024 * 1024);
options.setKeepAliveTime(30000);
if ("secure-service".equals(name)) {
options.setSsl(true);
options.setTrustAll(false);
}
}
@Override
public int priority() {
return 50;
}
}Core configuration classes for gRPC server and client settings:
public class GrpcConfiguration {
// Root gRPC configuration
}
public class GrpcServerConfiguration {
// Server-specific configuration including port, TLS, etc.
}
public class GrpcClientConfiguration {
// Client-specific configuration including host, port, TLS, etc.
}# Basic server configuration
quarkus.grpc.server.port=9000
quarkus.grpc.server.host=0.0.0.0
# TLS configuration
quarkus.grpc.server.ssl.certificate=path/to/server.crt
quarkus.grpc.server.ssl.key=path/to/server.key
quarkus.grpc.server.ssl.key-store=path/to/keystore.p12
quarkus.grpc.server.ssl.key-store-password=secret
# Performance tuning
quarkus.grpc.server.max-inbound-message-size=4194304
quarkus.grpc.server.max-inbound-metadata-size=8192
quarkus.grpc.server.keep-alive-time=30s
quarkus.grpc.server.keep-alive-timeout=10s
# Development settings
quarkus.grpc.server.reflection.enabled=true
quarkus.grpc.server.health.enabled=true# User service client
quarkus.grpc.clients.user-service.host=user-service.example.com
quarkus.grpc.clients.user-service.port=443
quarkus.grpc.clients.user-service.ssl.trust-store=path/to/truststore.p12
quarkus.grpc.clients.user-service.ssl.trust-store-password=secret
quarkus.grpc.clients.user-service.deadline=10s
# Payment service client with load balancing
quarkus.grpc.clients.payment-service.host=payment-service
quarkus.grpc.clients.payment-service.port=9000
quarkus.grpc.clients.payment-service.load-balancing-policy=round_robin
quarkus.grpc.clients.payment-service.max-retry-attempts=3
# Local development client
quarkus.grpc.clients.local-service.host=localhost
quarkus.grpc.clients.local-service.port=9001
quarkus.grpc.clients.local-service.plain-text=true@ApplicationScoped
public class TlsCustomizer implements ServerBuilderCustomizer<NettyServerBuilder> {
@Override
public void customize(GrpcServerConfiguration config, NettyServerBuilder builder) {
try {
// Custom SSL context
SslContextBuilder sslContextBuilder = SslContextBuilder.forServer(
new File("path/to/server.crt"),
new File("path/to/server.key")
);
// Configure client authentication
sslContextBuilder.clientAuth(ClientAuth.REQUIRE);
// Configure trusted client certificates
sslContextBuilder.trustManager(new File("path/to/client-ca.crt"));
// Configure cipher suites
sslContextBuilder.ciphers(Arrays.asList(
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
));
// Configure protocols
sslContextBuilder.protocols("TLSv1.2", "TLSv1.3");
builder.sslContext(sslContextBuilder.build());
} catch (Exception e) {
throw new RuntimeException("Failed to configure TLS", e);
}
}
}@ApplicationScoped
public class LoadBalancingCustomizer implements ChannelBuilderCustomizer<NettyChannelBuilder> {
@Override
public Map<String, Object> customize(String name,
GrpcClientConfiguration config,
NettyChannelBuilder builder) {
if ("distributed-service".equals(name)) {
// Configure service discovery
builder.nameResolverFactory(new DnsNameResolverProvider())
.defaultLoadBalancingPolicy("round_robin");
// Return advanced service config
return Map.of(
"loadBalancingConfig", List.of(
Map.of("weighted_round_robin", Map.of(
"enableOobLoadReport", true,
"oobReportingPeriod", "10s"
)),
Map.of("round_robin", Map.of())
),
"healthCheckConfig", Map.of(
"serviceName", "health-check-service"
)
);
}
return Map.of();
}
}@ApplicationScoped
public class InterceptorCustomizer implements ServerBuilderCustomizer<NettyServerBuilder> {
@Inject
MeterRegistry meterRegistry;
@Inject
TracingService tracingService;
@Override
public void customize(GrpcServerConfiguration config, NettyServerBuilder builder) {
// Add metrics interceptor
builder.intercept(new MetricsServerInterceptor(meterRegistry));
// Add tracing interceptor
builder.intercept(new TracingServerInterceptor(tracingService));
// Add rate limiting interceptor
builder.intercept(new RateLimitingInterceptor(
RateLimiter.create(100.0))); // 100 requests per second
// Add authentication interceptor for specific services
builder.intercept(ServerInterceptors.useInputStreamMessages(
new AuthenticationInterceptor()));
}
}@ApplicationScoped
public class DevelopmentCustomizer implements ServerBuilderCustomizer<NettyServerBuilder> {
@Override
public void customize(GrpcServerConfiguration config, NettyServerBuilder builder) {
if (LaunchMode.current() == LaunchMode.DEVELOPMENT) {
// Enable reflection for development
builder.addService(ProtoReflectionService.newInstance());
// Add development interceptors
builder.intercept(new DevelopmentLoggingInterceptor());
builder.intercept(new RequestDumpingInterceptor());
// Relaxed settings for development
builder.permitKeepAliveWithoutCalls(true)
.permitKeepAliveTime(1, TimeUnit.SECONDS);
}
}
}# Enable health checks
quarkus.grpc.server.health.enabled=true
# Configure health check service
quarkus.grpc.server.health.service-name=grpc-health-check@ApplicationScoped
public class HealthCheckCustomizer implements ServerBuilderCustomizer<NettyServerBuilder> {
@Override
public void customize(GrpcServerConfiguration config, NettyServerBuilder builder) {
// Add custom health check service
HealthStatusManager healthStatusManager = new HealthStatusManager();
builder.addService(healthStatusManager.getHealthService());
// Set service status
healthStatusManager.setStatus("", HealthCheckResponse.Status.SERVING);
healthStatusManager.setStatus("greeting-service", HealthCheckResponse.Status.SERVING);
}
}Configuration customizers are applied in priority order (higher priority applied later), allowing fine-grained control over the final configuration.
Install with Tessl CLI
npx tessl i tessl/maven-io-quarkus--quarkus-grpc