Java Netty systemd惰性初始化

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/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)