【问题标题】:Netty closeFuture().sync().channel(); blocks rest apiNetty closeFuture().sync().channel();阻止休息 api
【发布时间】:2017-05-21 05:24:13
【问题描述】:

我正在学习 Netty 并开始使用 Spring Boot 进行一些教程。我的目标是创建一个应用程序,它设置一个 tcp 端口来接收消息并通过一个 rest api 呈现它们。

大部分教程都说我应该添加这样的东西

serverChannel = serverBootstrap.bind(tcpPort).sync().channel().closeFuture().sync().channel();

启动netty。 当我这样做时,我实施的其他服务都不起作用。 现在当我使用以下代码 sn-p 启动应用程序时:

serverChannel = serverBootstrap.bind(tcpPort).sync().channel();

一切似乎都运行良好。 有人可以解释一下可能导致此问题的原因吗?

谢谢

【问题讨论】:

    标签: java spring-boot netty


    【解决方案1】:

    第一部分启动服务器, 1) 将其绑定在 TCP 端口上, 2)等待服务器准备好(socket正在监听) 3) 并返回关联的频道。

    serverBootstrap.bind(tcpPort).sync().channel();
                     (1)           (2)       (3)
    

    第二部分是等待主通道(监听套接字)关闭(closeFuture().sync()),其中closeFuture 为您提供“关闭”操作(意味着关闭服务器套接字)的“未来”,以及@ 987654325@ 等待这个未来完成。 channel() 为您返回与第一次相同的频道,但现在已关闭。

    因此您可能会在各种示例中找到此代码,因为通常您在主线程左右启动服务器(绑定),然后如果您不等待某些东西,主线程将结束,让您的 JVM 完成,因此您的服务器在启动后立即停止。

    所以总的来说,我们所做的是:

    • 启动服务器
    • 在管道中添加必要的处理程序来处理您的业务逻辑(当然还有网络协议)
    • 然后通过等待 closeFuture 完成您的主线程,这样,一旦在您的业务逻辑中您收到关闭命令,您就关闭了主通道,因此您的主线程也将关闭。

    例如见Shutdown netty programmatically

    【讨论】:

    • 我自己的错误:(2)是等待主通道(监听套接字)准备好(不是关闭),然后(3)返回相应的通道。而channel().closeFuture().sync()closeFuture() 给出了该通道关闭的ChannelFuture,然后sync() 等待该通道关闭,因此关闭...
    • 为什么要关闭频道?这里的主要渠道是什么?
    • “主”通道是“通过套接字作为侦听器的通道”,但在未连接的意义上不是“真实通道”(子通道将是连接通道,因为套接字已连接到侦听器服务,每个都有一个管道)。在关闭应用程序之前停止监听地址/端口是很重要的。所以要恢复:“主通道”只是根据绑定选项在地址/端口上的一个侦听器,您必须等待它关闭(不再侦听,等待传入连接)才能关闭应用程序。
    【解决方案2】:

    旧的,但我的 RestController 没有启动时遇到了同样的问题。其他答案帮助我解决了这个问题,但这里是 Spring 组件的完整代码。

    import com.myserver.netty.handler.ClientInboundHandler;
    import com.myserver.netty.handler.PacketDecoder;
    import com.myserver.netty.handler.PacketEncoder;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.*;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    
    import lombok.extern.log4j.Log4j2;
    import org.springframework.stereotype.Component;
    import javax.annotation.PostConstruct;
    import javax.annotation.PreDestroy;
    
    @Component
    @Log4j2
    public class NettyServer {
    
       private EventLoopGroup masters = new NioEventLoopGroup();
       private EventLoopGroup workers = new NioEventLoopGroup();
    
       private Channel mainChannel;
    
       @PostConstruct
       public void start() {
           try {
               ServerBootstrap bootstrap = init();
               mainChannel = bootstrap.bind(8484).sync().channel(); // save the main channel so we can cleanly close it when app is shutdown
               log.info("Netty Server started......");
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
    
       @PreDestroy
       public void stop() throws InterruptedException {
           log.info("Shutting down netty server");
           workers.shutdownGracefully().sync();
           masters.shutdownGracefully().sync();
           mainChannel.closeFuture().sync();
           log.info("Shutdown complete");
       }
    
       private ServerBootstrap init() {
           return new ServerBootstrap()
                   .group(masters, workers)
                   .channel(NioServerSocketChannel.class)
                   .option(ChannelOption.SO_BACKLOG, 5000)
                   .option(ChannelOption.TCP_NODELAY, true)
                   .option(ChannelOption.SO_KEEPALIVE, true)
                   .childHandler(new ChannelInitializer<SocketChannel>() {
                       @Override
                       protected void initChannel(SocketChannel channel) throws Exception {
                           channel.pipeline()
                                   .addLast(new PacketDecoder())
                                   .addLast(new ClientInboundHandler())
                                   .addLast(new PacketEncoder());
                       }
                   });
       }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-23
      • 2015-11-02
      • 2015-09-08
      • 2012-02-05
      • 2015-11-26
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多