Java Web容器篇之Tomcat & Nginx

Java Web系列文章彙總貼: Java Web知識總結匯總


Tomcat

Tomcat的頂層架構

 Tomcat的頂層架構

Tomcat的兩個核心組件:Connector & Container。

多個Connector和一個Container就形成了Service,而Service包括整個Tomcat的生命週期由Server控制。

Connector負責接受請求,Container負責處理這些請求,Service主要負責關聯兩者,同時會初始化它下面的其他組件。所有組件的聲明週期在一個Lifecycle的接口中控制。

Server提供一個接口讓其他程序能夠訪問到這個Service集合,同時要維護它包含的所有Service的生命週期,包括如何初始化、如何結束服務、如何找到別人要訪問的Service。

Connector架構分析

Connector就是使用ProtocolHandler來處理請求的,不同的ProtocolHandler代表不同的連接類型,比如:Http11Protocol使用的是普通Socket來連接的,Http11NioProtocol使用的是NioSocket來連接的。

其中ProtocolHandler由包含了三個部件:Endpoint、Processor、Adapter。

(1)Endpoint用來處理底層Socket的網絡連接,Processor用於將Endpoint接收到的Socket封裝成Request,Adapter用於將Request交給Container進行具體的處理。

(2)Endpoint由於是處理底層的Socket網絡連接,因此Endpoint是用來實現TCP/IP協議的,而Processor用來實現HTTP協議的,Adapter將請求適配到Servlet容器進行具體的處理。

(3)Endpoint的抽象實現AbstractEndpoint裏面定義的Acceptor和AsyncTimeout兩個內部類和一個Handler接口。Acceptor用於監聽請求,AsyncTimeout用於檢查異步Request的超時,Handler用於處理接收到的Socket,在內部調用Processor進行處理。

Container架構分析

 Container架構分析

4個子容器的作用分別是:

(1)Engine:引擎,用來管理多個站點,一個Service最多只能有一個Engine;
(2)Host:代表一個站點,也可以叫虛擬主機,通過配置Host就可以添加站點;
(3)Context:代表一個應用程序,對應着平時開發的一套程序,或者一個WEB-INF目錄以及下面的web.xml文件;
(4)Wrapper:每一Wrapper封裝着一個Servlet;

參考:
四張圖帶你瞭解Tomcat系統架構
Tomcat的系統架構與工作流程簡介
Servlet的工作原理


Nginx

什麼是C10K問題

C10K問題由來

隨着互聯網的普及,應用的用戶羣體幾何倍增長,此時服務器性能問題就出現。最初的服務器是基於進程/線程模型。新到來一個TCP連接,就需要分配一個進程。假如有C10K,就需要創建1W個進程,可想而知單機是無法承受的。那麼如何突破單機性能是高性能網絡編程必須要面對的問題,進而這些侷限和問題就統稱爲C10K問題,最早是由Dan Kegel進行歸納和總結的,並且他也系統的分析和提出解決方案。

C10K問題的本質

