Http-Netty-Rpc-Service系统改造:不要在springboot的启动主线程中阻塞,nettyserver的postconstruct注解的init方法中不要写future.chann...

常规的demo级别的netty服务端的代码写法是这样的:

try {
                //创建并初始化 Netty 服务端辅助启动对象 ServerBootstrap
                ServerBootstrap serverBootstrap = RpcServer.this.initServerBootstrap(bossGroup, workerGroup);
                //绑定对应ip和端口,同步等待成功
                ChannelFuture future = serverBootstrap.bind(port).sync();
                LOGGER.info("rpc server 已启动,端口:{}", port);
                //等待服务端监听端口关闭
                future.channel().closeFuture().sync();
            } catch (InterruptedException i) {
                LOGGER.error("rpc server 出现异常,端口:{}, cause:", port, i.getMessage());
            } finally {
                //优雅退出,释放 NIO 线程组
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }

在这里面future.channel().closeFuture().sync();这个语句的主要目的是,方便测试,方便写一个非springboot的demo,比如一个简单地junit test方法,closeFuture().sync()可以阻止junit test将server关闭,同时停止test应用的时候也不需要手动再调用关闭服务器的方法workerGroup.shutdownGracefully()...。这样设计在测试时省心。

但是,当将nettyserver联系到springboot应用的启动时,例如nettyserver设置为@Component,当springboot扫描到nettyserver时,springboot主线程执行到nettyserver的postconstruct注解的方法,然后发生了

future.channel().closeFuture().sync();
这样导致springboot主线程阻塞,无法继续加载剩下的bean,
更糟糕的是,如果springboot还添加了springboot-web的依赖(自带tomcat容器),那么被阻塞后将无法启动tomcat servlet engine和webapplicationcontext.

所以不能简单地在nettyserver中的构造方法/init方法中写future.channel().closeFuture().sync();和workerGroup.shutdownGracefully().

只需在构造方法/init方法中bootstrap.bind(port),这是异步的,不会阻塞springboot主线程。

而将stop方法单独抽取出来。

需要注意的是,即使直接关闭springboot应用,不手动调用上面的stop方法,nettyserver也会将之前绑定的端口解除,为了保险起见,可以将stop方法添加@predestroy注解

 




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值