深入對比Tomcat與Netty:HTTP請求從網卡到Controller的全鏈路追蹤

我們日常用Spring Boot寫的RestController,感覺上就是一個簡單的方法,但它背后其實有一套復雜的網絡服務在支撐。一個HTTP請求到底是怎么從用戶的瀏覽器,穿過層層網絡,最終抵達我們代碼里的Controller方法的?理解這個過程,特別是Tomcat和Netty這兩種主流服務器的處理方式,對我們寫出更高性能的應用很有幫助。

Tomcat模型:一個請求,一個線程,簡單直接

我們先聊聊大家最熟悉的Spring MVC on Tomcat組合。

Tomcat的NIO模型,本質上是一種高度優化的“單Reactor多線程”實現。它的內部角色分工很明確:有一小隊Acceptor線程,專門負責在門口迎接新的TCP連接。連接一旦建立,Acceptor不會親自服務,而是把這個連接交給Poller線程。

Poller線程也只有少數幾個,它像個雷達,不斷掃描所有已連接的通道,看看哪個通道上送來了數據。一旦發現某個連接有數據可讀,Poller也不會自己去讀寫,而是把這個“可讀”的信號打包成一個任務,扔給一個龐大的Worker線程池。

接下來就是重頭戲了。Worker線程池里的一個工作線程會領走這個任務,并且負責到底。這個線程會先去網絡通道里把請求數據讀出來,這個讀取的過程是阻塞的。讀完后,它把字節流解析成我們熟悉的HttpServletRequest對象,然后請求就進入了Spring的處理流程,最終調用到我們的Controller方法。

這里最關鍵的一點是,我們寫的業務代碼,包括查詢數據庫、調用其他服務等所有操作,全都在這個Worker線程上同步執行。執行完了,再由這個線程把響應數據寫回給用戶。所以,這種模式的好處是編程模型非常簡單,寫代碼就像寫單機程序一樣,思路很直觀。但缺點也很明顯,系統的并發能力,直接受限于Worker線程池的大小。

Netty模型:事件驅動,少數線程支撐海量連接

再來看看Spring WebFlux on Netty這個組合,它的玩法就完全不一樣了。

Netty是標準的“主從Reactor多線程”架構。它也有一個專門負責接客的BossGroup,通常就一個線程,工作很專一,只管接收連接,然后把連接轉手扔給WorkerGroup

WorkerGroup里包含了一組EventLoop線程,數量通常和CPU核心數差不多。一個連接被分配給某個EventLoop之后,這個連接的整個生命周期就和這個線程綁定了。從數據讀取、解碼成HttpRequest對象,再到分發給WebFlux框架,所有事情都由這一個EventLoop線程親力親為。

當請求最終到達我們的Controller方法時,代碼依然是運行在這個EventLoop線程上的。這就帶來一個嚴格的約束:絕對不能有任何阻塞操作。因為一旦這個線程被阻塞,它負責的所有其他連接就全都動不了了。

所以,我們必須返回MonoFlux這類響應式類型,并通過異步方式去調用下游。EventLoop線程在發起數據庫查詢或者RPC調用后,會立即返回去處理其他連接上的事件,而不是原地等待。當下游服務返回結果時,會通過一個回調事件,重新喚醒這個EventLoop線程,讓它繼續完成后續的數據處理和響應。這種事件驅動的模式,使得極少數的線程就能管理海量的并發連接。

核心差異與如何選擇

為了更直觀地看出差別,我們看一個表格。

特性維度Spring MVC on TomcatSpring WebFlux on Netty
線程模型一個請求一個Worker線程少數I/O線程處理所有連接
編程范式同步、阻塞異步、非阻塞 (響應式)
資源占用線程多,內存開銷大線程少,內存開銷小
核心風險線程池耗盡阻塞I/O線程
適用場景通用CRUD、CPU密集型業務高并發、I/O密集型業務(如網關)

這兩種模型的性能差異,在處理I/O密集的場景時會被無限放大。比如,處理1000個并發請求,每個請求都要等待1秒的網絡I/O。在Tomcat里,如果Worker線程池大小是200,那200個線程會立刻被占滿并阻塞,剩下的800個請求只能排隊。而在Netty里,哪怕只有8個EventLoop線程,也能輕松應對,因為它們從不等待。

