十八般武藝之Nginx踩坑總結

顯示亂碼問題

server {
  listen 80;
  server_name example.com;
  root /var/www/example;

  location / {
    charset utf-8; #一般是在個別的location中加入此項,具體情況具體對待
    rewrite .* /index.html break;
  }
}

index顯示列表(一般爲企業內部使用)

可在在location server 或 http段中加入

autoindex on;//自動顯示目錄
autoindex_exact_size off;//人性化方式顯示文件大小否則以byte顯示
autoindex_localtime on;//按服務器時間顯示,否則以gmt時間顯示

location用法

=:對URI做精確匹配;
    location = / {
        ...
    }
~:對URI做正則表達式模式匹配,區分字符大小寫;
~*:對URI做正則表達式模式匹配,不區分字符大小寫;
^~:對URI的左半部分做匹配檢查,不區分字符大小寫;
不帶符號:匹配起始於此uri的所有的url;
location /lizi {
        ...
    }
    例如www.example.com/lizi/xxx/xxx
    只要是路徑以/lizi開頭的都匹配,這種一般用於最後的通用匹配。

注意:匹配優先級:=, ^~, ~/~*,不帶符號;

具體匹配方式 http://seanlook.com/2015/05/17/nginx-location-rewrite/


常用優化配置

1.網絡連接的優化:

只能在events模塊設置,用於防止在同一一個時刻只有一個請求的情況下,出現多個睡眠進程會被喚醒但只能有一個進程可獲得請求的尷尬,如果不優化,在多進程的nginx會影響以部分性能。

events {
accept_mutex on; #優化同一時刻只有一個請求而避免多個睡眠進程被喚醒的設置,on爲防止被同時喚醒,默認爲off,因此nginx剛安裝完以後要進行適當的優化。
}

2.隱藏ngxin版本號:

當前使用的nginx可能會有未知的漏洞,如果被黑客使用將會造成無法估量的損失,但是我們可以將nginx的版本隱藏,如下:

server_tokens off; #在http 模塊當中配置

3.選擇事件驅動模型:

Nginx支持衆多的事件驅動,比如select、poll、epoll,只能設置在events模塊中設置:

events {
accept_mutex on;
multi_accept on;
use epoll; #使用epoll事件驅動,因爲epoll的性能相比其他事件驅動要好很多
}

4.配置單個工作進程的最大連接數:

通過worker_connections number;進行設置,numebr爲整數,number的值不能大於操作系統能打開的最大的文件句柄數,使用ulimit -n可以查看當前操作系統支持的最大文件句柄數,默認爲爲1024.

events {
    worker_connections  102400; #設置單個工作進程最大連接數102400
}

5.配置允許sendfile方式傳輸文件:

是由後端程序負責把源文件打包加密生成目標文件,然後程序讀取目標文件返回給瀏覽器;這種做法有個致命的缺陷就是佔用大量後端程序資源,如果遇到一些訪客下載速度巨慢,就會造成大量資源被長期佔用得不到釋放(如後端程序佔用的CPU/內存/進程等),很快後端程序就會因爲沒有資源可用而無法正常提供服務。通常表現就是 nginx報502錯誤,而sendfile打開後配合location可以實現有nginx檢測文件使用存在,如果存在就有nginx直接提供靜態文件的瀏覽服務,因此可以提升服務器性能.

    sendfile        on; #   可以配置在http、server或者location模塊,配置如下:
    sendfile_max_chunk 512k;   #Nginxg工作進程每次調用sendfile()傳輸的數據最大不能超出這個值,默認值爲0表示無限制,可以設置在http/server/location模塊中。

6.會話保持時間:

用戶和服務器建立連接後客戶端分配keep-alive鏈接超時時間,服務器將在這個超時時間過後關閉鏈接,我們將它設置低些可以讓ngnix持續工作的時間更長,1.8.1默認爲65秒,一般不超過120秒。

 keepalive_timeout  65 60;  #後面的60爲發送給客戶端應答報文頭部中顯示的超時時間設置爲60s:如不設置客戶端將不顯示超時時間。
  Keep-Alive:timeout=60  #瀏覽器收到的服務器返回的報文

