NIO Buffer带给我们的好处是在进行I/O数据读写时可以用块模式进行了,这相比以往使用字节的模式效率提升不小。首先我们来看下NIO 给我们提供了什么样的Buffer,他们都有些啥子特点,我们在应用应该怎样使用他们以扬长避短达到最佳的效率。
NIO提供了2种类型的Buffer,Direct Buffer 和 Heap Buffer。 Direct Buffer是创建在非java heap上的系统级缓冲区,创建和销毁的开销大;但与I/O数据交换非常快,可以直接与I/O进数据交换。Heap Buffer创建于java heap 上,相当于一个byte[]的封装,创建和销毁开销小。但不能直接与I/O进行数据交换,必须通过一个临时的Direct Buffer来中转数据,所以与I/O的数据交换速度慢。
个人比较认同以下3点意见:
1、 劣势:创建和释放Direct Buffer的代价比Heap Buffer得要高;
2、 区别:Direct Buffer不是分配在堆上的,它不被GC直接管理(但Direct Buffer的JAVA对象是归GC管理的,只要GC回收了它的JAVA对象,操作系统才会释放Direct Buffer所申请的空间),它似乎给人感觉是“内核缓冲区(buffer in kernel)”。Heap Buffer则是分配在堆上的,或者我们可以简单理解为Heap Buffer就是byte[]数组的一种封装形式,查看JAVA源代码实现,Heap Buffer也的确是这样。
3、 优势:当我们把一个Direct Buffer写入Channel的时候,就好比是“内核缓冲区”的内容直接写入了Channel,这样显然快了,减少了数据拷贝(因为我们平时的read/write都是需要在I/O设备与应用程序空间之间的“内核缓冲区”中转一下的)。而当我们把一个Heap Buffer写入Channel的时候,实际上底层实现会先构建一个临时的Direct Buffer,然后把Heap Buffer的内容复制到这个临时的Direct Buffer上,再把这个Direct Buffer写出去。当然,如果我们多次调用write方法,把一个Heap Buffer写入Channel,底层实现可以重复使用临时的Direct Buffer,这样不至于因为频繁地创建和销毁Direct Buffer影响性能。
下面也摘录了一些网上的总总结:
好,前面说了这么多。那CshBBrain到底采用了怎样的使用策略呢。下面我就详细介绍下。
CshBBrain中全部使用Direct Buffer来与I/O进行数据交换,而且只有与I/O有进行数据交换时才使用Buffer.任何一个网络服务器要使用Buffer与I/O进行数据交换的地方无非是读取客户端的数据和向客户端发送数据的地方,CshBBrain中也不例外。
首先来看数据读取的实现,在CshBBrain中当有客户端发送数据到服务器时,服务器会给分配一个工作线程Worker来进行数据读取,协议解码,业务处理和协议编码。所以在每个Worker中都有创建一个Direct Buffer,这个Buffer 在工作线程创建时就已经创建了,每次把任务分配给该线程的时候该线程就重复利用此Buffer来从I/O读取数据,读取完数据后将Buffer重置以便后面的连接重复使用。
Worker类中的相关代码:
private ByteBuffer charBuffer = null;// 读取缓冲区 定义缓冲区
this.charBuffer = ByteBuffer.allocateDirect(1024 * bufferSize);// 创建读取缓冲区
public void process(SelectionKey selectionKey){
Client key = Client.getSockector(selectionKey);
if(key.getMessages(charBuffer)){ // 已完成握手,从客户端读取报刊,重复利用
key.process();// 进行业务处理
}
}
Client类中使用worker中的buffer读取数据:
do{// 读取客户端请求的数据并解码
dataLength = socketChannel.read(byteBuffer);
if(dataLength > 0){
byteBuffer.flip();
this.decoderHandler.process(byteBuffer,this);// 解码处理
byteBuffer.clear();
readSuccess = true;
this.readDataFlag = true;// 将读取数据标识设置为真
this.preBlank = false;// 上次不为空读
}else{
if(this.preBlank){
++this.readCount;
}
this.preBlank = true;
break;
}
}while(dataLength > 0);
最后来看CshBBrain中数据发送的实现,CshBBrain将处理好的内容放入Client对象的responseMsgs队列中,然后由sendMsgs方法进行数据发送。发送数据给I/O时并不创建Direct Buffer,而是从BufferPool中获取一个Direct Buffer.BufferPool是CshBBrain中的Direct Buffer缓存池,服务器启动时根据系统参数minBufferPoolSize、maxBufferPoolSize和writeBuffer创建好指定数量指定大小的Direct Buffer,CshBBrain每次想I/O写数据时,从BufferPool缓冲池中获取一个Direct Buffer使用,使用完毕将Direct Buffer 重置放回BufferPool中供其他线程使用。这样就避免每次写数据都重复创建缓存的情况。
发送数据到I/O的Response类中相关代码:
if(bb == null){// 如果缓冲区为空,则从缓冲池中获取一个缓冲区
bb = BufferPool.getInstance().getBuffer();
}
写完数据重置缓冲区,放回缓冲池
buffer.clear();
BufferPool.getInstance().releaseBuffer(buffer);// 将用完的缓冲区放回缓冲区池
总之在开源Websocket服务器CshBBrain中,全部使用Direct Buffer.在worker线程和BufferPool中维护Direct Buffer,并实现最大限度的重用这些Direct Buffer来达到最好一个效果。Direct Buffer 和Heap Buffer的选用上本来都比较麻烦,作者也还在不断探索,如果你有好的方案望不吝赐教。
- 大小: 51.4 KB
- 大小: 57.3 KB
分享到:
相关推荐
MongoDB的Java驱动程序使用NIO进行网络通信,允许一个线程管理多个连接,提高了服务器的并发处理能力。NIO的核心组件包括Selector、Channel和Buffer。Selector用于监听多个通道的事件,Channel是数据传输的路径,...
NIO是一种不同于传统I/O的编程模型,它允许程序在等待数据读写时执行其他任务,从而提高了并发处理性能,尤其是在高并发的服务器端应用中。 Cindy-3.0b1-src这个版本是Cindy框架的源代码包,对于开发者来说,了解其...
【标题】:“手写 Tomcat NIO” 在深入探讨手写Tomcat NIO之前,我们首先需要理解NIO(Non-...在实际项目中,如果需要高性能的Web服务器,可能需要考虑使用成熟的开源产品,如Tomcat本身或Netty等高性能NIO框架。
2. **Grizzly**:是Sun Microsystems(现Oracle)开发的一个开源NIO框架,支持HTTP、WebSocket等多种协议。 **性能比较:** Java NIO相对于IO,在处理高并发、大数据量的场景下表现出更好的性能。IO模型更适合于...
在"tomcatNIO.zip"项目中,开发者可以深入研究如何配置和使用NIO模式的Tomcat,以及如何与Spring Boot框架进行集成。项目中的代码实例可以帮助理解NIO在实际Web服务中的工作原理,包括连接管理、线程池配置、异常...
Netty 开源框架实用知识库分享知识分享 Netty 是一个高性能、异步的网络编程框架,可以快速地开发高性能的网络应用程序 本文档将详细介绍 Netty 的核心概念、实现原理和实践应用,旨在帮助开发者快速掌握 Netty 的...
它是一个开源的Java库,广泛应用于服务器和客户端的开发,尤其在处理高并发、低延迟的网络服务时,Netty的表现尤为突出。Netty的核心是基于NIO(非阻塞I/O)和EventLoop事件驱动模型,这使得它能够在单线程或多线程...
6. 社区活跃:Netty 是活跃的开源项目,版本迭代周期短,bug 修复速度快。 Netty 的应用场景有哪些? 典型的应用有:阿里分布式服务框架 Dubbo,默认使用 Netty 作为基础通信组件,还有 RocketMQ 也是使用 Netty ...
《Netty实战》是关于...通过阅读《Netty实战》,你将掌握Netty的关键特性,学会如何在实际项目中使用Netty,提升网络应用的开发效率和性能。这本书的内容覆盖广泛,无论你是初学者还是资深开发者,都能从中获益匪浅。
在Java世界中,Netty因其高效、易用和丰富的特性而被广泛应用于多种场景,如RPC(远程过程调用)、游戏服务器、流媒体服务、WebSocket服务器等。Netty的核心是它的NIO(非阻塞I/O)模型,这使得它在处理大量并发连接...
- 通过这些示例,开发者可以更好地理解Netty的使用方式,并将其应用于实际项目中。 6. **源码剖析** - 分析Netty源码有助于深入理解其内部机制,例如,EventLoopGroup如何管理线程,Pipeline如何处理数据,以及...
《Netty 权威指南》可能涵盖了 Netty 在实际项目中的应用案例,比如构建WebSocket服务器、RPC框架、消息队列中间件等,通过这些案例,读者可以更好地理解如何在实际工作中应用 Netty。 总之,《Netty 全文指南》...
2. **Netty概述**:Netty由JBOSS组织开发,后来成为独立的开源项目。它提供了一套丰富的预定义的处理器链(Channel Pipeline),可以处理各种网络协议,如TCP、UDP、HTTP、FTP等。Netty的API设计简单且直观,便于...
Netty是一个开源的Java NIO框架,它简化了网络编程,特别是对于TCP和UDP协议的应用。这本书不仅涵盖了Netty的基础知识,还深入解析了其高级特性,是Java网络编程领域的重要参考资料。 首先,书中详细介绍了Netty的...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高...通过PPT的学习和示例代码的实践,开发者可以深入理解Netty的工作原理,从而在实际项目中更好地利用其优势,构建高效稳定的网络应用。
Netty 是由JBOSS组织开发的一个开源项目,最初设计用于解决Java NIO框架的复杂性问题。Netty提供了高度抽象的API,使得开发者可以轻松地处理网络通信的各种细节,如连接管理、数据编码解码、线程模型等。 2. **...
《Netty权威指南》是Java领域中关于网络编程的一本重要参考书籍,尤其在第二版中,它深入探讨了非阻塞I/O(NIO,Non-blocking I/O)技术,这是Java开发高并发、高性能网络应用的核心技术。Netty是一个开源的异步事件...
在实际项目中,Netty常用于开发高性能的服务器,如聊天服务器、游戏服务器、流媒体服务器等。此外,它也是许多开源项目如Dubbo、Spring Cloud等首选的网络通信框架。 10. **最佳实践** 学习Netty时,应掌握如何...
- Netty的起源:Netty最初由JBoss团队开发,现为Apache 2.0许可下的开源项目。 - Netty的核心理念:基于NIO(非阻塞I/O)模型,利用事件驱动架构,提高网络应用的性能和可扩展性。 - Netty的优势:高吞吐量、低...
- Netty的起源:Netty是由JBOSS组织开发的开源项目,最初为解决Java平台上的NIO(非阻塞I/O)编程复杂性而设计。 - Netty的核心理念:提供一个高度可定制的、组件化的网络通信框架,简化网络应用的开发和维护。 -...