那么,我們到底該怎么選?

其實很簡單,看你的業務場景。如果你的應用是I/O密集型的,比如微服務網關、消息推送中臺,需要用有限的服務器資源應對海量的并發連接,那么Netty/WebFlux是更好的選擇,它能最大化系統吞吐能力。

反過來,如果你的應用是業務邏輯復雜、并發量可控的傳統CRUD系統,那Tomcat/MVC的同步模型會讓開發、調試和排查問題變得簡單直觀得多。在這種場景下,開發效率和可維護性的重要性,往往比壓榨那一點硬件性能更重要。

總的來說,Tomcat用線程池隔離了阻塞,讓編程更簡單;Netty用事件驅動壓榨硬件性能,讓并發更高。兩者沒有絕對的優劣,理解它們背后的設計思想,才能在合適的場景做出正確的選擇。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/98036.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/98036.shtml
英文地址,請注明出處:http://en.pswp.cn/web/98036.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

GO學習記錄十——發包

記錄下不同平臺的發包操作和期間遇到的問題 1.命令: $env:GOOSlinux $env:GOARCHamd64 go build -o release/HTTPServices-linux第一行,配置平臺,linux、windows 第二行,配置部署服務器的處理器架構 第三行,輸出目標文…

貪心算法與動態規劃

1. 什么是貪心算法? 貪心算法是一種在每一步選擇中都采取在當前狀態下最好或最優(即最有利)的選擇,從而希望導致結果是全局最好或最優的算法。 核心思想:“每步都貪心地選擇眼前最好的,不去考慮整個未來的長…

學會“讀網頁”:生成式 AI 在足球賽事信息整理中的實戰

