Netty-based HTTP/2 transport implementation for gRPC Java providing high-performance network communication
—
HTTP/2 protocol negotiation strategies for different deployment scenarios, from TLS ALPN to plaintext upgrades and direct HTTP/2 connections.
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import io.grpc.netty.NettyServerBuilder;Enum defining the negotiation method for establishing HTTP/2 connections.
public enum NegotiationType {
TLS,
PLAINTEXT_UPGRADE,
PLAINTEXT
}Uses TLS ALPN (Application Layer Protocol Negotiation) or NPN (Next Protocol Negotiation) to negotiate HTTP/2 over an encrypted connection.
Uses HTTP/1.1 Upgrade header to negotiate from HTTP/1.1 to HTTP/2 over a plaintext connection.
Assumes the connection directly supports HTTP/2 without negotiation.
Experimental credentials for HTTP/1.1 to HTTP/2 upgrade scenarios.
public static ChannelCredentials create();Returns: ChannelCredentials that performs insecure HTTP/1 to HTTP/2 upgrade
Abstract base class for custom protocol negotiators.
public abstract AsciiString scheme();
public abstract ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler);Methods:
scheme() - Returns protocol scheme ("https", "http", etc.)newHandler() - Creates Netty channel handler for negotiationFactory for creating various protocol negotiators.
public static ProtocolNegotiator serverTls(SslContext sslContext);
public static ProtocolNegotiator serverTls(SslContext sslContext, HostnameVerifier hostnameVerifier);
public static ProtocolNegotiator serverPlaintext();public static ProtocolNegotiator tls(SslContext sslContext);
public static ProtocolNegotiator tls(SslContext sslContext, String authority);
public static ProtocolNegotiator plaintext();
public static ProtocolNegotiator plaintextUpgrade();Parameters:
sslContext - Netty SSL context for TLS connectionshostnameVerifier - Custom hostname verificationauthority - Expected server authority for verificationimport io.grpc.netty.NettyChannelBuilder;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.GrpcSslContexts;
// Client
SslContext sslContext = GrpcSslContexts.forClient().build();
ManagedChannel channel = NettyChannelBuilder.forAddress("api.example.com", 443)
.negotiationType(NegotiationType.TLS)
.sslContext(sslContext)
.build();
// Server
SslContext serverSslContext = GrpcSslContexts.forServer(
new File("server-cert.pem"),
new File("server-key.pem")
).build();
Server server = NettyServerBuilder.forPort(443)
.sslContext(serverSslContext)
.addService(new GreeterImpl())
.build();import io.grpc.netty.InsecureFromHttp1ChannelCredentials;
// Client with HTTP/1.1 to HTTP/2 upgrade
ChannelCredentials creds = InsecureFromHttp1ChannelCredentials.create();
ManagedChannel channel = Grpc.newChannelBuilder("localhost:8080", creds)
.build();
// Alternative using NegotiationType
ManagedChannel channel2 = NettyChannelBuilder.forAddress("localhost", 8080)
.negotiationType(NegotiationType.PLAINTEXT_UPGRADE)
.usePlaintext()
.build();
// Server supporting upgrade
Server server = NettyServerBuilder.forPort(8080)
.addService(new GreeterImpl())
.build();// Client assuming direct HTTP/2
ManagedChannel channel = NettyChannelBuilder.forAddress("internal-service", 9090)
.negotiationType(NegotiationType.PLAINTEXT)
.usePlaintext()
.build();
// Server with direct HTTP/2
Server server = NettyServerBuilder.forPort(9090)
.addService(new GreeterImpl())
.build();import io.grpc.netty.ProtocolNegotiators;
import io.grpc.netty.ProtocolNegotiator;
// Client with custom TLS negotiator
SslContext sslContext = GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
ProtocolNegotiator negotiator = ProtocolNegotiators.tls(sslContext, "my-service");
// Use with Netty internals (experimental)// Load balancer terminates TLS, forwards HTTP/2 plaintext to backend
ManagedChannel channel = NettyChannelBuilder.forAddress("backend-service", 9090)
.negotiationType(NegotiationType.PLAINTEXT)
.usePlaintext()
.build();// Load balancer only supports HTTP/1.1, needs upgrade
ManagedChannel channel = NettyChannelBuilder.forAddress("service", 80)
.negotiationType(NegotiationType.PLAINTEXT_UPGRADE)
.usePlaintext()
.build();// Simple plaintext for local development
ManagedChannel channel = NettyChannelBuilder.forAddress("localhost", 9090)
.usePlaintext() // Automatically uses appropriate negotiation
.build();
Server server = NettyServerBuilder.forPort(9090)
.addService(new GreeterImpl())
.build();// Self-signed certificates for testing
SslContext testSslContext = GrpcSslContexts.forServer(
new File("test-cert.pem"),
new File("test-key.pem")
).build();
Server testServer = NettyServerBuilder.forPort(0) // Random available port
.sslContext(testSslContext)
.addService(new GreeterImpl())
.build()
.start();
int port = testServer.getPort();
SslContext clientSslContext = GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
ManagedChannel channel = NettyChannelBuilder.forAddress("localhost", port)
.sslContext(clientSslContext)
.build();// Direct HTTP/2 within container network
ManagedChannel channel = NettyChannelBuilder.forAddress("service-name", 9090)
.negotiationType(NegotiationType.PLAINTEXT)
.usePlaintext()
.build();// Ingress handles TLS, forwards plaintext to pods
Server server = NettyServerBuilder.forPort(9090)
.addService(new GreeterImpl())
.build(); // Plaintext server for ingress backend// Add to JVM args or logging configuration
-Dio.netty.leakDetection.level=paranoid
-Djavax.net.debug=ssl:handshake:verboseimport io.netty.handler.ssl.OpenSsl;
System.out.println("OpenSSL available: " + OpenSsl.isAvailable());
System.out.println("ALPN support: " + OpenSsl.isAlpnSupported());HTTP/2 not negotiated:
UNAVAILABLE: HTTP/2 connection preface not receivedSolution: Verify ALPN configuration and protocol support
TLS handshake failure:
SSLHandshakeException during negotiationSolution: Check certificate configuration and cipher suite compatibility
Upgrade failure:
UNAVAILABLE: HTTP/1.1 to HTTP/2 upgrade failedSolution: Ensure server supports HTTP/2 upgrade headers
NegotiationType.TLS with proper certificatesusePlaintext() for simplicity, let gRPC choose negotiationNegotiationType.PLAINTEXT for direct HTTP/2Install with Tessl CLI
npx tessl i tessl/maven-io-grpc--grpc-netty