±à¼ÍƼö: |
±¾ÎÄÀ´×ÔÓÚ΢ÐŹ«ÖںţºOutOfMemoryError£¬±¾ÎÄÖ÷Òª½éÉÜÁËʲôÊÇI/O¶à·¸´Óã¬
ReactorÈýÖÖÏß³ÌÄ£ÐÍ £¬NettyÏß³ÌÄ£ÐÍ£¬NioEventLoopÔ´Âë·ÖÎöµÈÄÚÈÝ
£¬Ï£Íû¶ÔÄúÄÜÓÐËù°ïÖú¡£ |
|
µ±ÎÒÃÇ̸ÂÛNettyµÄÏß³ÌÄ£ÐÍʱ£¬Ê×ÏÈ»áÏëµ½µÄÊǾµäµÄReactor
IO¶à·¸´ÓÃÏß³ÌÄ£ÐÍ¡£´ÓÕâÆªÎÄÕÂÖУ¬´ó¼Ò¿ÉÒÔѧϰµ½ÈçÏÂ֪ʶ£º
ʲôÊÇI/O¶à·¸´ÓÃ
ReactorÈýÖÖÏß³ÌÄ£ÐÍ
NettyÏß³ÌÄ£ÐÍ
NioEventLoopÔ´Âë·ÖÎö
JDK epoll bug
ʲôÊÇI/O¶à·¸´ÓÃ
ѧϰI/O¶à·¸´ÓÃ֮ǰ£¬ÎÒÃÇÏÈÀ´Á˽âÈçϼ¸¸ö¸ÅÄ
×èÈûI/O£º¿Í»§¶Ë´ÓsocketÖжÁÈ¡Êý¾Ý»òдÈëÊý¾Ýʱ£¬Èç¹û¶ÁȡʱÁ÷ÖÐûÓÐÊý¾Ý£¬Ð´Èëʱ»º³åÇøÒÑÂú£¬¾ÍÐèÒªblock£¬ÖªµÀÁ÷ÖÐÓÐÊý¾Ý»òÕß»º³åÇøµÄÊý¾Ý±»Åſա£
·Ç×èÈûI/O£º¿Í»§¶Ë´ÓÁ÷ÖжÁÈ¡Êý¾Ý£¬Èç¹ûÁ÷ÖÐûÓÐÊý¾Ý£¬ÔòÁ¢¼´·µ»Ø£¬²»·¢Éúblock¡£
ͬ²½I/O£ºÍ¬²½I/O½«µ¼ÖÂÇëÇóµÄI/O²Ù×÷Ò»Ö±±»block£¬Ö±µ½I/OÍê³É¡£
Òì²½I/O£ºÒì²½I/O²»»áµ¼ÖÂblock£¬·¢³öI/OÇëÇóºóÁ¢¼´·µ»Ø£¬Ö±µ½Íê³ÉI/O²Ù×÷ºóÔÙÒ첽֪ͨµ÷Óýø³Ì¡£
I/O¶à·¸´ÓÿÉÒÔ¼àÊÓ¶à¸öFD£¨ÎļþÃèÊö·û£©£¬Ò»µ©Ä³¸öFD×¼±¸¾ÍÐ÷£¬¾Í»á֪ͨÏàÓ¦½ø³Ì´¦Àí¡£¶à·¸´ÓÃÒ²ÊÇ×èÈûµÄ£¬×èÈûµÄ·½·¨ÊÇselect/poll/epoll£¬¿ÉÒÔÔÚµ¥¸ö½ø³ÌÖÐͬʱ´¦Àí¶à¸öI/OÇëÇó£¬ÔÀíÊDzÉÓÃÂÖѯµÄ·½Ê½±ãÀûËùÓеÄI/O²Ù×÷£¬µ±Ä³Ð©I/OÓÐÊý¾Ýʱ£¬¾Í֪ͨÓû§½ø³Ì´¦Àí¡£
select£ºÏµÍ³Ìṩselectº¯ÊýÀ´ÊµÏÖ¶à·¸´ÓÃÊäÈë/Êä³öÄ£ÐÍ£¬selectϵͳµ÷ÓÃÊÇÓÃÀ´ÈÃÎÒÃǵijÌÐò¼àÊÓ¶à¸öÎļþ¾ä±úµÄ״̬±ä»¯¡£³ÌÐò»á×èÈûÔÚselectº¯ÊýÉÏ£¬Ö±µ½±»¼àÊÓµÄÎļþ¾ä±úÖÐÓÐÒ»¸ö»ò¶à¸ö·¢ÉúÁË״̬±ä»¯¡£
poll£ºpollº¯ÊýÓëselectº¯ÊýµÄ×î´ó²»Í¬Ö®´¦ÔÚÓÚ£ºselectº¯ÊýÓÐ×î´óÎļþÃèÊö·ûµÄÏÞÖÆ£¬Ò»°ã1024¸ö£¬¶øpollº¯Êý¶ÔÎļþÃèÊö·ûµÄÊýÁ¿Ã»ÓÐÏÞÖÆ¡£
epoll£º
¼àÊÓµÄÃèÊö·ûÊýÁ¿²»ÊÜÏÞÖÆ£¬ËùÖ§³ÖµÄFDÉÏÏÞÊÇLinuxϵͳ×î´ó¿ÉÒÔ´ò¿ªÎļþµÄÊýÄ¿£»
I/OЧÂʲ»»áËæ×żàÊÓfdµÄÊýÁ¿Ôö³¤¶øÏ½µ¡£epoll²»Í¬ÓÚselectºÍpollÂÖѯµÄ·½Ê½£¬¶øÊÇͨ¹ýÿ¸öfd¶¨ÒåµÄ»Øµ÷º¯ÊýÀ´ÊµÏֵģ¬Ö»ÓоÍÐ÷µÄfd²Å»áÖ´Ðлص÷º¯Êý¡£
ReactorÈýÖÖÏß³ÌÄ£ÐÍ
1. Reactorµ¥Ïß³ÌÄ£ÐÍ
ÊÇÖ¸ËùÓеÄI/O²Ù×÷¶¼ÔÚͬһ¸öNIOÏß³ÌÉÏÍê³É£¬Ö°ÔðÈçÏÂ
×÷ΪNIO·þÎñ¶Ë£¬½ÓÊÕ¿Í»§¶ËTCPÁ¬½Ó
×÷ΪNIO¿Í»§¶Ë£¬Ïò·þÎñ¶Ë·¢ÆðTCPÁ¬½Ó
¶ÁÈ¡¶Ô¶ËÇëÇó»òÕßÓ¦´ðÏûÏ¢
Ïò¶Ô¶Ë·¢ËÍÇëÇó»òÕßÓ¦´ðÏûÏ¢