逐步教程(Step-by-Step) — 適合初學者與教學類文章 背景(為什么要這樣做) 對于足球迷、資訊編輯與數據分析師來說,最快、最準確把握一場比賽的核心信息至關重要:比分、關鍵事件(進球、點球、紅…

BM3D 圖像降噪快速算法的 MATLAB 實現

BM3D 圖像降噪快速算法的 MATLAB 實現1. 快速 BM3D 算法流程(概述)步驟操作加速技巧① 分組塊匹配 堆疊FFT 互相關② 協同濾波3D 變換 硬閾值FFT 沿第三維③ 聚合加權平均稀疏矩陣累加 2. 核心函數(單文件版) 保存為 bm3d_fast.…

Go的schedt調度(runtime/proc.go)

1. 創建go的入口函數// Create a new g running fn. // Put it on the queue of gs waiting to run. // The compiler turns a go statement into a call to this. func newproc(fn *funcval) {gp : getg()pc : sys.GetCallerPC()systemstack(func() {newg : newproc1(fn, gp, …

Ubuntu 服務器配置轉發網絡訪問

配置文檔:Ubuntu 服務器轉發網絡訪問 一、網絡拓撲以以下網絡拓撲為示例Ubuntu 服務器(兩個網卡) eth1 10.66.71.222 (接入內網)eno1 192.168.2.100 (直連相機) 相機ip 192.168.2.1 Windows 客…

為什么企業需要高防IP

1. 抵御日益猖獗的DDoS攻擊 現代DDoS攻擊規模已突破Tbps級別 傳統防火墻無法應對大規模流量攻擊 高防IP采用分布式清洗中心,可輕松抵御300Gbps以上的攻擊流量 2. 保障業務連續性 網絡中斷1小時可能造成數百萬損失 高防IP確保服務99.99%可用性 智能切換機制實…

CSS基礎 - 選擇器備忘錄 --筆記5

目錄基礎選擇器組合器偽類選擇器屬性選擇器選擇器可以選中頁面上的特定元素并為其指定樣式。 CSS有多種選擇器。 基礎選擇器 標簽選擇器 – tagname:匹配目標元素的標簽名。優先級是0,0,1。如:p、h1、div類選擇器 – .class:匹配class屬性中…

自動駕駛中的傳感器技術46——Radar(7)

衛星雷達(又稱為分布式雷達)主要講當前雷達的雷達信號處理計算以及雷達目標相關的一些感知算法都遷移到中央域控進行,雷達端基本只負責數據采集,這樣做的影響如下: 雷達端成本與功耗降低; 雷達端采樣得到的…

【論文閱讀】Diff-Privacy: Diffusion-based Face Privacy Protection

基于擴散模型的人臉隱私保護方法——DiffPrivacy,解決了兩類人臉隱私任務:匿名化(anonymization)和視覺身份信息隱藏(visual identity information hiding)。1. 研究背景隨著人工智能和大數據技術的普及&am…

React 原理篇 - 深入理解虛擬 DOM

一、什么是虛擬 DOM? 在前端開發中,“虛擬 DOM” 是一個高頻出現的術語,尤其在 React 生態中被廣泛討論。但很多開發者對它的理解往往停留在 “JS 對象” 這個表層認知上。 實際上,虛擬 DOM 是一種編程概念—— 在這個概念里&…

對匯編的初理解

此處是一個簡單的函數,里面將調用了一個函數add()函數這里是函數的原型這里是調用lcd函數產生的匯編語言,翻譯過來就是r11,r0cnt(r4cnt,前文有提及),然后調用add函數,此處BL是指會回到指令的下一…

《Python 自動化實戰:從零構建一個文件同步工具》

《Python 自動化實戰:從零構建一個文件同步工具》 一、開篇引入:為什么我們需要文件同步? 你是否有過這樣的困擾: 公司電腦和家里電腦上都有工作項目,每次更新都要手動復制? U 盤頻繁傳輸文件,不僅麻煩還容易出錯? 項目文件夾動輒幾 G,每次同步都耗時長、效率低? 在…

工業相機與鏡頭的靶面尺寸詳解:選型避坑指南

在機器視覺系統中,相機與鏡頭的靶面尺寸匹配是一個非常關鍵卻又經常被忽略的細節。選錯了,不但影響圖像質量,還可能導致畫面“黑角”、視野不符、鏡頭浪費等問題。 今天我們就用通俗易懂的方式,聊一聊相機與鏡頭靶面尺寸的那些事兒…

使用 Go 和 go-commons 實現內存指標采集并對接 Prometheus

文章目錄一、準備工作二、編寫內存采集代碼三、運行 Exporter四、接入 Prometheus五、可擴展思路總結在運維和監控領域,資源指標采集 是必不可少的一環。CPU、內存、磁盤、網絡這些系統資源,需要實時采集并上報到監控系統中。 本文以 內存指標采集 為例&…

webrtc弱網-IntervalBudget類源碼分析與算法原理

一、核心功能 IntervalBudget 類用于基于時間窗口的帶寬預算管理。它根據設定的目標比特率(kbps)和一個固定時間窗口(500ms),計算在該時間窗口內可用的字節數(即“預算”),并支持預…

深度學習基本模塊:RNN 循環神經網絡

循環神經網絡(RNN)是一種專門用于處理序列數據的神經網絡架構。與處理空間數據的卷積神經網絡(Conv2D)不同,RNN通過引入循環連接使網絡具有"記憶"能力,能夠利用之前的信息來影響當前的輸出&#…

React18學習筆記(二) React的狀態管理工具--Redux,案例--移動端外賣平臺

文章目錄一.Redux的基礎用法1.示例:普通網頁中的Redux計步器2.Redux管理數據的流程3.配套工具和環境準備3.1.配套工具3.2.環境準備4.示例:React項目中的Redux計步器思路步驟step1:創建子模塊step2:導入子模塊step3:注入store實例step4:React組件內使用store中的數據step5:在組件…

34.Socket編程(UDP)(上)

點分十進制字符串IP 轉 32位網絡序列IP 分析:1)IP轉成4字節 2)4字節轉成網絡序列 思路: "192.168.1.1" 進行字符串劃分,以 "." 為分割符,分割出"192",&qu…

Redis的持久化工具包—RDB AOF

文章目錄 前言 一、RDB 持久化(快照持久化) 1. 定義 2. RDB 觸發機制 (1)手動觸發 (2)自動觸發 3. RDB 持久化流程 4. RDB 核心配置 5. RDB 優缺點 二、AOF 持久化(日志持久化) 1. 定…