Nginx學習筆記(二)——編譯安裝步驟詳解、Nginx性能優化、Nginx主配置文件詳解

一、Nginx相關問題

1.1 Nginx是如何處理一個請求的呢?

(1)nginx在啓動時,會解析配置文件,得到需要監聽的端口與ip地址;然後在nginx的master進程裏面,先初始化好這個監控的socket,再進行listen;然後再fork出多個子進程出來, 子進程會競爭accept新的連接。

(2)此時,客戶端就可以向nginx發起連接了。當客戶端與nginx進行三次握手,與nginx建立好一個連接後;

(3)此時,某一個子進程會accept成功,然後Nginx創建對連接的封裝,即ngx_connection_t結構體。接着,根據事件調用相應的事件處理模塊,如http模塊與客戶端進行數據的交換。

(4)最後,nginx或客戶端來主動關掉連接,到此,一個連接就完成了。

1.2 Nginx爲什麼不使用多線程?爲什麼性能這麼高?nginx是如何實現高併發的?

(1)例如Apache服務器的工作原理,創建多個進程或線程,而每個進程或線程都會爲其分配cpu和內存,但是併發過大會榨乾服務器資源。由於web server的工作性質決定了每個request的大部份生命都是在網絡傳輸中,實際上花費在server機器上的時間片不多。這是幾個進程就解決高併發的祕密所在。即webserver剛好屬於網絡io密集型應用,不算是計算密集型。

(2)所以Nginx,採用單線程異步非阻塞處理請求,運用epoll模型,提供了一個隊列,排隊解決,不會爲每個請求分配cpu和內存資源,節省了大量資源,同時也減少了大量的CPU的上下文切換。所以才使得Nginx支持更高的併發。

(3)Nginx會有一個master主進程,一個master對應多個worker工作進程,每個worker工作進程可以處理多個請求,每進來一個request,會有一個worker進程去處理。但不是全程的處理,處理到可能發生阻塞的地方,比如向後端服務器轉發request,並等待請求返回。那麼,這個處理的worker繼續處理其他請求,而一旦後端服務器返回了,就會觸發這個事件,worker纔會來接手,這個request纔會接着往下走。

二、Nginx的編譯安裝及調優

2.1 編譯安裝

1、 解壓:
1)解壓tar包: tar zxf nginx-1.15.7.tar.gz
2)隱藏nginx版本,防止被攻擊vim nginx-1.15.7/src/core/nginx.h
在這裏插入圖片描述

nginx-1.15.9目錄裏的內容