如果設置爲0表示關閉會話保持功能,將如下顯示:
  Connection:close  #瀏覽器收到的服務器返回的報文

7.配置nginx worker進程最大打開文件數

worker_rlimit_nofile 65535;

8.配置nginx gzip壓縮實現性能優化

圖片、視頻(流媒體)等文件儘量不要壓縮,因爲這些文件大多都是經過壓縮的,如果再壓縮很可能不會減小或減小很少,或者有可能增大,而在壓縮時還會消耗大量的CPU、內存資源


gzip on;                               #表示開啓壓縮功能

gzip_min_length  1k;                 #表示允許壓縮的頁面最小字節數,頁面字節數從header頭的Content-Length中獲取。默認值是0,表示不管頁面多大都進行壓縮,建議設置成大於1K。如果小於1K可能會越壓越大

gzip_buffers     432k;                   #壓縮緩存區大小

gzip_http_version 1.1;                  #壓縮版本

gzip_comp_level 9;                    #壓縮比率

gzip_types  text/css text/xml application/javascript;  #指定壓縮的類型

gzip_vary on;                       #vary header支持

9.nginx expires功能

爲用戶訪問網站的內容設定一個過期時間,當用戶第一次訪問到這些內容時,會把這些內容存儲在用戶瀏覽器本地,這樣用戶第二次及之後繼續訪問該網站,瀏覽器就會檢查已經緩存在用戶瀏覽器本地的內容,就不會去瀏覽器下載了,直到緩存的內容過期或者被清除爲止。

## Add expires header according to URI(path or dir).

location ~ ^/(images|javascript|js|css|flash|media|static)/ {
    expires 360d;
}

常用正則(跟Linux上的正則沒什麼區別)

. : 匹配除換行符以外的任意字符
? : 重複0次或1次
+ : 重複1次或更多次
* : 重複0次或更多次
\d :匹配數字
^ : 匹配字符串的開始
$ : 匹配字符串的結束
{n} : 重複n次
{n,} : 重複n次或更多次
[c] : 匹配單個字符c
[a-z] : 匹配a-z小寫字母的任意一個

類似分組():小括號()之間匹配的內容,可以在後面通過1來引用,2表示的是前面第二個()裏的內容。正則裏面容易讓人困惑的是\轉義特殊字符。


rewrite實例

