1.NIO最大的变化是把服务端和客户端抽像统一起来,用一个Selector来检测事件。但把服务端与客户端分开来做系统的难度会小些,性能也会高些(因为代码里少了检查是服务端还是客户端的部分)。
2.ServerSocketChannel只支持OP_ACCEPT,SocketChannel支持OP_WRITE、OP_READ、OP_CONNECT事件
3.一个ListenThread与一个Selector一一对应,Selector的select方法是对事件进行轮询,3000个连接大概要耗时20ms(这个是我自己的电脑上测试的结果,比较普通的配置),因此一个selector负责的连接最好不要太多。
4.SocketChannel的register方法会与Selecotr.selector(timeout)相互阻塞,因此最好把所有注册事件和注册变更事件放到selector线程中来执行。
5.同时把所有Accept事件放到selector线程中来处理,这样可以避免线程间的切换,减少连接延时。
6.每次有select事件上来后,先把所有ready事件从interest集中去掉,否则多线程处理时,同样的事件会报多次上来。
7.注意ServerSocketChannel注册的事件必须有OP_ACCEPT,否则下次有SOCKET连接不上,而客户端的OP_CONNECT只是开始注册一次,在检测一次后不需再重新注册OP_CONNECT事件,如果再次重新注册OP_CONNECT事件后会造成Selector.selector(timerout)阻塞不了,一直不停地循环。
8.SocketChannel.open()每次打开一个新的SocketChannel,同理每次Selector.open()也打开一个新的Selector。
9.把所有的OP_ACCEPT事件和修改interest事件交由Selector线程来处理,这样可以避免同步和阻塞,提高性能。
10.windows与linux的线程处理与网络处理还是有很大区别。经测试windows XP适合作客户端(注意缺省情况下,Windows 为匿名(临时)端口保留端口号 1024 到 5000,超出这个数量时就会报no buffer异常 ),如果拿来做服务端,客户端会报大量的connect refuse。而linux2.6的网络处理较好(不管是客户端还是服务端),经测试在CPU2.8G、MEM512M的机子上能轻松处理几万个连接(如果报Too many files open,可能系统设置有关,可通过ulimit -HSn 50000[每个进程能打开的句柄数]来和echo 100000 >/proc/sys/fs/file-max[系统能打开的最大文件句柄数]来设置)。不知道windows2003做为服务器时的性能怎么样。
11.JDK1.4的NIO并不等于AIO,只是在某个调上模拟异步,性能没有AIO好(网上有人说AIO比Epoll高,也有说相反的,这个本人未验证)。AIO的实现有IBM的AIO(windows上采用的是IOCP,linux2.6上采用的AIO)。(性能没有经验证)
12.windows上的socket收发缓存可以随便设置,但linux2.6上最小只能到1024byte(调整内核参数应该可以更改)。
13.JDK1.5update09与jdk6在linux上采用的是epoll,比之前的性能有明显的提高(能处理更多的连接,在短时间内大量连接时会报更少的错误)
14.当连接数太多时,检查连接超时也是个很大问题(每次select后再检查时间截也许是个比较好的办法)。
15.用视图缓冲区比每个连接用一个缓冲要好。(Grizzly的做法是系统有一个大的缓存区4000000Byte,然后每个线程在上面分割一个ByteBuffer)
关于JAVA NIO一些体验
最新推荐文章于 2024-09-04 16:51:20 发布