JAVA NIO相對于Old IO APIs 有非常大的改進,但是使用NIO是受限制的庭再。有些是設(shè)計問題捞奕,有些是缺陷導致,而netty已經(jīng)解決了這些問題拄轻。
①跨平臺與兼容性
NIO算是底層的APIs需依賴奧佐系統(tǒng)的IO APIs颅围。但Jvava NIO發(fā)現(xiàn)在不同系統(tǒng)平臺會出現(xiàn)問題。大量測試也耗不少時間恨搓;NIO2只支持JDK1.7+院促,而且沒提供DatagramSocket,故NIO2不支持UDP協(xié)議斧抱。
而Netty提供統(tǒng)一接口常拓,同一語句無論在JDK6.X 還是JDK7.X 都可運行,無需關(guān)心底層架構(gòu)功能辉浦!
②JAVA NIO的ByteBuffer構(gòu)造函數(shù)私有弄抬,無法擴展。Netty提供了自己的ByteBuffer實現(xiàn)宪郊,通過簡單APIs對其進行構(gòu)造掂恕、使用和操作荔茬,一此解決NIO的一些限制。
③NIO對緩沖區(qū)的聚合與分散操作可能會導致內(nèi)存泄漏竹海。
直到JDK1.7才解決此問題。
④壓碎著名的Epoll缺陷丐黄。
On Linux-like OSs the selector makes use of the epoll- IO event notification facility. This is a high-performance technique in which the OS works asynchronously with the networking stack.Unfortunately,? even? today? the “famous” epoll- bug? can? lead? to? an “invalid” state? in? the selector, resulting in 100% CPU-usage and spinning. The only way to recover is to recycle the old? selector? and? transfer? the? previously? registered? Channel? instances? to? the? newly? created Selector.
Linux-like OSs的選擇器使用的是epoll-IO事件通知工具斋配。這是一個在操作系統(tǒng)以異步方式工作的網(wǎng)絡(luò)stack.Unfortunately,即使是現(xiàn)在灌闺,著名的epoll-bug也可能會導致無效的狀態(tài)的選擇和100%的CPU利用率艰争。要解決epoll-bug的唯一方法是回收舊的選擇器,將先前注冊的通道實例轉(zhuǎn)移到新創(chuàng)建的選擇器上桂对。
What? happens? here? is? that? the Selector.select() method? stops? to? block? and? returns immediately-even? if? there? are? no? selected? SelectionKeys? present.? This? is? against? the contract,? which? is? in? the? Javadocs? of? the? Selector.select()? method:Selector.select() must not unblock if nothing is selected.
這里發(fā)生的是甩卓,不管有沒有已選擇的SelectionKey,Selector.select()方法總是不會阻塞并且會立刻返回蕉斜。這違反了Javadoc中對Selector.select()方法的描述逾柿,Javadoc中的描述:Selector.select() must not unblock if nothing is selected. (Selector.select()方法若未選中任何事件將會阻塞。)
The range of solutions to this epoll- problem is limited, but Netty attempts to automatically detect and prevent it. The following listing is an example of the epoll- bug.
NIO中對epoll問題的解決方案是有限制的宅此,Netty提供了更好的解決方案机错。
下面是epoll-bug的一個例子:
…
while (true) {
int selected = selector.select();
Set readyKeys = selector.selectedKeys();
Iterator iterator = readyKeys.iterator();
while (iterator.hasNext()) {
…
…
}
}
…
The effect of this code is that the while loop eats CPU:
這段代碼的作用是while循環(huán)消耗CPU:
…
while (true) {
}
…
The value will never be false, and the code keeps your CPU spinning and eats resources. This can have some undesirable side effects as it can consume all of your CPU, preventing any other CPU-bound work.
該值將永遠是假的,代碼將持續(xù)消耗你的CPU資源父腕。這會有一些副作用弱匪,因為CPU消耗完了就無法再去做其他任何的工作。
These are only a few of the possible problems you may see while using non-blocking IO. Unfortunately, even after years of development in this area, issues still need to be resolved; thankfully, Netty addresses them for you.
這些僅僅是在使用NIO時可能會出現(xiàn)的一些問題璧亮。不幸的是萧诫,雖然在這個領(lǐng)域發(fā)展了多年,問題依然存在枝嘶;幸運的是帘饶,Netty給了你解決方案。
⑤ Summary
This chapter provided an overview of Netty’s features, design and benefits. I discussed the difference between blocking and non-blocking processing to give you a fundamental understanding of the reasons to use a non-blocking framework. You learned how to use the JDK API to write network code in both blocking and non-blocking modes. This included the new non-blocking API, which comes with JDK 7. After seeing the NIO APIs in action, it was also important to understand some of the known issues that you may run into. In fact, this is why so many people use Netty: to take care of workarounds and other JVM quirks. In the next chapter, you’ll learn the basics of the Netty API and programming model, and, finally, use Netty to write some useful code.