mirror of https://github.com/grpc/grpc-java.git
netty: refactor NettyChannelBuilder keepalive API (#2874)
To be in line with `NettyServerBuilder` APIs - Deprecated `enableKeepAlive(boolean enable)` and `enableKeepAlive(boolean enable, long keepAliveDelay, TimeUnit delayUnit, long keepAliveTimeout, TimeUnit timeoutUnit)` which never worked in v1.2 - Added `keepAliveTime(long keepAliveTime, TimeUnit timeUnit)` and `keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit)`
This commit is contained in:
parent
90788305a3
commit
1c1864be73
|
@ -176,26 +176,25 @@ public final class GrpcUtil {
|
|||
/**
|
||||
* The default timeout in nanos for a keepalive ping request.
|
||||
*/
|
||||
public static final long DEFAULT_KEEPALIVE_TIMEOUT_NANOS = TimeUnit.MINUTES.toNanos(2);
|
||||
public static final long DEFAULT_KEEPALIVE_TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(20L);
|
||||
|
||||
/**
|
||||
* The magic keepalive time value that disables client keepalive.
|
||||
*/
|
||||
public static final long KEEPALIVE_TIME_NANOS_DISABLED = Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* The default delay in nanos for server keepalive.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public static final long DEFAULT_SERVER_KEEPALIVE_TIME_NANOS = TimeUnit.HOURS.toNanos(2L);
|
||||
|
||||
/**
|
||||
* The default timeout in nanos for a server keepalive ping request.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public static final long DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(20L);
|
||||
|
||||
/**
|
||||
* The magic keepalive time value that disables keepalive.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public static final long SERVER_KEEPALIVE_TIME_NANOS_DISABLED = Long.MAX_VALUE;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static io.grpc.internal.GrpcUtil.DEFAULT_KEEPALIVE_DELAY_NANOS;
|
||||
import static io.grpc.internal.GrpcUtil.DEFAULT_KEEPALIVE_TIMEOUT_NANOS;
|
||||
import static io.grpc.internal.GrpcUtil.KEEPALIVE_TIME_NANOS_DISABLED;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
@ -71,6 +72,9 @@ public final class NettyChannelBuilder
|
|||
extends AbstractManagedChannelImplBuilder<NettyChannelBuilder> {
|
||||
public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1048576; // 1MiB
|
||||
|
||||
private static final long MIN_KEEPALIVE_TIMEOUT_NANO = TimeUnit.MICROSECONDS.toNanos(499L);
|
||||
private static final long AS_LARGE_AS_INFINITE = TimeUnit.DAYS.toNanos(1000L);
|
||||
|
||||
private final Map<ChannelOption<?>, Object> channelOptions =
|
||||
new HashMap<ChannelOption<?>, Object>();
|
||||
|
||||
|
@ -83,9 +87,8 @@ public final class NettyChannelBuilder
|
|||
private SslContext sslContext;
|
||||
private int flowControlWindow = DEFAULT_FLOW_CONTROL_WINDOW;
|
||||
private int maxHeaderListSize = GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE;
|
||||
private boolean enableKeepAlive;
|
||||
private long keepAliveDelayNanos;
|
||||
private long keepAliveTimeoutNanos;
|
||||
private long keepAliveTimeNanos = KEEPALIVE_TIME_NANOS_DISABLED;
|
||||
private long keepAliveTimeoutNanos = DEFAULT_KEEPALIVE_TIMEOUT_NANOS;
|
||||
private TransportCreationParamsFilterFactory dynamicParamsFactory;
|
||||
|
||||
/**
|
||||
|
@ -241,28 +244,63 @@ public final class NettyChannelBuilder
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable keepalive with default delay and timeout.
|
||||
*
|
||||
* @deprecated Please use {@link #keepAliveTime} and {@link #keepAliveTimeout} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public final NettyChannelBuilder enableKeepAlive(boolean enable) {
|
||||
enableKeepAlive = enable;
|
||||
if (enable) {
|
||||
keepAliveDelayNanos = DEFAULT_KEEPALIVE_DELAY_NANOS;
|
||||
keepAliveTimeoutNanos = DEFAULT_KEEPALIVE_TIMEOUT_NANOS;
|
||||
return keepAliveTime(DEFAULT_KEEPALIVE_DELAY_NANOS, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
return keepAliveTime(KEEPALIVE_TIME_NANOS_DISABLED, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable keepalive with custom delay and timeout.
|
||||
*
|
||||
* @deprecated Please use {@link #keepAliveTime} and {@link #keepAliveTimeout} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public final NettyChannelBuilder enableKeepAlive(boolean enable, long keepAliveDelay,
|
||||
TimeUnit delayUnit, long keepAliveTimeout, TimeUnit timeoutUnit) {
|
||||
if (enable) {
|
||||
return keepAliveTime(keepAliveDelay, delayUnit)
|
||||
.keepAliveTimeout(keepAliveTimeout, timeoutUnit);
|
||||
}
|
||||
return keepAliveTime(KEEPALIVE_TIME_NANOS_DISABLED, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom keepalive time, the delay time for sending next keepalive ping. An unreasonably
|
||||
* small value might be increased, and {@code Long.MAX_VALUE} nano seconds or an unreasonably
|
||||
* large value will disable keepalive.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public NettyChannelBuilder keepAliveTime(long keepAliveTime, TimeUnit timeUnit) {
|
||||
checkArgument(keepAliveTime > 0L, "keepalive time must be positive");
|
||||
keepAliveTimeNanos = timeUnit.toNanos(keepAliveTime);
|
||||
if (keepAliveTimeNanos >= AS_LARGE_AS_INFINITE) {
|
||||
// Bump keepalive time to infinite. This disables keepalive.
|
||||
keepAliveTimeNanos = KEEPALIVE_TIME_NANOS_DISABLED;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable keepalive with custom delay and timeout.
|
||||
* Sets a custom keepalive timeout, the timeout for keepalive ping requests. An unreasonably small
|
||||
* value might be increased.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
public final NettyChannelBuilder enableKeepAlive(boolean enable, long keepAliveDelay,
|
||||
TimeUnit delayUnit, long keepAliveTimeout, TimeUnit timeoutUnit) {
|
||||
enableKeepAlive = enable;
|
||||
if (enable) {
|
||||
keepAliveDelayNanos = delayUnit.toNanos(keepAliveDelay);
|
||||
keepAliveTimeoutNanos = timeoutUnit.toNanos(keepAliveTimeout);
|
||||
public NettyChannelBuilder keepAliveTimeout(long keepAliveTimeout, TimeUnit timeUnit) {
|
||||
checkArgument(keepAliveTimeout > 0L, "keepalive timeout must be positive");
|
||||
keepAliveTimeoutNanos = timeUnit.toNanos(keepAliveTimeout);
|
||||
if (keepAliveTimeoutNanos < MIN_KEEPALIVE_TIMEOUT_NANO) {
|
||||
// Bump keepalive timeout.
|
||||
keepAliveTimeoutNanos = MIN_KEEPALIVE_TIMEOUT_NANO;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -272,7 +310,7 @@ public final class NettyChannelBuilder
|
|||
protected ClientTransportFactory buildTransportFactory() {
|
||||
return new NettyTransportFactory(dynamicParamsFactory, channelType, channelOptions,
|
||||
negotiationType, sslContext, eventLoopGroup, flowControlWindow, maxInboundMessageSize(),
|
||||
maxHeaderListSize, enableKeepAlive, keepAliveDelayNanos, keepAliveTimeoutNanos);
|
||||
maxHeaderListSize, keepAliveTimeNanos, keepAliveTimeoutNanos);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -393,7 +431,6 @@ public final class NettyChannelBuilder
|
|||
private final int flowControlWindow;
|
||||
private final int maxMessageSize;
|
||||
private final int maxHeaderListSize;
|
||||
private final boolean enableKeepAlive;
|
||||
private final long keepAliveDelayNanos;
|
||||
private final long keepAliveTimeoutNanos;
|
||||
|
||||
|
@ -402,7 +439,7 @@ public final class NettyChannelBuilder
|
|||
NettyTransportFactory(TransportCreationParamsFilterFactory transportCreationParamsFilterFactory,
|
||||
Class<? extends Channel> channelType, Map<ChannelOption<?>, ?> channelOptions,
|
||||
NegotiationType negotiationType, SslContext sslContext, EventLoopGroup group,
|
||||
int flowControlWindow, int maxMessageSize, int maxHeaderListSize, boolean enableKeepAlive,
|
||||
int flowControlWindow, int maxMessageSize, int maxHeaderListSize,
|
||||
long keepAliveDelayNanos, long keepAliveTimeoutNanos) {
|
||||
this.channelType = channelType;
|
||||
this.negotiationType = negotiationType;
|
||||
|
@ -423,7 +460,6 @@ public final class NettyChannelBuilder
|
|||
this.flowControlWindow = flowControlWindow;
|
||||
this.maxMessageSize = maxMessageSize;
|
||||
this.maxHeaderListSize = maxHeaderListSize;
|
||||
this.enableKeepAlive = enableKeepAlive;
|
||||
this.keepAliveDelayNanos = keepAliveDelayNanos;
|
||||
this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
|
||||
usingSharedGroup = group == null;
|
||||
|
@ -446,10 +482,8 @@ public final class NettyChannelBuilder
|
|||
NettyClientTransport transport = new NettyClientTransport(
|
||||
dparams.getTargetServerAddress(), channelType, channelOptions, group,
|
||||
dparams.getProtocolNegotiator(), flowControlWindow,
|
||||
maxMessageSize, maxHeaderListSize, dparams.getAuthority(), dparams.getUserAgent());
|
||||
if (enableKeepAlive) {
|
||||
transport.enableKeepAlive(true, keepAliveDelayNanos, keepAliveTimeoutNanos);
|
||||
}
|
||||
maxMessageSize, maxHeaderListSize, keepAliveDelayNanos, keepAliveTimeoutNanos,
|
||||
dparams.getAuthority(), dparams.getUserAgent());
|
||||
return transport;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
package io.grpc.netty;
|
||||
|
||||
import static io.grpc.internal.GrpcUtil.KEEPALIVE_TIME_NANOS_DISABLED;
|
||||
import static io.netty.channel.ChannelOption.SO_KEEPALIVE;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -82,7 +83,6 @@ class NettyClientTransport implements ConnectionClientTransport {
|
|||
private final int maxMessageSize;
|
||||
private final int maxHeaderListSize;
|
||||
private KeepAliveManager keepAliveManager;
|
||||
private boolean enableKeepAlive;
|
||||
private long keepAliveDelayNanos;
|
||||
private long keepAliveTimeoutNanos;
|
||||
|
||||
|
@ -98,7 +98,8 @@ class NettyClientTransport implements ConnectionClientTransport {
|
|||
SocketAddress address, Class<? extends Channel> channelType,
|
||||
Map<ChannelOption<?>, ?> channelOptions, EventLoopGroup group,
|
||||
ProtocolNegotiator negotiator, int flowControlWindow, int maxMessageSize,
|
||||
int maxHeaderListSize, String authority, @Nullable String userAgent) {
|
||||
int maxHeaderListSize, long keepAliveDelayNanos, long keepAliveTimeoutNanos,
|
||||
String authority, @Nullable String userAgent) {
|
||||
this.negotiator = Preconditions.checkNotNull(negotiator, "negotiator");
|
||||
this.address = Preconditions.checkNotNull(address, "address");
|
||||
this.group = Preconditions.checkNotNull(group, "group");
|
||||
|
@ -107,17 +108,10 @@ class NettyClientTransport implements ConnectionClientTransport {
|
|||
this.flowControlWindow = flowControlWindow;
|
||||
this.maxMessageSize = maxMessageSize;
|
||||
this.maxHeaderListSize = maxHeaderListSize;
|
||||
this.authority = new AsciiString(authority);
|
||||
this.userAgent = new AsciiString(GrpcUtil.getGrpcUserAgent("netty", userAgent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable keepalive with custom delay and timeout.
|
||||
*/
|
||||
void enableKeepAlive(boolean enable, long keepAliveDelayNanos, long keepAliveTimeoutNanos) {
|
||||
enableKeepAlive = enable;
|
||||
this.keepAliveDelayNanos = keepAliveDelayNanos;
|
||||
this.keepAliveTimeoutNanos = keepAliveTimeoutNanos;
|
||||
this.authority = new AsciiString(authority);
|
||||
this.userAgent = new AsciiString(GrpcUtil.getGrpcUserAgent("netty", userAgent));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,7 +161,7 @@ class NettyClientTransport implements ConnectionClientTransport {
|
|||
lifecycleManager = new ClientTransportLifecycleManager(
|
||||
Preconditions.checkNotNull(transportListener, "listener"));
|
||||
EventLoop eventLoop = group.next();
|
||||
if (enableKeepAlive) {
|
||||
if (keepAliveDelayNanos != KEEPALIVE_TIME_NANOS_DISABLED) {
|
||||
keepAliveManager = new KeepAliveManager(
|
||||
new ClientKeepAlivePinger(this), eventLoop, keepAliveDelayNanos, keepAliveTimeoutNanos,
|
||||
false);
|
||||
|
|
|
@ -40,6 +40,7 @@ import io.grpc.netty.ProtocolNegotiators.TlsNegotiator;
|
|||
import io.netty.handler.ssl.SslContext;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.net.ssl.SSLException;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -164,4 +165,22 @@ public class NettyChannelBuilderTest {
|
|||
assertEquals("bad_authority", n.getHost());
|
||||
assertEquals(-1, n.getPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negativeKeepAliveTime() {
|
||||
NettyChannelBuilder builder = NettyChannelBuilder.forTarget("fakeTarget");
|
||||
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.expectMessage("keepalive time must be positive");
|
||||
builder.keepAliveTime(-1L, TimeUnit.HOURS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negativeKeepAliveTimeout() {
|
||||
NettyChannelBuilder builder = NettyChannelBuilder.forTarget("fakeTarget");
|
||||
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.expectMessage("keepalive timeout must be positive");
|
||||
builder.keepAliveTimeout(-1L, TimeUnit.HOURS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import static io.grpc.Status.Code.INTERNAL;
|
|||
import static io.grpc.internal.GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
|
||||
import static io.grpc.internal.GrpcUtil.DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS;
|
||||
import static io.grpc.internal.GrpcUtil.DEFAULT_SERVER_KEEPALIVE_TIME_NANOS;
|
||||
import static io.grpc.internal.GrpcUtil.KEEPALIVE_TIME_NANOS_DISABLED;
|
||||
import static io.grpc.internal.GrpcUtil.USER_AGENT_KEY;
|
||||
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_WINDOW_SIZE;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -168,7 +169,7 @@ public class NettyClientTransportTest {
|
|||
NettyClientTransport transport = new NettyClientTransport(
|
||||
address, NioSocketChannel.class, channelOptions, group, newNegotiator(),
|
||||
DEFAULT_WINDOW_SIZE, DEFAULT_MAX_MESSAGE_SIZE, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE,
|
||||
authority, null /* user agent */);
|
||||
KEEPALIVE_TIME_NANOS_DISABLED, 1L, authority, null /* user agent */);
|
||||
transports.add(transport);
|
||||
callMeMaybe(transport.start(clientTransportListener));
|
||||
|
||||
|
@ -391,12 +392,14 @@ public class NettyClientTransportTest {
|
|||
|
||||
private NettyClientTransport newTransport(ProtocolNegotiator negotiator, int maxMsgSize,
|
||||
int maxHeaderListSize, String userAgent, boolean enableKeepAlive) {
|
||||
long keepAliveTimeNano = KEEPALIVE_TIME_NANOS_DISABLED;
|
||||
if (enableKeepAlive) {
|
||||
keepAliveTimeNano = 1000L;
|
||||
}
|
||||
NettyClientTransport transport = new NettyClientTransport(
|
||||
address, NioSocketChannel.class, new HashMap<ChannelOption<?>, Object>(), group, negotiator,
|
||||
DEFAULT_WINDOW_SIZE, maxMsgSize, maxHeaderListSize, authority, userAgent);
|
||||
if (enableKeepAlive) {
|
||||
transport.enableKeepAlive(true, 1000, 1000);
|
||||
}
|
||||
DEFAULT_WINDOW_SIZE, maxMsgSize, maxHeaderListSize, keepAliveTimeNano, 1L, authority,
|
||||
userAgent);
|
||||
transports.add(transport);
|
||||
return transport;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue