项目场景:
基于Netty实现的文件管理,对客户端windows系统上的大量中小文件进行上传,并回调rest接口记录文件上传状态。
问题描述
在运行了一段时间后,文件传输过程中出现如下异常:
io.netty.channel.AbstractChannel$AnnotatedSocketException: Address already in use: no further information: /10.168.18.170:8345Caused by: java.net.BindException: Address already in use: no further informationat sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:715)at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330)at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:710)at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)at java.lang.Thread.run(Thread.java:748)04-25 11:23:07.931 INFO [client-1-3][HttpClientUtil.java:49]- url http://127.0.0.1:8877/test/taskreDataRequest param {msg=, task=b14c8549263e429f8038e8546e4fce91, action=upload, model=start}java.lang.IllegalStateException: org.apache.http.nio.reactor.IOReactorException: Failure opening selectorat org.apache.http.impl.nio.client.IOReactorUtils.create(IOReactorUtils.java:45)at org.apache.http.impl.nio.client.HttpAsyncClientBuilder.build(HttpAsyncClientBuilder.java:686)at cn.com.sdgs.test.client.util.HttpClientUtil.doGet(HttpClientUtil.java:54)at cn.com.sdgs.test.client.util.HttpClientUtil.callBack(HttpClientUtil.java:50)at cn.com.sdgs.test.client.handler.ClientUploadHandler.read(ClientUploadHandler.java:65)at cn.com.sdgs.test.client.handler.ClientUploadHandler.init(ClientUploadHandler.java:34)at cn.com.sdgs.test.client.handler.ClientDispatchHandler.channelRead0(ClientDispatchHandler.java:75)at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)at java.lang.Thread.run(Thread.java:748)Caused by: org.apache.http.nio.reactor.IOReactorException: Failure opening selectorat org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.<init>(AbstractMultiworkerIOReactor.java:144)at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.<init>(DefaultConnectingIOReactor.java:82)at org.apache.http.impl.nio.client.IOReactorUtils.create(IOReactorUtils.java:43)... 32 moreCaused by: java.io.IOException: Unable to establish loopback connectionat sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:94)at sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:61)at java.security.AccessController.doPrivileged(Native Method)at sun.nio.ch.PipeImpl.<init>(PipeImpl.java:171)at sun.nio.ch.SelectorProviderImpl.openPipe(SelectorProviderImpl.java:50)at java.nio.channels.Pipe.open(Pipe.java:155)at sun.nio.ch.WindowsSelectorImpl.<init>(WindowsSelectorImpl.java:127)at sun.nio.ch.WindowsSelectorProvider.openSelector(WindowsSelectorProvider.java:44)at java.nio.channels.Selector.open(Selector.java:227)at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.<init>(AbstractMultiworkerIOReactor.java:142)... 34 moreCaused by: java.net.SocketException: No buffer space available (maximum connections reached?): connectat sun.nio.ch.Net.connect0(Native Method)at sun.nio.ch.Net.connect(Net.java:459)at sun.nio.ch.Net.connect(Net.java:451)at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:646)at java.nio.channels.SocketChannel.open(SocketChannel.java:189)at sun.nio.ch.PipeImpl$Initializer$LoopbackConnector.run(PipeImpl.java:127)at sun.nio.ch.PipeImpl$Initializer.run(PipeImpl.java:76)... 43 more04-25 11:23:08.879 ERROR [Worker-1][UploadService.java:34]- connect or send msg error 2d175e278b5249e083dfc5ed34b17e5a
原因分析:
错误信息Address already in use: no further information: /10.168.18.170:8345,具有迷惑性,貌似8345端口被占用,实际上是因为短时大量连接占用了过多的端口。Windows的默认最大TCP连接端口数(MaxUserPort)是5000,默认240秒释放之前的操作完的连接端口。
解决方案1:
可以使用以下命令在运行 Windows Vista 或 Windows Server 2008 netsh 的计算机上查看动态端口范围:
netsh int ipv4 show dynamicport tcp
使用 netsh 命令扩大动态端口,如下所示:
netsh int <ipv4|ipv6> set dynamic <tcp|udp> start= number num= range。
此命令设置 TCP 的动态端口范围。 起始端口为 数字,端口总数为 范围。
下面是示例命令:
netsh int ipv4 set dynamicport tcp start=20000 num=8000
解决方案2:
使用连接池减少连接的创建。