2 回答

TA貢獻(xiàn)1784條經(jīng)驗(yàn) 獲得超8個(gè)贊
目前有 2 個(gè)基本概念來處理對(duì)具有各種優(yōu)點(diǎn)和缺點(diǎn)的 Web 服務(wù)器的并行訪問:
阻塞
非阻塞
阻止網(wǎng)絡(luò)服務(wù)器
阻塞、多線程的第一個(gè)概念服務(wù)器在池中有有限數(shù)量的線程。每個(gè)請(qǐng)求都將分配給特定的線程,并且該線程將被分配直到請(qǐng)求被完全服務(wù)。這與超市結(jié)賬隊(duì)列的工作方式基本相同,一次一個(gè)顧客,可能有平行線。在大多數(shù)情況下,Web 服務(wù)器中的請(qǐng)求在處理請(qǐng)求的大部分時(shí)間里都是 cpu 空閑的。這是因?yàn)樗仨毜却?I/O:讀取套接字、寫入數(shù)據(jù)庫(kù)(基本上也是 IO)并讀取結(jié)果并寫入套接字。此外,使用/創(chuàng)建一堆線程很慢(上下文切換)并且需要大量?jī)?nèi)存。因此,這個(gè)概念通常不會(huì)非常有效地使用它擁有的硬件資源,并且對(duì)可以并行服務(wù)的客戶端數(shù)量有硬性限制。slow loris,一種通常單個(gè)客戶端可以毫不費(fèi)力地 DOS 大型多線程 Web 服務(wù)器的攻擊。
概括
(+) 更簡(jiǎn)單的代碼
(-) 并行客戶端的硬限制
(-) 需要更多內(nèi)存
(-) 通常的網(wǎng)絡(luò)服務(wù)器工作硬件使用效率低下
(-) 易于 DOS
大多數(shù)“傳統(tǒng)”網(wǎng)絡(luò)服務(wù)器都是這樣工作的,例如舊的 tomcat、Apache 網(wǎng)絡(luò)服務(wù)器以及所有Servlet
早于 3 或 3.1 的東西等等。
非阻塞網(wǎng)絡(luò)服務(wù)器
相比之下,非阻塞網(wǎng)絡(luò)服務(wù)器可以只用一個(gè)線程為多個(gè)客戶端提供服務(wù)。那是因?yàn)樗褂昧?em>非阻塞內(nèi)核 I/O 特性。這些只是內(nèi)核調(diào)用,當(dāng)可以寫入或讀取某些內(nèi)容時(shí)會(huì)立即返回并回調(diào),從而使 cpu 可以自由地做其他工作。重用我們的超市比喻,這就像,當(dāng)收銀員需要他的主管解決問題時(shí),他不會(huì)等待并阻塞整個(gè)通道,而是開始結(jié)賬下一位顧客,直到主管到達(dá)并解決第一位顧客的問題顧客。
這通常在事件循環(huán)或更高的抽象中完成,如green-threads或fibers。本質(zhì)上這樣的服務(wù)器不能真正并發(fā)處理任何事情(當(dāng)然你可以有多個(gè)非阻塞線程),但它們能夠并行服務(wù)數(shù)千個(gè)客戶端,因?yàn)閮?nèi)存消耗不會(huì)像多線程那樣急劇擴(kuò)展概念(閱讀:最大并行客戶端沒有硬性限制)。也沒有線程上下文切換。缺點(diǎn)是,非阻塞代碼通常更難以讀寫(例如callback-hell),并且在請(qǐng)求執(zhí)行大量 cpu 昂貴工作的情況下效果不佳。
概括
(-) 更復(fù)雜的代碼
(-) cpu 密集型任務(wù)的性能更差
(+) 作為 Web 服務(wù)器更有效地使用資源
(+) 更多沒有硬限制的并行客戶端(最大內(nèi)存除外)
大多數(shù)現(xiàn)代“快速”網(wǎng)絡(luò)服務(wù)器和框架促進(jìn)了非阻塞概念:Netty、Vert.x、Webflux、nginx、servlet 3.1+、Node、Go 網(wǎng)絡(luò)服務(wù)器。
作為旁注,查看此基準(zhǔn)頁(yè)面,您會(huì)發(fā)現(xiàn)大多數(shù)最快的 Web 服務(wù)器通常都是非阻塞服務(wù)器: https: //www.techempower.com/benchmarks/

TA貢獻(xiàn)1884條經(jīng)驗(yàn) 獲得超4個(gè)贊
使用 Servlet 2.5 時(shí),Servlet 容器會(huì)將請(qǐng)求分配給線程,直到該請(qǐng)求已被完全處理。
使用 Servlet 3.0 異步處理時(shí),服務(wù)器可以在應(yīng)用程序處理請(qǐng)求時(shí)在單獨(dú)的線程池中分派請(qǐng)求處理。然而,當(dāng)涉及到 I/O 時(shí),工作總是發(fā)生在服務(wù)器線程上,并且它總是阻塞的。這意味著“慢客戶端”可以獨(dú)占服務(wù)器線程,因?yàn)榉?wù)器在讀取/寫入網(wǎng)絡(luò)連接較差的客戶端時(shí)被阻塞。
使用 Servlet 3.1,允許異步 I/O,在這種情況下,“一個(gè)請(qǐng)求/線程”模型不再存在。在任何時(shí)候,位請(qǐng)求處理都可以安排在服務(wù)器管理的不同線程上。
Servlet 3.1+ 容器通過 Servlet API 提供了所有這些可能性。利用異步處理或非阻塞 I/O 取決于應(yīng)用程序。在非阻塞 I/O 的情況下,范式的改變很重要,而且使用起來真的很有挑戰(zhàn)性。
使用 Spring WebFlux - Tomcat、Jetty 和 Netty 沒有完全相同的運(yùn)行時(shí)模型,但它們都支持反應(yīng)式背壓和非阻塞 I/O。
添加回答
舉報(bào)