netty5.0的任务线程无法回收的问题
来源:互联网 发布:centos ssh 连不上 编辑:程序博客网 时间:2024/05/24 06:11
在最近的项目的运用了netty5.0,之后就发现过两天tomcat就莫名的内存消耗增大,或者直接就进程死掉了。
跟踪了很久发现是netty5在任务线程组里面很多的没有进行回收,然后又创建了很多新的任务线程。但也不是一次性就创建了很多,慢慢的增加的。
通过VisualVM追踪发现很多的nioEventLoopGroup线程,而且很明显的使用中线程不会增加,但是闲下来了,慢慢就会增加。非常奇怪,应该是netty5的一个bug,
我并没有跟踪源码去看,换到4.1之后所有的问题就自然消失了。
附带我netty4.1的客服端代码,有断线重连和空闲发送心跳包,因为是和设备交互,所有的数据都是转码后的。
package com.local.hr.tcp;import org.apache.log4j.Logger;import com.dashu.client.NettyClientBootstrap;import com.local.hr.udp.UdpClientSocket;import com.local.hr.util.ReturnEntity;import io.netty.bootstrap.Bootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.bytes.ByteArrayEncoder;import io.netty.handler.timeout.IdleStateHandler;public class NettyClient {public static Integer clientId = 0;private Logger log = Logger.getLogger(NettyClientBootstrap.class);private int port;private String host;private String ip;private String mac;private SocketChannel channel;private String userName;private String password;private Bootstrap bootstrap;public boolean isopen = true;public NettyClient(String host, int port, String mac,String userName,String password) throws InterruptedException {String ip ="";try {ReturnEntity entity = UdpClientSocket.getIP(mac, userName, password);//通过udp获取主机地址if (entity!=null) {ip =entity.getIp();}} catch (Exception e) {e.printStackTrace();}this.userName=userName;this.password = password;this.port = port;if (ip!=null&&!"".equals(ip)) {this.host = ip;}else{this.host = host;}this.mac = mac;start(this);}public String getMac() {return mac;}private void start(final NettyClient client) throws InterruptedException {EventLoopGroup eventLoopGroup = new NioEventLoopGroup();bootstrap = new Bootstrap();bootstrap.channel(NioSocketChannel.class);bootstrap.option(ChannelOption.SO_KEEPALIVE, true);bootstrap.group(eventLoopGroup);bootstrap.remoteAddress(host, port);bootstrap.handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new IdleStateHandler(150, 150, 300));// 空闲时间 socketChannel.pipeline().addLast(new ByteArrayEncoder());socketChannel.pipeline().addLast(new NettyClientHandler(mac, host, client));}});ChannelFuture future = bootstrap.connect(host, port).sync();if (future.isSuccess()) {this.channel = (SocketChannel) future.channel();isopen = true;log.info("connect server 成功---------");}}public void doConnect() {try {String ip ="";try {ReturnEntity entity = UdpClientSocket.getIP(mac, userName, password);if (entity!=null) {ip =entity.getIp();}} catch (Exception e) {e.printStackTrace();}if (ip!=null&&!"".equals(ip)&&!this.host.equals(ip)) {this.host=ip;}ChannelFuture future = bootstrap.connect(host, port).sync();this.channel = (SocketChannel) future.channel();isopen = true;} catch (Exception e) {log.info("断线重连失败: " + e.getMessage());}}public SocketChannel getChannel() {return channel;}public boolean isopen() {return isopen;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public static void main(String[] args) throws InterruptedException {NettyClient client = new NettyClient("192.168.10.17", 9090, "80.24.00.00", "", "");Thread.sleep(3000);for (int i = 0; i < 10000; i++) {client.channel.writeAndFlush("你好" + i);Thread.sleep(3000);}Thread.sleep(1000000);}}
package com.local.hr.tcp;import java.util.concurrent.TimeUnit;import org.apache.log4j.LogManager;import org.apache.log4j.Logger;import com.local.hr.util.EdHrCode;import com.local.hr.util.NewsCache;import com.local.hr.util.ReturnEntity;import com.local.hr.util.UnHrCode;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.EventLoop;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.timeout.IdleStateEvent;public class NettyClientHandler extends SimpleChannelInboundHandler<Object> {private static final Logger log = LogManager.getLogger(NettyClientHandler.class);private String mac;private String hostIp;private NettyClient client;private EdHrCode code = new EdHrCode();private UnHrCode un = new UnHrCode();public NettyClientHandler(String mac,String hostIp,NettyClient client) {this.mac=mac;this.hostIp=hostIp;this.client = client;}@Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {//断线重连client.isopen = false;final EventLoop eventLoop = ctx.channel().eventLoop();eventLoop.schedule(new Runnable() {@Overridepublic void run() {client.doConnect();while(!client.isopen) {try {Thread.sleep(180000);//等三分钟重新再试} catch (InterruptedException e1) {e1.printStackTrace();}client.doConnect();}}}, 5L, TimeUnit.SECONDS);ctx.close();super.channelInactive(ctx);}// 利用写空闲发送心跳检测消息@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt)throws Exception {if (evt instanceof IdleStateEvent) {log.debug("空闲了啊!");String h = this.un.heartbeat(this.mac, this.hostIp);ctx.writeAndFlush(this.un.hexStr2ByteArray(h));}} @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = code.bytesToHexString(req); log.debug(this.mac+" 收到消息:"+body); NewsCache.add(this.mac, body); ReturnEntity entity= code.caseControlCode("2a", body); if (entity.getStatus()==ReturnEntity.DATA_STATUS_NORMAL) { NewsCache.addRead(this.mac, entity);} }@Overrideprotected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {// TODO Auto-generated method stub}}
0 0
- netty5.0的任务线程无法回收的问题
- Netty5的客户端
- Netty5的服务端
- 线程资源的回收
- 线程资源的回收
- linux线程资源回收的问题(虚拟内存)
- Activity已销毁,创建的线程未回收问题
- Activity已销毁,创建的线程未回收问题
- 线程的终止与回收
- coding---进程、线程的回收
- 线程的停止与回收
- netty5.0源码包的依赖包的pom.xml
- 异步线程无法多次创建的问题
- netty5.0之Server端NioEventLoopGroup的初始化
- netty5.0之server端NioServerSocketChannel的bind分析
- 《netty5.0源码解析》读书笔记之Java的IO演进
- 由于线程停在某个无法进行垃圾回收的点----bug
- 解决Java线程池任务执行完毕后线程回收问题
- 事务控制和锁定语句
- React-native 布局
- Android Studio 上传SVN忽略文件
- 使用butterknife轻松定义控件
- CCF 201612-4 压缩编码 区间dp(石子合并)+四边形不等式优化
- netty5.0的任务线程无法回收的问题
- IMP-00010: not a valid export file, header failed verification
- [CSAPP] 存储器层次结构(一)
- 知识图谱
- windows环境下安装selenium
- find the nth digit HDU - 1597
- 适配器模式(Adapter):类适配器、对象适配器
- IOS页面自动布局之NSLaboutConstraint基础
- 灯光师小明