ÔÚһЩСÈÝÁ¿³¡¾°Ï£¬¿ÉÒÔʹÓöàÏß³ÌÄ£ÐÍ£¬µ«¶ÔÓڸ߸ºÔس¡¾°Ï²¢²»ÊÊÓã¬ÔÒòÈçÏ£º
Ò»¸öNIOÏß³Ìͬʱ´¦Àí³É°ÙÉÏǧµÄÁ¬½Ó£¬ÐÔÄÜÉÏÎÞ·¨±£Ö¤¡£
NIOÏ̸߳ºÔعýÖØ£¬´¦ÀíËÙ¶È»áÔ½À´Ô½Âý£¬»áµ¼Ö´óÁ¿¿Í»§¶ËÁ¬½Ó³¬Ê±
Ò»µ©NIOÏß³ÌÅÜ·É£¬»òÕßËÀÑ»·£¬»áµ¼ÖÂÕû¸öϵͳµÄ²»¿ÉÓÃ
2. Reactor¶àÏß³ÌÄ£ÐÍ

Óëµ¥Ïß³ÌÄ£ÐÍ×î´óµÄÇø±ðÊÇ£¬ÓÐÒ»×éNIOÀ´´¦ÀíI/OÇëÇó£¬ÌصãÈçÏÂ
ÓÐÒ»¸öNIOÏ̡߳ª¡ªAcceptorÏß³ÌÓû§¼àÌý¿Í»§¶ËµÄÁ¬½Ó
ÓÐÒ»¸öNIOÏ̳߳ظºÔðI/OµÄ¶Áд²Ù×÷£¬¸ÃÏ̳߳ؿÉÒÔÊÇ»ùÓÚJDKµÄÏ̳߳ء£
3. Ö÷´ÓReactor¶àÏß³ÌÄ£ÐÍ

