Netty systemd lazy initialization



是否可以使用继承的服务器套接字通道通过 systemd/inetd 初始化 netty lazy? 我们在基于 Jetty 的旧服务器中使用了它,其中 Jetty 会调用 Java 的 System.inheritedChannel(( 来获取通过 systemd 在延迟初始化上创建的套接字。

我搜索了很多,我找到的只是一个 Jira 票证,上面说它应该支持版本 4:https://issues.jboss.org/browse/NETTY-309。

但是这个 jira 票证没有示例,我找不到任何文档,也找不到源代码上的任何内容,可以指出我如何在 netty 中实现这一目标。

任何帮助将不胜感激。
谢谢

编辑: 只是为了更清楚,我想知道是否有可能让我的 java 应用程序套接字由 systemd 激活,然后以某种方式将套接字引用传递给 netty。

编辑2: 这是Norman Mayer建议的方法,但实际上失败了,但以下例外:

public class MyServerBootStrap {
private ServiceContext ctx;
private Config config;
private Collection<Channel> channels;
private Collection<Connector> connectors;
public MyServerBootStrap(List<Connector> connectors) {
this.ctx = ApplicationContext.getInstance();
this.config = ctx.getMainConfig();
this.connectors = connectors;
this.channels = new ArrayList<>(connectors.size());
}
public void run(Connector connector) throws RuntimeException, IOException, InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(config.getInt("http_acceptor_threads", 0));
EventLoopGroup workerGroup = new NioEventLoopGroup(config.getIntError("http_server_threads"));
final SocketAddress addr;
final ChannelFactory<ServerChannel> channelFactory;
if (connector.geEndpoint().isInherited()) {
System.out.println(
"Trying to bootstrap inherited channel: " + connector.geEndpoint().getDescription());
ServerSocketChannel channel = (ServerSocketChannel) System.inheritedChannel();
addr = channel.getLocalAddress();
System.out.println("Channel localAddress(): " + addr);
channelFactory = new MyChannelFactory(channel);
} else {
System.out.println(
"Trying to bootstrap regular channel: " + connector.geEndpoint().getDescription());
addr = connector.geEndpoint().getSocketAdress();
channelFactory = new MyChannelFactory(null);
}
ServerBootstrap b = new ServerBootstrap();
b
.group(bossGroup, workerGroup)
.localAddress(addr)
.channelFactory(channelFactory)
.childHandler(new ChannelInitializerRouter(Collections.singletonList(connector)))
.childOption(ChannelOption.SO_KEEPALIVE, true);
if (config.contains("tcp_max_syn_backlog")) {
b.option(ChannelOption.SO_BACKLOG, config.getIntError("tcp_max_syn_backlog"));
}
Channel serverChannel = b.bind().sync().channel();
channels.add(serverChannel);
}
public void run() throws RuntimeException {
try {
for (Connector connector : connectors) {
run(connector);
}
for (Channel channel : channels) {
channel.closeFuture().sync();
}
} catch (Throwable exc) {
throw new RuntimeException("Failed to start web-server", exc);
} finally {
// TODO: fix this
// workerGroup.shutdownGracefully();
// bossGroup.shutdownGracefully();
}
}
}

class MyChannelFactory implements io.netty.channel.ChannelFactory<ServerChannel> {
private ServerSocketChannel channel;
public MyChannelFactory(ServerSocketChannel ch) {
this.channel = ch;
}
@Override
public ServerChannel newChannel() {
if (channel == null) {
return new NioServerSocketChannel();
} else {
return new NioServerSocketChannel(channel);
}
}
}

.log:

Trying to bootstrap inherited channel: public (tcp port: 8080)
Channel localAddress(): /0:0:0:0:0:0:0:0:8080
java.lang.RuntimeException: Failed to start web-server
at MyServerBootStrap.run(MyServerBootStrap.java:85)
at MyServer.run(MyServer.java:61)
at Main.start(Main.java:96)
at Main.main(Main.java:165)
Caused by: java.nio.channels.AlreadyBoundException
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:216)
at sun.nio.ch.InheritedChannel$InheritedServerSocketChannelImpl.bind(InheritedChannel.java:92)
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:128)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:558)
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1338)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:501)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:486)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:999)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:254)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:366)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:463)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)

是的,这应该是可能的。

NioServerSocketChannel允许您通过其构造函数包装现有Channel。因此,您需要做的就是编写自己的ChannelFactory并将其与ServerBootstrap一起使用,以确保创建包装它的NioServerSocketChannel

另一种方法是根本不使用ServerBootstrap,而只是使用自己手动创建的NioServerSocketChannel调用寄存器等。

最新更新