舉例詳解Tomcat與Nginx、Apache的區(qū)別是什么
這個問題本身有個誤解:把三個東西都叫「web server」,會讓人以為它們是同一種東西的三種實現(xiàn)。其實不是。Nginx 和 Apache 是 HTTP 服務(wù)器,Tomcat 是 Servlet 容器,它們干的活不在一個層次上。
Nginx 和 Apache(一般說的 Apache 指的是 Apache HTTP Server,也就是 httpd)是 HTTP 服務(wù)器:收 HTTP 請求、按配置干活、回 HTTP 響應(yīng)。它們擅長扛靜態(tài)文件、做反向代理、做負載均衡,但它們不執(zhí)行 Java 代碼。你打一個 .war 包丟給 Nginx,Nginx 不知道怎么處理——它只會返回 404 或者把請求轉(zhuǎn)給別人。
Tomcat 是 Servlet 容器,不是完整的 Java EE 應(yīng)用服務(wù)器(那是 WildFly、WebLogic、WebSphere 干的事,它們支持 EJB、JMS、JTA 等完整規(guī)范)。Tomcat 只實現(xiàn) Servlet 和 JSP 規(guī)范,核心能力是:把 HTTP 請求交給你的 Java 代碼去處理,再把結(jié)果變成 HTTP 響應(yīng)發(fā)回去。
所以「Java 后臺程序能不能用 Apache 和 Nginx」——能,而且生產(chǎn)環(huán)境里經(jīng)常是「Nginx/Apache 在前,Tomcat 在后」:前面負責(zé)扛流量、靜態(tài)資源、HTTPS 終結(jié)、負載均衡,后面專門跑 Java。
Nginx 和 Apache:都是 HTTP 服務(wù)器,架構(gòu)不一樣
兩者都能做靜態(tài)文件服務(wù)、反向代理、負載均衡,但內(nèi)部設(shè)計完全不同。
Apache 有三種工作模式(MPM):prefork 是一個連接一個進程,worker 是多進程+多線程,event 是在 worker 基礎(chǔ)上優(yōu)化了 keep-alive 連接的處理?,F(xiàn)代 Apache(2.4+)默認用 event MPM,處理 keep-alive 的方式已經(jīng)接近事件驅(qū)動了,不完全是老式的「一個連接占一個線程」。但不管哪種模式,Apache 的并發(fā)上限都受限于進程/線程數(shù)——每個線程有自己的??臻g(Linux 默認 8MB),1000 個線程光棧就要 8GB 內(nèi)存,還沒算堆上的數(shù)據(jù)。所以 Apache 的并發(fā)連接數(shù)一般在幾百到幾千這個量級。
Nginx 是另一種思路:少量 worker 進程 + 事件循環(huán)。每個 worker 用 epoll(Linux)/ kqueue(macOS)做 I/O 多路復(fù)用,一個 worker 可以同時掛著幾萬條連接。大部分連接在等 I/O,不需要單獨的線程,也就不需要那 8MB 的棧空間。所以同樣一臺機器,Nginx 能撐的并發(fā)連接數(shù)比 Apache 高一個數(shù)量級。
這也是很多人說「Nginx 比 Apache 性能好」的原因——不是 Nginx 處理單個請求更快,而是它用更少的資源就能維持大量連接。 如果你的場景是幾十個并發(fā)、主要跑 PHP,Apache + mod_php 用著挺好,沒必要換。但如果要扛幾萬并發(fā)、做反向代理或者負載均衡,Nginx 的模型更合適。
Tomcat:能直接對外,但不擅長
這里要糾正一個常見的說法:「Tomcat 必須放在 Nginx 后面」。
Tomcat 自帶 HTTP 連接器(Coyote),可以直接監(jiān)聽 80 或 443 端口對外服務(wù)。開發(fā)的時候大家天天直接訪問 localhost:8080,沒什么問題。Spring Boot 更進一步——內(nèi)嵌 Tomcat 打成一個 jar 包,java -jar 直接跑,連單獨部署 Tomcat 都省了。
很多微服務(wù)架構(gòu)里,每個服務(wù)就是一個內(nèi)嵌 Tomcat 的 Spring Boot 應(yīng)用,前面掛一個 API 網(wǎng)關(guān)(Spring Cloud Gateway、Kong 之類的)做路由和鑒權(quán),根本沒有單獨部署 Nginx 的環(huán)節(jié)。
但 Tomcat 直接對外有幾個短板:
靜態(tài)文件性能。 Nginx 處理靜態(tài)文件用的是 sendfile 系統(tǒng)調(diào)用(之前零拷貝那篇講過),數(shù)據(jù)不經(jīng)過用戶空間,直接從磁盤到網(wǎng)卡。Tomcat 處理靜態(tài)文件要經(jīng)過 Java 的 IO 層,多了一次拷貝和 JVM 的開銷。量小的時候感知不到,量大了差距就出來了。
SSL 終結(jié)。 Nginx 的 SSL 實現(xiàn)基于 OpenSSL,經(jīng)過大量優(yōu)化,支持 session 復(fù)用、OCSP stapling 這些。Tomcat 也能做 SSL,但性能和配置靈活性都不如 Nginx。把 SSL 卸載到 Nginx,Tomcat 和 Nginx 之間走 HTTP 明文,Tomcat 的負擔(dān)更輕。
限流、緩存、負載均衡。 這些 Nginx 用幾行配置就能搞定,Tomcat 要么不支持,要么需要寫 Java 代碼或者引入額外組件。
所以典型的生產(chǎn)部署是這樣的:
upstream tomcat_backend {
server 127.0.0.1:8080;
server 127.0.0.1:8081; # 多實例負載均衡
}
server {
listen 443 ssl;
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/key.pem;
location /static/ {
alias /var/www/static/;
}
location / {
proxy_pass http://tomcat_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Nginx 扛 SSL、吐靜態(tài)文件、做負載均衡,動態(tài)請求轉(zhuǎn)給后面的 Tomcat。但這不是唯一的架構(gòu)——小項目、內(nèi)部系統(tǒng)、微服務(wù)里 Tomcat 直接對外也很常見,取決于你的流量規(guī)模和運維需求。
為啥早年都是 Apache + Tomcat
早期 Nginx 還沒普及的時候,Apache 是 Linux 上默認的 HTTP 服務(wù)器。Java 項目的標準搭配是 Apache + mod_jk(或 mod_proxy)+ Tomcat:Apache 在前面接請求,通過 AJP 協(xié)議或 HTTP 代理轉(zhuǎn)給 Tomcat。
mod_jk 用的是 AJP 協(xié)議(Apache JServ Protocol),比 HTTP 更緊湊,省了 HTTP 頭的解析開銷。但 AJP 協(xié)議在 2020 年爆出過 Ghostcat 漏洞(CVE-2020-1938),之后很多團隊開始關(guān)閉 AJP 端口,改用 HTTP 代理。
現(xiàn)在新項目基本都用 Nginx 替代 Apache 當入口了。Apache 在需要 .htaccess(目錄級配置覆蓋)或者跑 mod_php 的場景還有優(yōu)勢,但純做反向代理和負載均衡,Nginx 的資源占用和并發(fā)能力都更好。
怎么判斷你的項目該用哪種組合
Spring Boot 微服務(wù)、內(nèi)部系統(tǒng)、流量不大: 內(nèi)嵌 Tomcat 直接對外,前面掛個網(wǎng)關(guān)或者云廠商的負載均衡器就行,不需要單獨部署 Nginx。
對外的 Web 應(yīng)用、有靜態(tài)資源、需要 HTTPS: Nginx 在前做 SSL 終結(jié)和靜態(tài)資源,動態(tài)請求 proxy_pass 到 Tomcat。
PHP + Java 混合部署(老項目): Apache 跑 mod_php 處理 PHP,同時 mod_proxy 把 Java 請求轉(zhuǎn)給 Tomcat。不過這種架構(gòu)越來越少了。
純靜態(tài)站點、CDN 回源、API 網(wǎng)關(guān): 只需要 Nginx,不需要 Tomcat。
Nginx 和 Tomcat 不是競爭關(guān)系,Apache 和 Nginx 才是。而即便是 Apache 和 Nginx,在大部分場景下也不是「誰好誰差」的問題——Nginx 在高并發(fā)反向代理上更強,Apache 在需要 .htaccess 和動態(tài)模塊加載的場景更方便。
總結(jié)
到此這篇關(guān)于Tomcat與Nginx、Apache區(qū)別是什么的文章就介紹到這了,更多相關(guān)Tomcat與Nginx、Apache的區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nginx帶寬限制?limit_rate?limit_rate_after指令
這篇文章主要為大家介紹了nginx帶寬限制?limit_rate?limit_rate_after指令詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04
使用ngxtop實時監(jiān)控Nginx日志文件的示例代碼
在Nginx日志分析領(lǐng)域,ngxtop是一款強大的實時監(jiān)控工具,它能夠即時解析Nginx的訪問日志文件,提供直觀、可定制的實時統(tǒng)計信息,幫助管理員更好地了解服務(wù)器的運行狀況和Web流量,本文給大家介紹使用ngxtop實時監(jiān)控Nginx日志文件的示例代碼,需要的朋友可以參考下2024-01-01
Nginx正向代理實現(xiàn)局域網(wǎng)電腦訪問外網(wǎng)的過程詳解
在工作中我遇到了一個類似的情況:在公司網(wǎng)絡(luò)中,由于管理要求,局域網(wǎng)內(nèi)的電腦不能直接訪問外網(wǎng),但是,工作上領(lǐng)導(dǎo)吩咐需要讓局域網(wǎng)內(nèi)的電腦能夠訪問外網(wǎng)上的某個網(wǎng)站,這時候就需要用到正向代理,本文將介紹如何配置 Nginx 實現(xiàn)這一功能,需要的朋友可以參考下2024-03-03

