最近在阅读netty(3.2.7)源码的时候,看到服务器端接受客户端连接代码的时候嗅到了一丝不和谐的气味,具体代码见:
org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink类里面的BOSS线程:
public void run() { final Thread currentThread = Thread.currentThread(); channel.shutdownLock.lock(); try { for (;;) { try { if (selector.select(1000) > 0) { selector.selectedKeys().clear(); } SocketChannel acceptedSocket = channel.socket.accept(); if (acceptedSocket != null) { registerAcceptedChannel(acceptedSocket, currentThread); } } catch (SocketTimeoutException e) { // Thrown every second to get ClosedChannelException // raised. } catch (CancelledKeyException e) { // Raised by accept() when the server socket was closed. } catch (ClosedSelectorException e) { // Raised by accept() when the server socket was closed. } catch (ClosedChannelException e) { // Closed as requested. break; } catch (Throwable e) { logger.warn( "Failed to accept a connection.", e); try { Thread.sleep(1000); } catch (InterruptedException e1) { // Ignore } } } } finally { channel.shutdownLock.unlock(); closeSelector(); } }
1、selector.selectedKeys().clear();不管当前有多少个SelectionKey被触发,都一律清除掉,然后
2、SocketChannel acceptedSocket = channel.socket.accept();只接受一个链接。
曾今阅读别人对于NETTY的性能测试的时候貌似有说到在客户端高并发请求访问会出现丢包现象
今天看到这段代码怀疑就是这段代码的问题,稍微修改代码成如下来验证:
public void run() { final Thread currentThread = Thread.currentThread(); channel.shutdownLock.lock(); try { for (;;) { try { /** * 由于Runnable没有简单的sleep,所以我这里使用很土的方式让线程暂停30秒再去执行selector操作。 * 测试如果服务器启动后,30秒内有三个客户端连接请求过来,服务器端会处理几次. */ Long currentTime = System.currentTimeMillis(); while(true){ if(System.currentTimeMillis() - currentTime>30000){ break; } } if (selector.select(1000) > 0) { selector.selectedKeys().clear(); } SocketChannel acceptedSocket = channel.socket.accept(); if (acceptedSocket != null) { registerAcceptedChannel(acceptedSocket, currentThread); } } catch (SocketTimeoutException e) { // Thrown every second to get ClosedChannelException // raised. } catch (CancelledKeyException e) { // Raised by accept() when the server socket was closed. } catch (ClosedSelectorException e) { // Raised by accept() when the server socket was closed. } catch (ClosedChannelException e) { // Closed as requested. break; } catch (Throwable e) { logger.warn( "Failed to accept a connection.", e); try { Thread.sleep(1000); } catch (InterruptedException e1) { // Ignore } } } } finally { channel.shutdownLock.unlock(); closeSelector(); } }
可以直接使用netty中的例子DiscardServer和DiscardClient来做试验。开启一个DiscardServer后,然后在30秒内直接连续启动四个DiscardClient,等30秒后发现服务器端只接受并分配了一个链接.
-------------------------------------------------------------------分割线----------------------------------------------------------------------------------------
然后我去下了最稳定发布版本的netty源码,最新的稳定版截止到本文撰写时间为(3.6.5版),在这个版本中服务器端的Boss类的代码被抽出来形成了NioServerBoss.其中的代码为:
protected void process(Selector selector) { Set<SelectionKey> selectedKeys = selector.selectedKeys(); if (selectedKeys.isEmpty()) { return; } for (Iterator<SelectionKey> i = selectedKeys.iterator(); i.hasNext();) { SelectionKey k = i.next(); i.remove(); NioServerSocketChannel channel = (NioServerSocketChannel) k.attachment(); try { // accept connections in a for loop until no new connection is ready for (;;) { SocketChannel acceptedSocket = channel.socket.accept(); if (acceptedSocket == null) { break; } registerAcceptedChannel(channel, acceptedSocket, thread); } } catch (CancelledKeyException e) { // Raised by accept() when the server socket was closed. k.cancel(); channel.close(); } catch (SocketTimeoutException e) { // Thrown every second to get ClosedChannelException // raised. } catch (ClosedChannelException e) { // Closed as requested. } catch (Throwable t) { if (logger.isWarnEnabled()) { logger.warn( "Failed to accept a connection.", t); } try { Thread.sleep(1000); } catch (InterruptedException e1) { // Ignore } } } }
在这个版本会根据SelectionKey的个数来来接受客户端的请求,这个版本我未做过性能测试,应该可以解决客户端高并发下的丢包现象.
PS:最新更新到4.0的版本的netty代码又发生了翻天覆地的变化,还是直接去阅读4.0的代码到时候.
相关推荐
netty-3.2.7.final JAR包,netty-3.2.7.final JAR包,netty-3.2.7.final JAR包
JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA版基于netty的物联网高并发智能网关 JAVA...
Android Studio 开发Netty网络访问框架,实现了客户端、服务端两种访问方式,支持发送心跳数据,使用Handler实现外部数据交互,有调用Demo,在实际项目中使用暂时没有问题
Netty 高并发深入浅出学习高并发服务器Netty 高并发深入浅出学习高并发服务器
通过netty编写文件传输的客户端与服务端,以及协议说明, 通用的netty传输协议 通过该协议进行文件传输 文件传输客户端与服务端 可以根据文件的最后更新时间来增量传输文件 源码开放,通过eclipse或者idea导入代码...
Java异步NIO框架Netty实现高性能高并发无标题笔记 1. 背景 1.1. 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨 节点...
C# Netty 客户端,服务器端 自己研究一才研究出来的与大家分享一下
netty-3.2.7.Final 源码包,包含pom文件,eclipse或者myeclipse导入就可用,方便学习源码和进行二次开发。
spring boot demo,整合netty5实现高并发websocket,并引入slf4g+lombok,采用maven形式; 直接导入运行,有测试页面也有实现代码及详细注释,src/main/webapps/TestNettyWebSocket.html里第十行改成 ws://localhost...
实现Java服务端和C#客户端联通 Java使用Netty 开发环境为IDEA C#使用DotNetty 开发环境为VS2017 运行时先开启Java服务端 再开启客户端
Java + Netty 实现的高并发高可用MQTT服务broker,轻松支持10万并发,已用于生产环境 技术体系:(使用 netty 实现通信及协议解析,使用 nutzboot 提供依赖注入及属性配置,使用 redis 实现消息缓存,集群,使用 ...
NULL 博文链接:https://jonenine.iteye.com/blog/2170673
同过netty实现HTTP服务器(或者客户端) 。务器提供诸如HTML文件和其他内容之类的资源,或代表客户端执行其他功能,向客户端返回响应消息。 响应包含有关请求的完成状态信息,并且还可以在其消息正文中包含所请求的...
springboot整合netty,分客户端和服务端两个项目,springboot整合netty,分客户端和服务端两个项目,springboot整合netty,分客户端和服务端两个项目,springboot整合netty,分客户端和服务端两个项目
netty-3.2.7.Final
Netty中实现多客户端连接与通信-以实现聊天室群聊功能为例示例代码
netty5.0通信框架实现客户端和服务器端demo 的数据对象传输,控制的比较完美,里面包括了netty5.0通信框架jar包
netty-高并发编程-视频教程张龙
详细的netty框架的简单案例,包括客户端服务端
android netty5局域网通讯(客户端+服务端),可以直接运行