Java Netty systemd惰性初始化
是否可以使用继承的服务器套接字通道通过systemd/inetd初始化netty lazy? 我们在旧的基于Jetty的服务器中使用了它,Jetty将在那里调用Java的System.inheritedChannel()来获取通过systemd在惰性初始化中创建的套接字 我搜索了很多,我只找到了一张Jira票证,上面说它应该支持版本4: 但是这张jira票没有任何例子,我也找不到任何文档,也找不到任何源代码,它们可以告诉我如何在netty中实现这一点 任何帮助都将不胜感激。Java Netty systemd惰性初始化,java,sockets,netty,systemd,Java,Sockets,Netty,Systemd,是否可以使用继承的服务器套接字通道通过systemd/inetd初始化netty lazy? 我们在旧的基于Jetty的服务器中使用了它,Jetty将在那里调用Java的System.inheritedChannel()来获取通过systemd在惰性初始化中创建的套接字 我搜索了很多,我只找到了一张Jira票证,上面说它应该支持版本4: 但是这张jira票没有任何例子,我也找不到任何文档,也找不到任何源代码,它们可以告诉我如何在netty中实现这一点 任何帮助都将不胜感激。 谢谢 编辑: 更清楚
谢谢 编辑: 更清楚地说,我想知道的是,systemd是否可以激活我的java应用程序套接字,然后以某种方式将套接字引用传递给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);
}
}
}
是的,这应该是可能的
NioServerSocketChannel
允许您通过其构造函数包装现有的频道。因此,您只需编写自己的ChannelFactory
,并将其与ServerBootstrap
一起使用,以确保创建一个封装它的NioServerSocketChannel
另一种方法是完全不使用ServerBootstrap
,而只使用自己手动创建的NioServerSocketChannel
调用register等。你好,诺曼。第一个解决方案看起来很漂亮,但在我的情况下,它没有帮助,因为我的服务器将绑定到多个端口,但最多从systemd继承一个端口。由于ChannelFactory.newChannel()没有参数,因此无法确定要返回的通道是否继承。在创建频道时,我们没有地址来决定我可以返回哪种频道,这对我来说很奇怪。有没有关于如何针对暴露的场景处理这种方法的建议?为什么不使用多个ServerBootstrap实例呢?我认为这有点过分了。但我只是尝试了一下,这种方法实际上不起作用。我正在用我尝试的代码更新问题。请注意,我必须将localAddress添加到serverBootsrap。localaddress在绑定时是必需的,无论是在我正在做的引导上,还是作为bind方法的参数。如果使用预绑定套接字,则不应调用bind(),而应仅调用register()
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)