C10K問題的本質上是操作系統的問題。對於Web 1.0/2.0時代的操作系統,傳統的同步阻塞I/O模型處理方式都是requests per second。當創建的進程或線程多了,數據拷貝頻繁(緩存I/O、內核將數據拷貝到用戶進程空間、阻塞,進程/線程上下文切換消耗大, 導致操作系統崩潰,這就是C10K問題的本質。
可見, 解決C10K問題的關鍵就是儘可能減少這些CPU資源消耗。

C10K問題的解決方案

從網絡編程技術的角度來說,主要思路:

  • 每個連接分配一個獨立的線程/進程
  • 同一個線程/進程同時處理多個連接

摘自:
C10K問題

正向代理和反向代理

正向代理:
正向代理通過下面的圖理解其實就是用戶想從服務器拿資源數據,但是隻能通過proxy服務器才能拿到,所以用戶A只能去訪問proxy服務器然後通過proxy服務器去服務器B拿數據,這種情況用戶是明確知道你要訪問的是誰,在我們生活中最典型的案例就是“翻牆“了,也是通過訪問代理服務器最後訪問外網的。
反向代理:
反向代理其實就是客戶端去訪問服務器時,他並不知道會訪問哪一臺,感覺就是客戶端訪問了Proxy一樣,而實則就是當proxy關口拿到用戶請求的時候會轉發到代理服務器中的隨機(算法)某一臺。而在用戶看來,他只是訪問了Proxy服務器而已,典型的例子就是負載均衡了。

圖示:

參考:
談一談正向代理和反向代理

Nginx中常用的幾種負載均衡策略

策略 釋義
輪詢 默認方式
weight 權重方式
ip_hash 根據ip分配方式
least_conn 最少連接方式
fair(第三方) 響應時間方式
url_hash(第三方) 根據URL分配方式

參考:
Nginx服務器之負載均衡策略(6種)

擴展:Web的負載均衡策略

幾種負載均衡方式

  • HTTP重定向實現負載均衡
  • DNS負載均衡
  • 反向代理負載均衡

負載均衡組件

  • apache
  • nginx
  • lvs
  • HAProxy
  • keepalived

常見的幾種負載均衡算法

  • 1、輪詢
  • 2、加權輪詢
  • 3、隨機
  • 4、加權隨機
  • 5、Hash法:根據客戶端的IP,或者請求的“Key”,計算出一個hash值,然後對節點數目取模
  • 6、最少連接

更多:
高併發解決方案之一 ——負載均衡
Web應用的負載均衡、集羣、高可用(HA)解決方案整理總結
關於負載均衡的一切:總結與思考

Nginx架構及工作原理

Nginx架構

大致上Nginx的架構就是這樣:
1.Nginx啓動後,會產生一個主進程,主進程執行一系列的工作後會產生一個或者多個工作進程;
2.在客戶端請求動態站點的過程中,Nginx服務器還涉及和後端服務器的通信。Nginx將接收到的Web請求通過代理轉發到後端服務器,由後端服務器進行數據處理和組織;
3.Nginx爲了提高對請求的響應效率,降低網絡壓力,採用了緩存機制,將歷史應答數據緩存到本地。保障對緩存文件的快速訪問;

工作進程

工作進程的主要工作有以下幾項:

  • 接收客戶端請求;
  • 將請求一次送入各個功能模塊進行過濾處理;
  • IO調用,獲取響應數據;
  • 與後端服務器通信,接收後端服務器處理結果;
  • 數據緩存
  • 響應客戶端請求;

進程交互

Nginx服務器在使用Master-Worker模型時,會涉及到主進程和工作進程的交互和工作進程之間的交互。這兩類交互都依賴於管道機制。
1.Master-Worker交互
這條管道與普通的管道不同,它是由主進程指向工作進程的單向管道,包含主進程向工作進程發出的指令,工作進程ID等;同時主進程與外界通過信號通信;
2.worker-worker交互
這種交互是和Master-Worker交互是基本一致的。但是會通過主進程。工作進程之間是相互隔離的,所以當工作進程W1需要向工作進程W2發指令時,首先找到W2的進程ID,然後將正確的指令寫入指向W2的通道。W2收到信號採取相應的措施。

Nginx模塊化

  • (1)核心模塊;
    核心模塊是Nginx服務器正常運行必不可少的模塊,如同操作系統的內核。它提供了Nginx最基本的核心服務。像進程管理、權限控制、錯誤日誌記錄等;

  • (2)標準HTTP模塊;
    標準HTTP模塊支持標準的HTTP的功能;

  • (3)可選HTTP模塊;
    可選HTTP模塊主要用於擴展標準的HTTP功能,讓Nginx能處理一些特殊的服務;

  • (4)郵件服務模塊;
    郵件服務模塊主要用於支持Nginx的郵件服務;

  • (5)第三方模塊;
    第三方模塊是爲了擴展Nginx服務器應用,完成開發者想要的功能;

參考:
Nginx服務器架構簡析
Nginx架構設計簡介

Nginx配置

#運行用戶
user nobody;
#啓動進程,通常設置成和cpu的數量相等
worker_processes  1;
 
#全局錯誤日誌及PID文件
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
 
#pid        logs/nginx.pid;
 
#工作模式及連接數上限
events {
    #epoll是多路複用IO(I/O Multiplexing)中的一種方式,
    #僅用於linux2.6以上內核,可以大大提高nginx的性能
    use   epoll; 
 
    #單個後臺worker process進程的最大併發鏈接數    
    worker_connections  1024;
 
    # 併發總數是 worker_processes 和 worker_connections 的乘積
    # 即 max_clients = worker_processes * worker_connections
    # 在設置了反向代理的情況下,max_clients = worker_processes * worker_connections / 4  爲什麼
    # 爲什麼上面反向代理要除以4,應該說是一個經驗值
    # 根據以上條件,正常情況下的Nginx Server可以應付的最大連接數爲:4 * 8000 = 32000
    # worker_connections 值的設置跟物理內存大小有關
    # 因爲併發受IO約束,max_clients的值須小於系統可以打開的最大文件數
    # 而系統可以打開的最大文件數和內存大小成正比,一般1GB內存的機器上可以打開的文件數大約是10萬左右
    # 我們來看看360M內存的VPS可以打開的文件句柄數是多少:
    # $ cat /proc/sys/fs/file-max
    # 輸出 34336
    # 32000 < 34336,即併發連接總數小於系統可以打開的文件句柄總數,這樣就在操作系統可以承受的範圍之內
    # 所以,worker_connections 的值需根據 worker_processes 進程數目和系統可以打開的最大文件總數進行適當地進行設置
    # 使得併發總數小於操作系統可以打開的最大文件數目
    # 其實質也就是根據主機的物理CPU和內存進行配置
    # 當然,理論上的併發總數可能會和實際有所偏差,因爲主機還有其他的工作進程需要消耗系統資源。
    # ulimit -SHn 65535
 
}
 
 
http {
    #設定mime類型,類型由mime.type文件定義
    include    mime.types;
    default_type  application/octet-stream;
    #設定日誌格式
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    access_log  logs/access.log  main;
 
    #sendfile 指令指定 nginx 是否調用 sendfile 函數(zero copy 方式)來輸出文件,
    #對於普通應用,必須設爲 on,
    #如果用來進行下載等應用磁盤IO重負載應用,可設置爲 off,
    #以平衡磁盤與網絡I/O處理速度,降低系統的uptime.
    sendfile     on;
    #tcp_nopush     on;
 
    #連接超時時間
    #keepalive_timeout  0;
    keepalive_timeout  65;
    tcp_nodelay     on;
 
    #開啓gzip壓縮
    gzip  on;
    gzip_disable "MSIE [1-6].";
 
    #設定請求緩衝
    client_header_buffer_size    128k;
    large_client_header_buffers  4 128k;
 
 
    #設定虛擬主機配置
    server {
        #偵聽80端口
        listen    80;
        #定義使用 www.nginx.cn訪問
        server_name  www.nginx.cn;
 
        #定義服務器的默認網站根目錄位置
        root html;
 
        #設定本虛擬主機的訪問日誌
        access_log  logs/nginx.access.log  main;
 
        #默認請求
        location / {
            
            #定義首頁索引文件的名稱
            index index.php index.html index.htm;   
 
        }
 
        # 定義錯誤提示頁面
        error_page   500 502 503 504 /50x.html;
        location = /50x.html {
        }
 
        #靜態文件,nginx自己處理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            
            #過期30天,靜態文件不怎麼更新,過期可以設大一點,
            #如果頻繁更新,則可以設置得小一點。
            expires 30d;
        }
 
        #PHP 腳本請求全部轉發到 FastCGI處理. 使用FastCGI默認配置.
        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;
        }
 
        #禁止訪問 .htxxx 文件
            location ~ /.ht {
            deny all;
        }
 
    }
}

參考:
nginx.conf 配置及基本優化
Nginx配置詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章