Èç¹û²¢·¢°ÙÍòµÄ¿Í»§¶ËÁ¬½Ó£¬ÔÚReactor¶àÏß³ÌÄ£ÐÍÏÂÖ»ÓÐÒ»¸öNIOµÄAcceptorÏ̴߳¦Àí¿Í»§¶ËÁ¬½Ó»áÓÐÐÔÄÜÎÊÌâ¡£Ö÷´ÓReactorÏß³ÌÄ£Ð͵ÄÌØµãÊÇ£º·þÎñ¶ËÓÃÓÚ½ÓÊÕ¿Í»§¶ËµÄÁ¬½Ó²»ÔÙÊÇÒ»¸öµ¥¶ÀµÄNIOỊ̈߳¬¶øÊÇÒ»¸öNIOµÄAcceptorÏ̳߳ء£Acceptor½ÓÊÕµ½¿Í»§¶ËµÄTCPÁ¬½ÓÇëÇó´¦ÀíÍê³Éºó£¬½«Ð´´½¨µÄChannelSocket×¢²áµ½I/OÏ̳߳Ø(sub
reactorÏ̳߳Ø)ÉϵÄijһ¸öÏß³ÌÉÏ£¬ÓÉI/O¸ºÔðºóÐøµÄI/O¶Áд²Ù×÷¡£
4. NettyÏß³ÌÄ£ÐÍ

»¹¼ÇµÃNetty·þÎñ¶ËÆô¶¯Ê±µÄ´úÂëÂ𣿣¿
EventLoopGroup
bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup(); |
·þÎñ¶ËÆô¶¯Ê±´´½¨ÁËÁ½¸öNioEventLoopGroup£¬ËûÃÇʵ¼ÊÉÏʱÁ½¸ö¶ÀÁ¢µÄReactorÏ̳߳أ¬Ò»¸ö¸ºÔð½ÓÊÕ¿Í»§¶ËµÄTCPÁ¬½Ó£¬ÁíÒ»¸öÓÃÓÚ´¦ÀíI/O²Ù×÷£¬»òÖ´ÐÐϵͳTask¡¢¶¨Ê±ÈÎÎñTaskµÈ£¬ÈçÉÏͼËùʾµÄÁ½¸ö·½·¨£º
NioEventLoop.execute(Runnable
task)
NioEventLoop.schedule(Runnable task) |
NioEventLoopÔ´Âë·ÖÎö
ÏÈÈÃÎÒÃÇÀ´¿´¿´NioEventLoopµÄ¼Ì³Ð¹ØÏµÍ¼

NioEventLoopÐèÒª´¦ÀíÍøÂçI/O²Ù×÷£¬Ê×ÏȾۺÏÁËÒ»¸ö¶à·¸´ÓÃÆ÷Selector,²¢ÇÒNioEventLoopµÄ¹¹Ôì·½·¨ÖÐÖ±½Óµ÷ÓÃopenSelector()·½·¨Íê³É³õʼ»¯¡£

´úÂëÖг£Á¿DISABLE_KEYSET_OPTIMIZATION(selectedKeysÓÅ»¯¿ª¹Ø)ĬÈÏΪfalse£¬Ôòͨ¹ý·´ÉäµÄ·½Ê½»ñµÃSelector£¬·ñÔòÖ±½Ó·µ»Ø¡£

½ÓÏÂÀ´Öص㿴һÏÂrun·½·¨

Õû¸örun·½·¨ÓÃÒ»¸öwhileÑ»·°üΧ£¬Ê×ÏȽ«wakenUp²ÎÊýÉèÖÃΪfalse²¢½«¾ÉÖµ±£´æÔÚoldWakenUpÖС£
1¡¢µ÷ÓÃhasTask()Åж϶ÓÁÐÖÐÊÇ·ñÓÐÈÎÎñ£¬Èç¹ûÓÐÔòÖ´ÐÐselectNow()·½·¨£¬¸Ã·½·¨»áÁ¢¼´³ö·¢SelectµÄÑ¡Ôñ²Ù×÷ÅжÏÊÇ·ñÓÐ×¼±¸¾ÍÐ÷µÄChannel£¬Èç¹ûÓÐÔò·µ»ØChannelµÄ¼¯ºÏ£¬·ñÔò·µ»Ø0¡£
2¡¢Èç¹ûûÓÐÈÎÎñ£¬Ôòµ÷ÓÃselect()·½·¨ÂÖѯ,¿´ÊÇ·ñÓÐ×¼±¸¾ÍÐ÷µÄChannel£¬select()´úÂëÈçÏ£º

