use of io.grpc.InternalInstrumented in project grpc-java by grpc.
the class NettyServerTest method multiPortStartStopGet.
@Test
public void multiPortStartStopGet() throws Exception {
InetSocketAddress addr1 = new InetSocketAddress(0);
InetSocketAddress addr2 = new InetSocketAddress(0);
NettyServer ns = new NettyServer(Arrays.asList(addr1, addr2), new ReflectiveChannelFactory<>(NioServerSocketChannel.class), new HashMap<ChannelOption<?>, Object>(), new HashMap<ChannelOption<?>, Object>(), new FixedObjectPool<>(eventLoop), new FixedObjectPool<>(eventLoop), false, ProtocolNegotiators.plaintext(), Collections.<ServerStreamTracer.Factory>emptyList(), TransportTracer.getDefaultFactory(), // ignore
1, // ignore
false, // ignore
1, // ignore
1, // ignore
1, // ignore
1, // ignore
1, // ignore
1, // ignore
1, // ignore
1, // ignore
true, // ignore
0, Attributes.EMPTY, channelz);
final SettableFuture<Void> shutdownCompleted = SettableFuture.create();
ns.start(new ServerListener() {
@Override
public ServerTransportListener transportCreated(ServerTransport transport) {
return new NoopServerTransportListener();
}
@Override
public void serverShutdown() {
shutdownCompleted.set(null);
}
});
// SocketStats won't be available until the event loop task of adding SocketStats created by
// ns.start() complete. So submit a noop task and await until it's drained.
eventLoop.submit(new Runnable() {
@Override
public void run() {
}
}).await(5, TimeUnit.SECONDS);
assertEquals(2, ns.getListenSocketAddresses().size());
for (SocketAddress address : ns.getListenSocketAddresses()) {
assertThat(((InetSocketAddress) address).getPort()).isGreaterThan(0);
}
List<InternalInstrumented<SocketStats>> stats = ns.getListenSocketStatsList();
assertEquals(2, ns.getListenSocketStatsList().size());
for (InternalInstrumented<SocketStats> listenSocket : stats) {
assertSame(listenSocket, channelz.getSocket(id(listenSocket)));
// very basic sanity check of the contents
SocketStats socketStats = listenSocket.getStats().get();
assertThat(ns.getListenSocketAddresses()).contains(socketStats.local);
assertNull(socketStats.remote);
}
// Cleanup
ns.shutdown();
shutdownCompleted.get();
// listen socket is removed
for (InternalInstrumented<SocketStats> listenSocket : stats) {
assertNull(channelz.getSocket(id(listenSocket)));
}
}
use of io.grpc.InternalInstrumented in project grpc-java by grpc.
the class NettyServer method start.
@Override
public void start(ServerListener serverListener) throws IOException {
listener = checkNotNull(serverListener, "serverListener");
final ServerBootstrap b = new ServerBootstrap();
b.option(ALLOCATOR, Utils.getByteBufAllocator(forceHeapBuffer));
b.childOption(ALLOCATOR, Utils.getByteBufAllocator(forceHeapBuffer));
b.group(bossExecutor, workerGroup);
b.channelFactory(channelFactory);
// For non-socket based channel, the option will be ignored.
b.childOption(SO_KEEPALIVE, true);
if (channelOptions != null) {
for (Map.Entry<ChannelOption<?>, ?> entry : channelOptions.entrySet()) {
@SuppressWarnings("unchecked") ChannelOption<Object> key = (ChannelOption<Object>) entry.getKey();
b.option(key, entry.getValue());
}
}
if (childChannelOptions != null) {
for (Map.Entry<ChannelOption<?>, ?> entry : childChannelOptions.entrySet()) {
@SuppressWarnings("unchecked") ChannelOption<Object> key = (ChannelOption<Object>) entry.getKey();
b.childOption(key, entry.getValue());
}
}
b.childHandler(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel ch) {
ChannelPromise channelDone = ch.newPromise();
long maxConnectionAgeInNanos = NettyServer.this.maxConnectionAgeInNanos;
if (maxConnectionAgeInNanos != MAX_CONNECTION_AGE_NANOS_DISABLED) {
// apply a random jitter of +/-10% to max connection age
maxConnectionAgeInNanos = (long) ((.9D + Math.random() * .2D) * maxConnectionAgeInNanos);
}
NettyServerTransport transport = new NettyServerTransport(ch, channelDone, protocolNegotiator, streamTracerFactories, transportTracerFactory.create(), maxStreamsPerConnection, autoFlowControl, flowControlWindow, maxMessageSize, maxHeaderListSize, keepAliveTimeInNanos, keepAliveTimeoutInNanos, maxConnectionIdleInNanos, maxConnectionAgeInNanos, maxConnectionAgeGraceInNanos, permitKeepAliveWithoutCalls, permitKeepAliveTimeInNanos, eagAttributes);
ServerTransportListener transportListener;
// This is to order callbacks on the listener, not to guard access to channel.
synchronized (NettyServer.this) {
if (terminated) {
// Server already terminated.
ch.close();
return;
}
// `channel` shutdown can race with `ch` initialization, so this is only safe to increment
// inside the lock.
sharedResourceReferenceCounter.retain();
transportListener = listener.transportCreated(transport);
}
/**
* Releases the event loop if the channel is "done", possibly due to the channel closing.
*/
final class LoopReleaser implements ChannelFutureListener {
private boolean done;
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!done) {
done = true;
sharedResourceReferenceCounter.release();
}
}
}
transport.start(transportListener);
ChannelFutureListener loopReleaser = new LoopReleaser();
channelDone.addListener(loopReleaser);
ch.closeFuture().addListener(loopReleaser);
}
});
Future<Map<ChannelFuture, SocketAddress>> bindCallFuture = bossExecutor.submit(new Callable<Map<ChannelFuture, SocketAddress>>() {
@Override
public Map<ChannelFuture, SocketAddress> call() {
Map<ChannelFuture, SocketAddress> bindFutures = new HashMap<>();
for (SocketAddress address : addresses) {
ChannelFuture future = b.bind(address);
channelGroup.add(future.channel());
bindFutures.put(future, address);
}
return bindFutures;
}
});
Map<ChannelFuture, SocketAddress> channelFutures = bindCallFuture.awaitUninterruptibly().getNow();
if (!bindCallFuture.isSuccess()) {
channelGroup.close().awaitUninterruptibly();
throw new IOException(String.format("Failed to bind to addresses %s", addresses), bindCallFuture.cause());
}
final List<InternalInstrumented<SocketStats>> socketStats = new ArrayList<>();
for (Map.Entry<ChannelFuture, SocketAddress> entry : channelFutures.entrySet()) {
// We'd love to observe interruption, but if interrupted we will need to close the channel,
// which itself would need an await() to guarantee the port is not used when the method
// returns. See #6850
final ChannelFuture future = entry.getKey();
if (!future.awaitUninterruptibly().isSuccess()) {
channelGroup.close().awaitUninterruptibly();
throw new IOException(String.format("Failed to bind to address %s", entry.getValue()), future.cause());
}
final InternalInstrumented<SocketStats> listenSocketStats = new ListenSocket(future.channel());
channelz.addListenSocket(listenSocketStats);
socketStats.add(listenSocketStats);
future.channel().closeFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
channelz.removeListenSocket(listenSocketStats);
}
});
}
listenSocketStatsList = Collections.unmodifiableList(socketStats);
}
Aggregations