1 socket IO事件
1.1 讀事件
讀事件:句柄從不可讀變成可讀邓嘹,或者句柄寫緩沖區(qū)有新的數據進來且超過SO_RCVLOWAT。
常見的產生讀事件有如下幾種:
- socket有一個未清除的錯誤惰说。如非阻塞的connect連接錯誤會使socket變成可讀寫狀態(tài)。
- 非阻塞accept有新的連接進來奴烙。
- socket寫對端關閉助被,read返回0剖张。
- socket讀緩沖區(qū)有新的數據進來且超過SO_RCVLOWAT
1.2 寫事件
寫事件:句柄從不可寫變成可寫,或者句柄寫緩沖區(qū)有新的數據進來而且緩沖區(qū)水位高于SO_SNDLOWAT揩环。常見的寫事件事件有如下幾種:
- socket有一個未清除的錯誤搔弄。例如非阻塞connect連接出錯會導致socket變成可讀可寫狀態(tài)。
- 非阻塞connect連接成功后端口狀態(tài)會變成可寫丰滑。
- socket讀對端關閉顾犹,socket變成可寫狀態(tài),產生SIGPIPE信號褒墨。
- socket寫緩沖區(qū)有新的數據進來且超過SO_SNDLOWAT
在epoll中炫刷,讀事件對應EPOLLIN,寫事件對應EPOLLOUT郁妈。
2 ET
句柄在發(fā)生讀寫事件時只會通知用戶一次
ET模式主要關注fd從不可用到可用或者可用到不可用的情況浑玛。
ET只支持非阻塞模式。
2.1 應用層邏輯
ET模式下讀寫操作要時用wihle循環(huán)噩咪,直到讀/寫夠足夠多的數據顾彰,或者讀/寫到返回EAGAIN。尤其時在寫大塊數據時胃碾,一次write操作不足以寫完全部數據涨享,或者在讀大塊數據時,應用層緩沖區(qū)數據太小仆百,一次read操作不足以讀完全部數據厕隧,應用層要么一直調用while循環(huán)一直IO到EGAIN,或者自己調用epoll_ctl手動觸發(fā)ET響應。
2.2 優(yōu)缺點
缺點:應用層業(yè)務邏輯復雜俄周,容易遺漏事件吁讨,很難用好。
優(yōu)點:相對LT模式效率比較高峦朗。
3 LT
只要句柄一直處于可用狀態(tài)挡爵,就會一直通知用戶。
LT模式下甚垦,句柄讀緩沖區(qū)被讀空后,句柄會從可用轉變未不可以用涣雕,這個時候不會通知用戶艰亮。寫緩沖區(qū)只要還沒寫滿,就會一直通知用戶挣郭。
LT模式支持阻塞和非阻塞兩種方式迄埃。epoll默認的模式是LT。
LT下兑障,應用層的業(yè)務邏輯比較簡單侄非,更不容易遺漏事件蕉汪,更不容易出錯。通常逞怨,在將數據寫完后者疤,我們會關閉句柄的寫事件。
3.1 優(yōu)缺點
優(yōu)點:編程更符合用戶直覺叠赦,業(yè)務層邏輯更簡單驹马。
缺點:效率比ET低。
3.2 ET比LT更高效得原因
ET在通知用戶后除秀,就會把fd從就緒隊列里刪除糯累。而LT通知用戶后fd還在就緒鏈表中,隨著fd的增多册踩,就緒鏈表越大泳姐。下次epoll要通知用戶時還需要遍歷整個就緒鏈表。遍歷的性能是線性暂吉,如果fd的數量非常多胖秒,就會帶來比較顯著的效率下降。
同樣數量的fd下借笙,LT模式維護的就緒鏈表比ET的大扒怖。
3.3 非阻塞模式下的accept該用什么觸發(fā)模式?
LT和ET各有優(yōu)缺點业稼。使用哪種模式取決于并發(fā)量盗痒。當并發(fā)量比較小時,比較推薦LT低散,因為LT模式下應用的讀寫邏輯比較簡單俯邓,不容易遺漏事件,代碼不易出錯好維護熔号,而且性能損失不大稽鞭。當并發(fā)量非常大時,推薦使用ET模式引镊,可以有效提升EPOLL效率朦蕴。
3.4 LT模式下,可寫狀態(tài)的fd會一直觸發(fā)事件弟头,該怎么處理這個問題
- 方法1:每次要寫數據時吩抓,將fd綁定EPOLLOUT事件,寫完后將fd同EPOLLOUT從epoll中移除赴恨。
- 方法2:方法一中每次寫數據都要操作epoll疹娶。如果數據量很少,socket很容易將數據發(fā)送出去伦连∮杲龋可以考慮改成:數據量很少時直接send钳垮,數據量很多時在采用方法1.
應用
使用ET的例子
nginx
使用LT的例子
redis