通常毁欣,我們寫服務(wù)器處理模型的程序時(shí)候庇谆,有以下幾種模型:
每收到一個(gè)請(qǐng)求岳掐,創(chuàng)建一個(gè)新的進(jìn)程,來處理該請(qǐng)求饭耳;
每收到一個(gè)請(qǐng)求串述,創(chuàng)建一個(gè)新的線程,來處理該請(qǐng)求寞肖;
每收到一個(gè)請(qǐng)求纲酗,放入一個(gè)事件列表,讓主進(jìn)程通過非阻塞I/O方式來處理請(qǐng)求(也就是啟動(dòng)協(xié)程) 也就是
事件驅(qū)動(dòng)模型
上面的幾種方式新蟆,各有千秋觅赊,
第一種方法,由于創(chuàng)建新的進(jìn)程的開銷比較大琼稻,所以吮螺,會(huì)導(dǎo)致服務(wù)器性能比較差,但實(shí)現(xiàn)比較簡單。第二種方式帕翻,由于要涉及到線程的同步鸠补,有可能會(huì)面臨死鎖等問題。第三種方式嘀掸,在寫應(yīng)用程序代碼時(shí)紫岩,邏輯比前面兩種都復(fù)雜。
綜合考慮各方面因素横殴,一般普遍認(rèn)為第三種方式是大多數(shù)網(wǎng)絡(luò)服務(wù)器采用的方式被因。
- 實(shí)例一:什么是事件驅(qū)動(dòng)模型?
在ui編程中衫仑,經(jīng)常要對(duì)鼠標(biāo)進(jìn)行點(diǎn)擊梨与,首先如何獲取說表點(diǎn)擊呢?
方式一:創(chuàng)建一個(gè)線程文狱,該線程一直循環(huán)檢測是否有鼠標(biāo)點(diǎn)擊粥鞋,那么這個(gè)方式有以下缺點(diǎn):
造成cpu資源的浪費(fèi),如果鼠標(biāo)點(diǎn)擊的頻率非常小瞄崇,但是掃面線程還是會(huì)一直循環(huán)檢測呻粹,這會(huì)造成很多cpu資源的浪費(fèi);如果掃描鼠標(biāo)點(diǎn)擊的接口是阻塞的呢苏研?(就是點(diǎn)擊鼠標(biāo)等浊,此時(shí)要運(yùn)行一個(gè)任務(wù)需要時(shí)間),如果我們不但要掃描鼠標(biāo)還要掃描鍵盤摹蘑,由于掃描鼠標(biāo)阻塞筹燕,那么可能永遠(yuǎn)不會(huì)去掃描鍵盤,而如果要掃描的設(shè)備非常多,這就會(huì)帶來響應(yīng)時(shí)間的問題撒踪。
所以过咬,該方式是非常不好的!V仆掸绞!
方式二:事件驅(qū)動(dòng)模型
目前大部分ui都是事件驅(qū)動(dòng)模型,如很多UI平臺(tái)都會(huì)提供onclick()事件耕捞。事件驅(qū)動(dòng)模型大體思路如下:
1衔掸、有一個(gè)事件(消息)隊(duì)列
2、鼠標(biāo)按下時(shí)俺抽,往這個(gè)隊(duì)列中增加一個(gè)點(diǎn)擊事件(消息)
3具篇、有一個(gè)循環(huán),不斷的從隊(duì)列中取出事件凌埂,調(diào)用不同的函數(shù),如onclick()等
4诗芜、事件(消息)一般都各自保存在各自的處理函數(shù)指針瞳抓,這樣每個(gè)消息都有自己獨(dú)立的處理函數(shù)
事件驅(qū)動(dòng)編程是一種編程范式,這里程序的執(zhí)行流由外部事件來決定伏恐。它的特點(diǎn)是包含一個(gè)事件循環(huán)孩哑,當(dāng)外部事件發(fā)生時(shí)使用回調(diào)機(jī)制來觸發(fā)相應(yīng)的處理。另外兩種常見的編程范式是(單線程)同步以及多線程編程翠桦。(回調(diào)機(jī)制:可以參考上篇最后一個(gè)實(shí)例)
注意横蜒,io操作是操作系統(tǒng)進(jìn)行的,不需要程序销凑,那么事件驅(qū)動(dòng)模型丛晌,每次遇到io事件就把該事件放在操作系統(tǒng)中的一個(gè)隊(duì)列中,然后等待操作系統(tǒng)返回斗幼,而這個(gè)返回就是回調(diào)機(jī)制的使用澎蛛,返回io執(zhí)行結(jié)果。定義好事件蜕窿,并且注冊(cè)一個(gè)回調(diào)函數(shù)谋逻,然后放入操作系統(tǒng)的隊(duì)列
下圖展示了隨著時(shí)間的推移,這三種模式下程序所做的工作桐经。這個(gè)程序有3個(gè)任務(wù)需要完成毁兆,每個(gè)任務(wù)都在等待I/O操作時(shí)阻塞自身。阻塞在I/O操作上所花費(fèi)的時(shí)間已經(jīng)用灰色框標(biāo)示出來了阴挣。
- 實(shí)例二:IO多路復(fù)用
協(xié)程實(shí)現(xiàn)了io自動(dòng)阻塞切換气堕,那么協(xié)程在原理上是怎么實(shí)現(xiàn)的?也就是我們?nèi)绾螌?shí)現(xiàn)在io阻塞時(shí)的自動(dòng)切換?
1送巡、同步IO和異步IO摹菠,阻塞IO和非阻塞IO分別是什么,到底有什么區(qū)別骗爆?(討論的背景是Linux環(huán)境下的network IO)
http://www.cnblogs.com/alex3714/articles/5876749.html
緩存(標(biāo)準(zhǔn)I/O)I/O是什么次氨?
又稱標(biāo)準(zhǔn)I/O,比如socket-server摘投,我們從網(wǎng)卡接收數(shù)據(jù)煮寡,數(shù)據(jù)會(huì)先到達(dá)操作系統(tǒng)內(nèi)核的緩沖區(qū)中,再被拷貝到應(yīng)用程序的地址空間犀呼。
緩存I/O的缺點(diǎn):
數(shù)據(jù)在傳輸?shù)倪^程中需要在應(yīng)用程序的地址空間和內(nèi)核進(jìn)行多次數(shù)據(jù)拷貝操作幸撕,這些數(shù)據(jù)拷貝的操作帶來的cpu,內(nèi)存的(尤其是內(nèi)存)的開銷是特別大的外臂。
I/O模式
1坐儿、阻塞I/O(blocking I/O)
linux中所有的socket默認(rèn)是阻塞I/O。
這是典型的socket宋光,阻塞I/O貌矿。
特點(diǎn):io執(zhí)行的等待數(shù)據(jù)階段和拷貝數(shù)據(jù)階段都被阻塞了。
2罪佳、非阻塞I/O non - blocking
linux下逛漫,可以通過設(shè)置socket使其成為non-blocking I/O.
特點(diǎn):進(jìn)程執(zhí)行recv操作沒數(shù)據(jù)立刻返回error,進(jìn)程不需要等待赘艳。馬上進(jìn)程再次執(zhí)行recv動(dòng)作酌毡,就不斷的詢問內(nèi)核,知道有數(shù)據(jù)蕾管。nonblocking IO的特點(diǎn)是用戶進(jìn)程需要不斷的主動(dòng)詢問kernel數(shù)據(jù)好了沒有枷踏。
注意:只是非阻塞
3、I/O多路復(fù)用 (I/O multiplexing model) (事件驅(qū)動(dòng) I/O)
IO multiplexing就是我們說的select掰曾,poll呕寝,epoll,有些地方也稱這種IO方式為event driven IO婴梧。select/epoll的好處就在于單個(gè)process就可以同時(shí)處理多個(gè)網(wǎng)絡(luò)連接的IO下梢。它的基本原理就是select,poll塞蹭,epoll這個(gè)function會(huì)不斷的輪詢所負(fù)責(zé)的所有socket孽江,當(dāng)某個(gè)socket有數(shù)據(jù)到達(dá)了,就通知用戶進(jìn)程番电。
阻塞I/O 不能實(shí)現(xiàn)socket的并發(fā)岗屏,但是非阻塞模型在用戶看來已經(jīng)實(shí)現(xiàn)了socket的并發(fā)辆琅,因?yàn)橛脩暨M(jìn)程不需要等待,但是拷貝數(shù)據(jù)還是處于阻塞狀態(tài)这刷。
select poll epoll就是實(shí)現(xiàn)了這個(gè)socket并發(fā)婉烟。不斷循環(huán)socket鏈接。
I/O 多路復(fù)用的特點(diǎn)是通過一種機(jī)制一個(gè)進(jìn)程能同時(shí)等待多個(gè)文件描述符暇屋,而這些文件描述符(套接字描述符)其中的任意一個(gè)進(jìn)入讀就緒狀態(tài)似袁,select()函數(shù)就可以返回。
這種方式和第一種方式的區(qū)別就是:阻塞I/O只是一個(gè)socket鏈接咐刨,而多路復(fù)用 I/O檢測很多鏈接昙衅,有一個(gè)受到數(shù)據(jù)就返回,但是進(jìn)程都會(huì)阻塞定鸟。
4而涉、異步I/O
用戶進(jìn)程發(fā)起read操作之后,立刻就可以開始去做其它的事联予。而另一方面啼县,從kernel的角度,當(dāng)它受到一個(gè)asynchronous read之后沸久,首先它會(huì)立刻返回谭羔,所以不會(huì)對(duì)用戶進(jìn)程產(chǎn)生任何block。然后麦向,kernel會(huì)等待數(shù)據(jù)準(zhǔn)備完成,然后將數(shù)據(jù)拷貝到用戶內(nèi)存客叉,當(dāng)這一切都完成之后诵竭,kernel會(huì)給用戶進(jìn)程發(fā)送一個(gè)signal,告訴它read操作完成了兼搏。
特點(diǎn)是:完全不需要用戶進(jìn)程等待
- 實(shí)例三:多路復(fù)用中的select卵慰、poll、epoll
http://www.cnblogs.com/alex3714/p/4372426.html
epoll 佛呻,linux2.6以后才支持裳朋。windows不支持epoll,windows只支持select吓著。
現(xiàn)在最流行的鲤嫡,nginx在用,包括djang等绑莺,python下最牛逼的異步網(wǎng)絡(luò)框架暖眼。