1)auto目錄:裏面有4個子目錄,cc是編譯使用的,os是判斷操作系統類型的,其他都是輔助configure編譯的,也就是操作系統有什麼特性供nginx使用
2)CHANGES:各版本的改變,bug修復等信息;CHANGES.ru:nginx作者是俄羅斯人,這是俄羅斯版本
3)conf: 爲了方便運維配置,conf目錄裏有示例文件,安裝好後會拷貝到安裝目錄
4)configure 
5)contrib:提供nginx語法檢測字體
   cp -r contrib/vim/* ~/.vim	##家目錄下如果沒有.vim目錄,手動新建
6)html:默認發佈目錄,50x.html是報500錯誤時的頁面
7) src:源碼目錄

修改文件 /nginx-1.15.9/src/core/nginx.h

#define NGINX_VER          "nginx/" NGINX_VERSION
改爲:
#define NGINX_VER          "nginx/"	 

在這裏插入圖片描述

3) 在Nginx源碼/auto/cc/gcc文件中:  vim auto/cc/gcc

  • 在此Debug模式模式會插入許多追蹤和ASSERT之類的信息,在正常編譯過程中結束,會產生幾兆大小的包,我們可以在編譯之前關閉debug模式,這樣在編譯結束,只會產生幾百K左右的包大小。
# debug
#CFLAGS="$CFLAGS -g" ##本行註釋掉,關閉debug日誌模式,  

在這裏插入圖片描述
在這裏插入圖片描述

2、編譯安裝nginx
1)安裝gcc編譯器和openssl-devel: yum install gcc openssl-devel -y
2)在 /root/nginx/nginx-1.15.9 目錄下編譯:

./configure \
###自定義配置:
--prefix=/usr/local/nginx  \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/temp/nginx/client \
--http-proxy-temp-path=/var/temp/nginx/proxy \
--http-fastcgi-temp-path=/var/temp/nginx/fastcgi \
--http-uwsgi-temp-path=/var/temp/nginx/uwsgi \
--http-scgi-temp-path=/var/temp/nginx/scgi
--prefix=PATH 
	## 指定nginx的安裝目錄。默認 /usr/local/nginx
--with-http_realip_module 
	##通過這個模塊允許我們改變客戶端請求頭中客戶端IP地址值(例如X-Real-IP 或 X-Forwarded-For)
	##意義在於能夠使得後臺服務器記錄原始客戶端的IP地址
--with-http_ssl_module 
	##使用https協議模塊。默認情況下,該模塊沒有被構建。前提是openssl與openssl-devel已安裝
--without-http_rewrite_module 
	##perl正則表達式使用在location指令和ngx_http_rewrite_module模塊中。

發現報錯:
在這裏插入圖片描述
原因:缺少依賴性:gd-devel-2.0.35-26.el7.x86_64.rpm(缺什麼裝什麼)

3) 安裝:yum install gd-devel-2.0.35-26.el7.x86_64.rpm,再次編譯。

4)make && make install 安裝

3、啓動腳本做軟鏈接: ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
在這裏插入圖片描述

nginx -t	##檢測配置文件語法
nginx		##啓動nginx

4、修改配置

1)查看nginx的默認配置文件:vim //usr/local/nginx/conf/nginx.conf
2)修改用戶,讓nginx以nginx用戶和用戶組啓動。
在這裏插入圖片描述
3)檢測配置文件語法 :nginx -t 修改了nginx用戶和組後檢測會報錯,需要手動創建nginx用戶
在這裏插入圖片描述
4)添加nginx用戶useradd nginx,此時就不報錯了。

  • useradd -s /sbin/nologin -M -d /usr/local/nginx/ nginx 創建用戶

在這裏插入圖片描述
再次加載nginx的配置可能會出現報錯:

nginx: [error] invalid PID number "" in "/usr/local/nginx/logs/nginx.pid"
#解決:刪除/usr/local/nginx/logs/nginx.pid,再重新啓動

5)此時 ps aux,可看到兩個nginx進程,一個是root用戶開啓的master進程,一個是由nginx用戶開啓的worker進程
在這裏插入圖片描述

2.2調優

5、升級nginx的配置,調優
開啓的work進程數是由cpu的總核心數決定的(有幾核就有幾個work進程)
1) 修改虛擬機cpu核心數(虛擬機關機)
在這裏插入圖片描述

2)查看邏輯CPU的個數:cat /proc/cpuinfo | grep “processor” | wc -l 發現是4核的

在這裏插入圖片描述
3)修改nginx開啓的work進程數:vim //usr/local/nginx/conf/nginx.conf,並且重置nginx nginx -s reload

user  nginx     nginx;
worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;
  • nginx默認沒有開啓利用多核cpu,這樣配置後,在計算最費時的資源時,使用的cpu核數越多,越快,'0001’從左到右一次表示第四,第三,第二,第一個cpu核心,0表示關閉,1表示開啓
    在這裏插入圖片描述
    在這裏插入圖片描述

此時可以看到開啓了4個work進程。
在這裏插入圖片描述

4)修改併發連接數:vim //usr/local/nginx/conf/nginx.conf,並且重置nginx nginx -s reload
在這裏插入圖片描述

  • worker_connections 65535 : 單個後臺worker process進程的 最大併發鏈接數 ,同時也受linux系統進程的最大打開文件數的限制,需要修改’ulimit -n 65536’設置後,方可生效。
  • epoll是多路複用IO(I/O Multiplexing)中的一種方式 ,但是僅用於linux2.6以上內核,可以大大提高nginx的性能 ,Nginx正是由此IO模型支持高併發。Nginx支持select,poll,epoll,kqueue,resig,/dev/poll.kqueue對應BSD系統的高效IO模型,epoll對應Linux系統的高效模型。
  • I/O多路複用:如果一個I/O流進來,我們就開啓一個進程處理這個I/O流。那麼假設現在有一百萬個I/O流進來,那我們就需要開啓一百萬個進程一一對應處理這些I/O流(——這就是傳統意義下的多進程併發處理)。思考一下,一百萬個進程,你的CPU佔有率會多高,這個實現方式及其的不合理。所以人們提出了I/O多路複用這個模型,一個線程,通過記錄I/O流的狀態來同時管理多個I/O,可以提高服務器的吞吐能力

在這裏插入圖片描述

ps aux 查看進程,cat /proc/2212/limits在這裏插入圖片描述
在這裏插入圖片描述

如果不是我們期望的65535,

ulimit -a #查看系統的最大打開文件數
ulimit -n 65535 #更改系統配置,立即生效

在這裏插入圖片描述
nginx -s reload,然後重新查看。

在這裏插入圖片描述

三、Nginx主配置文件結構

nginx配置文件主要分爲六個區域:
main(全局設置)events(nginx工作模式)http(http設置)sever(主機設置)location(URL匹配)upstream(負載均衡服務器設置)

3.1 main模塊

下面時一個main區域,他是一個全局的設置:

    user nobody nobody;
    worker_processes 1;
    error_log  /usr/local/var/log/nginx/error.log  notice;
    pid        /usr/local/var/run/nginx/nginx.pid;
    worker_rlimit_nofile 1024;

user 來指定Nginx Worker進程運行用戶以及用戶組,默認由nobody賬號運行。但我們一般更改爲用戶nginx運行,需要在nginx主機創建用戶nginx。

worker_processes來指定了Nginx要開啓的子進程數。每個Nginx進程平均耗費10M~12M內存。根據經驗,一般指定1個進程就足夠了,如果是多核CPU,建議指定和CPU的數量一樣的進程數即可

error_log用來定義全局錯誤日誌文件。日誌輸出級別有debug、info、notice、warn、error、crit可供選擇,其中,debug輸出日誌最爲最詳細,而crit輸出日誌最少。

pid用來指定進程id的存儲文件位置。

worker_rlimit_nofile用於指定一個nginx進程可以打開的最多文件描述符數目,這裏是65535,需要使用命令“ulimit -n 65535”來設置。

3.2 events模塊

events模塊來用指定nginx的工作模式和工作模式及連接數上限,一般是這樣:

    events {
        use kqueue; #mac平臺
        worker_connections  1024;
    }

use用來指定Nginx的工作模式。Nginx支持的工作模式有select、poll、kqueue、epoll、rtsig和/dev/poll。其中select和poll都是標準的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平臺上,而kqueue用在BSD系統中,因爲Mac基於BSD,所以Mac也得用這個模式,對於Linux系統,epoll工作模式是首選。

worker_connections用於定義Nginx每個進程的最大連接數,即接收前端的最大請求數,默認是1024。最大客戶端連接數由worker_processes和worker_connections決定,即Max_clients=worker_processes*worker_connections,在作爲反向代理時,Max_clients變爲:Max_clients = worker_processes * worker_connections/4。
進程的最大連接數受Linux系統進程的最大打開文件數限制,在執行操作系統命令“ulimit -n 65536”後worker_connections的設置才能生效。

3.3 http 模塊

http模塊是最核心的模塊了,它負責HTTP服務器相關屬性的配置,它裏面的server和upstream子模塊,至關重要,等到反向代理和負載均衡以及虛擬目錄等會仔細說。

    http{
        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  /usr/local/var/log/nginx/access.log  main;
        sendfile        on;
        tcp_nopush      on;
        tcp_nodelay     on;
        keepalive_timeout  10;
        #gzip  on;
        upstream myproject {
            .....
        }
        server {
            ....
        }
    }

include 用來設定文件的mime類型,類型在配置文件目錄下的mime.type文件定義,來告訴nginx來識別文件類型。

default_type設定了默認的類型爲二進制流,也就是當文件類型未定義時使用這種方式,例如在沒有配置asp 的locate 環境時,Nginx是不予解析的,此時,用瀏覽器訪問asp文件就會出現下載了。

log_format用於設置日誌的格式,和記錄哪些參數,這裏設置爲main,剛好用於access_log來記錄這種類型。

main的類型日誌如下:也可以增刪部分參數。

127.0.0.1 - - [21/Apr/2015:18:09:54 +0800] "GET /index.php HTTP/1.1" 200 87151 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36"

access_log 用來紀錄每次的訪問日誌的文件地址,後面的main是日誌的格式樣式,對應於log_format的main。

sendfile參數用於開啓高效文件傳輸模式。將tcp_nopush和tcp_nodelay兩個指令設置爲on用於防止網絡阻塞。

keepalive_timeout設置客戶端連接保持活動的超時時間。在超過這個時間之後,服務器會關閉該連接。

3.4 server 模塊

sever 模塊是http的子模塊,它用來定一個虛擬主機。

    server {
            listen       8080;
            server_name  localhost 192.168.12.10 www.yangyi.com;
            # 全局定義,如果都是這一個目錄,這樣定義最簡單。
            root   /Users/yangyi/www;
            index  index.php index.html index.htm; 
            charset utf-8;
            access_log  usr/local/var/log/host.access.log  main;
            aerror_log  usr/local/var/log/host.error.log  error;
            ....
    }

server標誌定義虛擬主機開始。
listen用於指定虛擬主機的服務端口。
server_name用來指定IP地址或者域名,多個域名之間用空格分開。
root 表示在這整個server虛擬主機內,全部的root web根目錄。注意要和locate {}下面定義的區分開來。
index 全局定義訪問的默認首頁地址。注意要和locate {}下面定義的區分開來。
charset用於設置網頁的默認編碼格式。
access_log用來指定此虛擬主機的訪問日誌存放路徑,最後的main用於指定訪問日誌的輸出格式。

3.5 location模塊

location模塊是nginx中用的最多的,也是最重要的模塊了,負載均衡、反向代理、虛擬域名都與它相關。

location 根據它字面意思就知道是來定位的,定位URL,解析URL,所以,它也提供了強大的正則匹配功能,也支持條件判斷匹配,用戶可以通過location指令實現Nginx對動、靜態網頁進行過濾處理。像我們的php環境搭建就是用到了它。

我們先來設定默認首頁和虛擬機目錄。

    location / {
                root   /Users/yangyi/www;
                index  index.php index.html index.htm;
            }

location /表示匹配訪問根目錄。

root指令用於指定訪問根目錄時,虛擬主機的web目錄,這個目錄可以是相對路徑(相對路徑是相對於nginx的安裝目錄)。也可以是絕對路徑。

index用於設定我們只輸入域名後訪問的默認首頁地址,有個先後順序:index.php index.html index.htm,如果沒有開啓目錄瀏覽權限,又找不到這些默認首頁,就會報403錯誤。

location 還有一種方式就是正則匹配,開啓正則匹配這樣:location ~。後面加個~。下面就是:

    location ~ \.php$ {
                root           /Users/yangyi/www;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                include        fastcgi.conf;
            }

\.php$ 熟悉正則的我們直到,這是匹配.php結尾的URL,用來解析php文件。裏面的root也是一樣,用來表示虛擬主機的根目錄。
fast_pass鏈接的是php-fpm 的地址。

3.6 upstream 模塊

upstream 模塊負責負載均衡模塊,通過一個簡單的調度算法來實現客戶端IP到後端服務器的負載均衡。

    upstream iyangyi.com{
        ip_hash;
        server 192.168.12.1:80;
        server 192.168.12.2:80 down;
        server 192.168.12.3:8080  max_fails=3  fail_timeout=20s;
        server 192.168.12.4:8080;
    }

在上面的例子中,通過upstream指令指定了一個負載均衡器的名稱iyangyi.com。這個名稱可以任意指定,在後面需要的地方直接調用即可。

裏面是ip_hash這是其中的一種負載均衡調度算法,下面會着重介紹。緊接着就是各種服務器了。用server關鍵字表識,後面接ip。

Nginx的負載均衡模塊目前支持4種調度算法:

  • weight輪詢(默認)。每個請求按時間順序逐一分配到不同的後端服務器,如果後端某臺服務器宕機,故障系統被自動剔除,使用戶訪問不受影響。weight。指定輪詢權值,weight值越大,分配到的訪問機率越高,主要用於後端每個服務器性能不均的情況下。
  • ip_hash。每個請求按訪問IP的hash結果分配,這樣來自同一個IP的訪客固定訪問一個後端服務器,有效解決了動態網頁存在的session共享問題。
  • fair。比上面兩個更加智能的負載均衡算法。此種算法可以依據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間來分配請求,響應時間短的優先分配。Nginx本身是不支持fair的,如果需要使用這種調度算法,必須下載Nginx的upstream_fair模塊。
  • url_hash。按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,可以進一步提高後端緩存服務器的效率。Nginx本身是不支持url_hash的,如果需要使用這種調度算法,必須安裝Nginx的hash軟件包。

在HTTP Upstream模塊中,可以通過server指令指定後端服務器的IP地址和端口,同時還可以**設定每個後端服務器在負載均衡調度中的狀態**。常用的狀態有:

  • down,表示當前的server暫時不參與負載均衡。
  • backup,預留的備份機器。當其他所有的非backup機器出現故障或者忙的時候,纔會請求backup機器,因此這臺機器的壓力最輕。
  • max_fails,允許請求失敗的次數,默認爲1。當超過最大次數時,返回proxy_next_upstream 模塊定義的錯誤。
  • fail_timeout,在經歷了max_fails次失敗後,暫停服務的時間。max_fails可以和fail_timeout一起使用。

注意 :當負載調度算法爲ip_hash時,後端服務器在負載均衡調度中的狀態不能是weight和backup。

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