綜述
react vi.反應(yīng),影響; reactor n.反應(yīng)器;reactor是網(wǎng)絡(luò)編程中的一種設(shè)計模式。使用reactor模式可以實現(xiàn)高性能的IO镐作,Netty和Redis的IO模式就是實現(xiàn)了reactor模式來實現(xiàn)高性能并發(fā)的藏姐。同時reactor模式也是23種設(shè)計模式的一種。
網(wǎng)絡(luò)編程模型經(jīng)歷了從單線程->多線程->線程池->reactor模式该贾,單線程到多線程是要依賴于底層多個CPU的硬件技術(shù)發(fā)展的支持羔杨,線程池則減少了多線程中的線程不斷的創(chuàng)建和銷毀所消耗的資源,reactor模式則是把處理socket的粒度做了細分靶庙,來解決高性能的并發(fā)請求问畅。
// 單線程模式娃属,無法并發(fā),如果當前的請求沒有處理完护姆,那么后面的請求只能被阻塞矾端,服務(wù)器的吞吐量太低。
while(true){
socket = accept();
handle(socket);
}
// 多線程模式卵皂,connection per thread秩铆,每一個連接用一個線程處理。
while(true){
socket = accept();
new Thread(socket);
}
// 線程池模式灯变,減少了線程的反復(fù)創(chuàng)建和銷毀殴玛,但本質(zhì)上一個線程還是要完整的處理連接、讀取添祸、寫入
while(true){
socket = accept();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Thread(socket));
}
// reactor模式(基于IO多路復(fù)用的技術(shù))
1. java nio的select函數(shù)滚粟,可以同時監(jiān)聽多個套接字socket。每個socket都會關(guān)聯(lián)連接event刃泌、讀取event凡壤、回寫event。
2. 把一個線程拆分成更小的粒度:建立連接的handler耙替、讀取數(shù)據(jù)的handler亚侠、回寫數(shù)據(jù)的hander。handler處理完event就丟給下一個handler處理俗扇,自己又可以去服務(wù)socket硝烂,提高了復(fù)用率,提高了系統(tǒng)的吞吐量铜幽。
基本上所有的網(wǎng)絡(luò)處理程序都有以下基本的處理過程: Read request->Decode request->Process service->Encode reply->Send reply滞谢。
在單核機器上,多線程并不一定能提高系統(tǒng)性能啥酱,除非有一些阻塞情況發(fā)生爹凹,否則線程上下文切換的開銷會使處理速度變慢。舉個生動的例子镶殷,一個人削蘋果和切西瓜(一件一件的做)禾酱。一個人削蘋果和燒一壺開水(一邊燒水一邊把蘋果削了);
餐廳點餐來理解reactor模式
上面這個圖绘趋,是多線程方式颤陶。每個顧客都有自己的服務(wù)團隊(線程),在人少的情況下是可以良好的運作的陷遮∽易撸可以發(fā)現(xiàn)其實服務(wù)員并不是一直在干活的,大部分時間他們只是站在餐桌旁邊等客人點菜帽馋。于是老板就對服務(wù)員說搅方,客人點菜的時候你們就別傻站著了比吭,先去服務(wù)其它客人,有客人點好的時候喊你們再過去姨涡。
老板發(fā)現(xiàn)根本不需要那么多的服務(wù)員衩藤,于是裁了一波員,最終甚至可以只有一個服務(wù)員涛漂。這就是 Reactor 模式的核心思想:減少等待赏表。當遇到需要等待 IO 時,先釋放資源匈仗,而在 IO 完成時瓢剿,再通過事件驅(qū)動 (event driven) 的方式,繼續(xù)接下來的處理悠轩。從整體上減少了資源的消耗间狂。
三種reactor線程模型
無論是C++還是Java編寫的網(wǎng)絡(luò)框架,大多數(shù)都是基于Reactor模式進行設(shè)計和開發(fā)火架,Reactor模式基于事件驅(qū)動前标,特別適合處理海量的I/O事件。Reactor三種線程模型:單線程模型距潘、多線程模型、主從線程模型只搁。