Åж϶ÓÁÐÖÐÊÇ·ñÓÐÒѳ¬Ê±»ò¼´½«Ö´ÐеĶ¨Ê±ÈÎÎñ£¬ÈçÓУ¬Ôòµ÷ÓÃselectNow()·½·¨²¢½«selectCntÖÃΪ1£¬²¢Í˳öµ±Ç°Ñ»··µ»Ørun()·½·¨¡£·ñÔò½«³¬Ê±Ê±¼ä×÷Ϊ²ÎÊý½øÐÐselect()£¬Ã¿´Îselectºó¶¼Òª½«selectCnt++£¬Èç¹ûÂú×ãÈçÏÂÌõ¼þÔòÍ˳öÑ»·¼ÌÐørun()·½·¨µÄºóÃæµÄÂß¼¡£
if (selectedKeys
!= 0 || this.oldWakenUp || this.wakenUp.get()
|| this.hasTasks()) {
break;
} |
Èç¹û±¾´ÎSelectorµÄÂÖѯ½á¹ûΪ¿Õ£¬ËµÃ÷ÕâÊÇÒ»¸ö¿ÕÂÖѯ£¬ÓпÉÄܳö·¢ÁËJDKµÄepoll bug£¬Õâ¸öbug»áµ¼ÖÂÒ»Ö±¿ÕÂÖѯʹI/OÏß³ÌÒ»Ö±´¦ÓÚ100%µÄ״̬£¬´Ëʱ¾ÍÐèÒªÖØ½¨SelectorÀ´±ÜÃâ·¢ÉúÕâÀàÎÊÌ⣬rebuildSelector()´úÂëÈçÏ£º

rebuildSelectorµÄÖ÷ÒªÂß¼ÊÇ£ºÊ×ÏÈÅжÏÊÇ·ñÓÐÆäËûÏß³ÌÔÚ½øÐÐrebuild£¬ÈçÓÐÔò½«±¾´Î²Ù×÷·â×°³ÉÒ»¸ötask·ÅÈë¶ÓÁУ¬±ÜÃâ¶àÏß³Ìͬʱrebuild¡£È»ºó´´½¨ÐµÄSelector£¬Í¨¹ýÑ»·½«×¢²áÔھɵÄSelectorÉϵÄSocketChannel×¢²áÔÚеÄSelectorÉϲ¢¹Ø±Õ¾ÉµÄSelector¡£
ÈÃÎÒÃÇÔÙ·µ»Ørun()·½·¨¿´¿´ºóÃæµÄÂß¼¡£
ÔÚopenSelector()·½·¨ÖÐÎÒÃǵÃÖª£¬Èç¹ûDISABLE_KEYSET_OPTIMIZTIONΪfalseʱ£¬Í¨¹ý·´Éä»ñµÃ¶à·¸´ÓÃÆ÷selector£¬ºÍselectedKeys£¬ËùÒÔrun·½·¨½ÓÏÂÀ´»áµ÷processSelectedKeysPlain()·½·¨
if (this.selectedKeys
!= null) {
this.processSelectedKeysOptimized (this.selectedKeys.flip());
} else {
this.processSelectedKeysPlain (this.selector.selectedKeys());
} |

Ñ»·selectedKeys£¬»ñÈ¡sekectionKeyºÍËüµÄ¸½¼þÐÅÏ¢k.attachment()£¬
Èç¹ûËüÊÇÒ»¸öAbstractnioChannelµÄʵÀý£¬ËµÃ÷ËüÊÇÒ»¸öNioServerSocketChannel»òNioSocketChannel£¬ÐèÒª½øÐÐI/O²Ù×÷£¬·ñÔòËüÊǸö¶¨Ê±ÈÎÎñ¡£
I/O²Ù×÷ʱµÄÔ´ÂëÈçÏ£º

NioUnsafeÀàÊÇÖ÷Òª¶ÔByteBuf½øÐжÁдµÄÀ࣬Ê×ÏÈÅжÏreadyOps×ֶΣ¬Èç¹ûÊǶÁÇëÇó£¬Ôòµ÷ÓÃunsafe.read()·½·¨£¬Ð´ÇëÇóµ÷ÓÃunsafe.forceFlush()·½·¨£¬Á¬½ÓÇëÇóµ÷ÓÃunsafe.finishConnect()·½·¨¡£
JDK epoll bug
¹Ù·½Á¬½Ó
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6670302 |
¹Ù·½¸ø³öµÄ²âÊÔ´úÂëÈçÏ£º

ÖØµãÔÚwhile(true)Ñ»·Àï±ß£¬Ò²¾ÍÊÇ˵
int numKeys =
selector.select(); |
ÕâÐдúÂëÈç¹ûûÓÐÂÖѯµ½×¼±¸¾ÍÐ÷µÄChannel£¬±¾¸Ã×èÈû£¬µ«JDK epoll²¢Ã»ÓÐ×èÈû·µ»ØÒ»¸ö¿ÕµÄ¼¯ºÏ£¬µ¼ÖÂwhileÏÝÈëËÀÑ»·ÖС£ºÜ¶à·þÎñÆ÷Ó¦Ó㬱ÈÈçÉÏÎĵÄNetty£¬JettyµÈ¶ÔÆä×÷ÁËÐÞ¸´£¬rebuildSelector¡£
|