http {
    # 定義image日誌格式
    log_format imagelog '[$time_local] ' $image_file ' ' $image_type ' ' $body_bytes_sent ' ' $status;
    # 開啓重寫日誌
    rewrite_log on;

    server {
        root /home/www;

        location / {
                # 重寫規則信息
                error_log logs/rewrite.log notice;
                # 注意這裏要用‘’單引號引起來,避免{}
                rewrite '^/images/([a-z]{2})/([a-z0-9]{5})/(.*)\.(png|jpg|gif)$' /data?file=$3.$4;
                # 注意不能在上面這條規則後面加上“last”參數,否則下面的set指令不會執行
                set $image_file $3;
                set $image_type $4;
        }

        location /data {
                # 指定針對圖片的日誌格式,來分析圖片類型和大小
                access_log logs/images.log mian;
                root /data/images;
                # 應用前面定義的變量。判斷首先文件在不在,不在再判斷目錄在不在,如果還不在就跳轉到最後一個url裏
                try_files /$arg_file /image404.html;
        }
        location = /image404.html {
                # 圖片不存在返回特定的信息
                return 404 "image not found\n";
        }
}

if語句塊

  • 例子是網上找的,if語句塊長用在做單獨的限制,如限制訪問特定的資源,然後對此類請求做處理,rewire或者deny或者proxy_pass等等。
  • 例子中的set語句沒怎麼用過。也沒再去查資料,用的時候再查 = =
if ($http_user_agent ~ MSIE) {proxy_pass
    rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite請求到/msid/目錄下

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
 } //如果cookie匹配正則,設置變量$id等於正則引用部分

if ($request_method = POST) {
    return 405;
} //如果提交方法爲POST,則返回狀態405(Method not allowed)。return不能返回301,302

if ($slow) {
    limit_rate 10k;
} //限速,$slow可以通過 set 指令設置

if (!-f $request_filename){
    break;
    proxy_pass  http://127.0.0.1;
} //如果請求的文件名不存在,則反向代理到localhost 。這裏的break也是停止rewrite檢查

if ($args ~ post=140){
    rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com

location ~* \.(gif|jpg|png|swf|flv)$ {
    valid_referers none blocked www.jefflei.com www.leizhenfang.com;
    if ($invalid_referer) {
        return 404;
    } //防盜鏈
}

https

  • 定義一個新的server,配置如下,必須的配置有listen ,server_name, ssl ,ssl_certificate, ssl_certificate_key,一般配置的時候我都是直接複製,然後改主機名,證書私鑰文件,日誌路徑,root的根目錄這幾項。
  • 如果想讓訪問80的轉到443,可用rewrite語句
listen 443;
server_name agent.t.jlhcar.com;

ssl on;
ssl_certificate, "/usr/local/certificate/agent.t.jlhcar.com.pem";\\證書
ssl_certificate_key "/usr/local/certificate/agent.t.jlhcar.com.key";\\私鑰
ssl_session_cache shared:SSL:1m;
ssl_session_timeout  10m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\\協議
...
//日誌以及root根目錄的其他配置

server {
        listen 80;
        server_name agent.xxx.com;
        rewrite ^/(.*)$ https://agent.xxx.com/$1;
}

注意:曾經遇到過這麼一個坑,http轉https的時候會將POST轉換爲GET請求,此時需要這樣配置

server {
        listen 80;
        server_name dev-payment.xxxx.cn;
        return 307 https://dev-payment.xxxx.cn$request_uri;
}

php後端處理(fastcgi)

location ~ \.php($|/) {
        fastcgi_pass unix:/dev/shm/php-fpm.unix; //最重要的一項,根據實際情況來配置(根據php的配置文件listen的配置來配置,其值可以是一個域名、IP地址:端口、或者是一個Unix的Socket文件。
)
        fastcgi_index index.php; //當請求以/結尾的時候,會將請求傳遞給所設置的index.php文件處理。


        fastcgi_split_path_info ^(.+\.php)(.*)$; //Nginx默認獲取不到PATH_INFO的值,得通過fastcgi_split_path_info指定定義的正則表達式來給$fastcgi_path_info賦值。


        fastcgi_param PATH_INFO $fastcgi_path_info; //
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi.conf;
}

示例鏈接:https://segmentfault.com/q/1010000010786459


負載均衡和反向代理

  • 在http配置段要配置一個upstream
upstream ucart{
    server 119.29.48.27:80;
    server 119.29.48.27:80;
}

注意:nginx中不識別_(下劃線),否則會出現400錯誤

然後再server配置段,將所需要處理的請求反向代理至後端服務器,在可根據需要和服務器配置情況來定義權重,實現負載均衡

location /ucarapi/ {
    proxy_pass http://ucar_t/;
    proxy_connect_timeout   3; //連接超時時間
    proxy_read_timeout      30;
    proxy_set_header  Host tapi.51ucar.cn; //HTTP頭信息,後端服務器根據此來找到特定虛擬主機
    proxy_set_header X-Real-IP $remote_addr; //HTTP頭信息,真實IP
    proxy_set_header X-Scheme $scheme;
}

喜歡我寫的東西的朋友可以關注一下我的公衆號,上面有我的學習資源以及一些其他福利。:Devops部落


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