1. <th id="orwrz"></th>
        <tbody id="orwrz"><pre id="orwrz"></pre></tbody>
      2. <rp id="orwrz"><object id="orwrz"></object></rp>
        首頁 運維干貨Nginx 最全操作總結

        Nginx 最全操作總結

        運維派隸屬馬哥教育旗下專業運維社區,是國內成立最早的IT運維技術社區,歡迎關注公眾號:yunweipai
        領取學習更多免費Linux云計算、Python、Docker、K8s教程關注公眾號:馬哥linux運維

        本文將會從:安裝 -> 全局配置 -> 常用的各種配置 來書寫,其中常用配置寫的炒雞詳細,需要的童鞋可以直接滑倒相應的位置查看。

        安裝 nginx

        下載 nginx 的壓縮包文件到根目錄,官網下載地址:nginx.org/download/nginx-x.xx.xx.tar.gz

        yum?update?#更新系統軟件  
        cd?/  
        wget?nginx.org/download/nginx-1.17.2.tar.gz  
        

        解壓 tar.gz 壓縮包文件,進去 nginx-1.17.2

        tar?-xzvf?nginx-1.17.2.tar.gz  
        cd?nginx-1.17.2  
        

        進入文件夾后進行配置檢查

        ./configure  
        

        通過安裝前的配置檢查,發現有報錯。檢查中發現一些依賴庫沒有找到,這時候需要先安裝 nginx 的一些依賴庫

        yum?-y?install?pcre*?#安裝使nginx支持rewrite  
        yum?-y?install?gcc-c++  
        yum?-y?install?zlib*  
        yum?-y?install?openssl?openssl-devel  
        

        再次進行檢查操作 ./configure 沒發現報錯顯示,接下來進行編譯并安裝的操作

        // 檢查模塊支持
          ./configure  --prefix=/usr/local/nginx  --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream_ssl_preread_module --with-threads --user=www --group=www 
        

        這里得特別注意下,你以后需要用到的功能模塊是否存在,不然以后添加新的包會比較麻煩。

        查看默認安裝的模塊支持

        ls nginx-1.17.2 查看 nginx 的文件列表,可以發現里面有一個 auto 的目錄。

        在這個 auto 目錄中有一個 options 文件,這個文件里面保存的就是 nginx 編譯過程中的所有選項配置。

        通過命令:cat nginx-1.17.2/auto/options | grep YES 就可以查看

        nginx 編譯安裝時,怎么查看安裝模塊

        編譯并安裝

        make?&&?make?install  
        

        這里需要注意,模塊的支持跟后續的 nginx 配置有關,比如 SSL,gzip 壓縮等等,編譯安裝前最好檢查需要配置的模塊存不存在。

        查看 nginx 安裝后在的目錄,可以看到已經安裝到 /usr/local/nginx 目錄了

        whereis?nginx  
        $nginx:?/usr/local/nginx  
        

        啟動 nginx 服務

        cd?/usr/local/nginx/sbin/  
        ./nginx  
        

        服務啟動的時候報錯了:nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) ,通過命令查看本機網絡地址和端口等一些信息,找到被占用的 80 端口 netstat \-ntpl 的 tcp 連接,并殺死進程(kill 進程 pid)

        netstat?-ntpl  
        kill?進程PID  
        

        繼續啟動 nginx 服務,啟動成功

        ./nginx  
        

        在瀏覽器直接訪問 ip 地址,頁面出現 Welcome to Nginx! 則安裝成功。

        nginx 配置

        基本結構

        main????????#?全局配置,對全局生效  
        ├──?events??#?配置影響?nginx?服務器或與用戶的網絡連接  
        ├──?http????#?配置代理,緩存,日志定義等絕大多數功能和第三方模塊的配置  
        │???├──?upstream?#?配置后端服務器具體地址,負載均衡配置不可或缺的部分  
        │???├──?server???#?配置虛擬主機的相關參數,一個?http?塊中可以有多個?server?塊  
        │???├──?server  
        │???│???├──?location??#?server?塊可以包含多個?location?塊,location?指令用于匹配?uri  
        │???│???├──?location  
        │???│???└──?...  
        │???└──?...  
        └──?...  
        

        主要配置含義

        • main:nginx 的全局配置,對全局生效。
        • events:配置影響 nginx 服務器或與用戶的網絡連接。
        • http:可以嵌套多個 server,配置代理,緩存,日志定義等絕大多數功能和第三方模塊的配置。
        • server:配置虛擬主機的相關參數,一個 http 中可以有多個 server。
        • location:配置請求的路由,以及各種頁面的處理情況。
        • upstream:配置后端服務器具體地址,負載均衡配置不可或缺的部分。

        nginx.conf 配置文件的語法規則

        1. 配置文件由指令與指令塊構成
        2. 每條指令以 “;” 分號結尾,指令與參數間以空格符號分隔
        3. 指令塊以 {} 大括號將多條指令組織在一起
        4. include 語句允許組合多個配置文件以提升可維護性
        5. 通過 # 符號添加注釋,提高可讀性
        6. 通過 \$ 符號使用變量
        7. 部分指令的參數支持正則表達式,例如常用的 location 指令

        內置變量

        nginx 常用的內置全局變量,你可以在配置中隨意使用:

        常用命令

        這里列舉幾個常用的命令:

        nginx?-s?reload??#?向主進程發送信號,重新加載配置文件,熱重啟  
        nginx?-s?reopen??#?重啟?Nginx  
        nginx?-s?stop????#?快速關閉  
        nginx?-s?quit????#?等待工作進程處理完成后關閉  
        nginx?-T?????????#?查看當前?Nginx?最終的配置  
        nginx?-t?-c?<配置路徑>??#?檢查配置是否有問題,如果已經在配置目錄,則不需要?-c  
        

        以上命令通過 nginx \-h 就可以查看到,還有其它不常用這里未列出。

        Linux 系統應用管理工具 systemd 關于 nginx 的常用命令:

        systemctl?start?nginx????#?啟動?Nginx  
        systemctl?stop?nginx?????#?停止?Nginx  
        systemctl?restart?nginx??#?重啟?Nginx  
        systemctl?reload?nginx???#?重新加載?Nginx,用于修改配置后  
        systemctl?enable?nginx???#?設置開機啟動?Nginx  
        systemctl?disable?nginx??#?關閉開機啟動?Nginx  
        systemctl?status?nginx???#?查看?Nginx?運行狀態  
        

        配置 nginx 開機自啟

        利用 systemctl 命令

        如果用 yum install 命令安裝的 nginx,yum 命令會自動創建 nginx.service 文件,直接用命令:

        systemctl?enable?nginx???#?設置開機啟動?Nginx  
        systemctl?disable?nginx??#?關閉開機啟動?Nginx  
        

        就可以設置開機自啟,否則需要在系統服務目錄里創建 nginx.service 文件。

        創建并打開 nginx.service 文件:

        vi?/lib/systemd/system/nginx.service  
        

        內容如下:

        [Unit]  
        Description=nginx  
        After=network.target  
        
        [Service]  
        Type=forking  
        ExecStart=/usr/local/nginx/sbin/nginx  
        ExecReload=/usr/local/nginx/sbin/nginx?-s?reload  
        ExecStop=/usr/local/nginx/sbin/nginx?-s?quit  
        PrivateTmp=true  
        
        [Install]  
        WantedBy=multi-user.target  
        

        :wq 保存退出,運行 systemctl daemon-reload 使文件生效。

        這樣便可以通過以下命令操作 nginx 了:

        systemctl?start?nginx.service?#?啟動nginx服務  
        systemctl?enable?nginx.service?#?設置開機啟動  
        systemctl?disable?nginx.service?#?停止開機自啟動  
        systemctl?status?nginx.service?#?查看服務當前狀態  
        systemctl?restart?nginx.service?#?重新啟動服務  
        systemctl?is-enabled?nginx.service?#查詢服務是否開機啟動 
        

        通過開機啟動命令腳本實現開機自啟

        創建開機啟動命令腳本文件:

        vi?/etc/init.d/nginx  
        

        在這個 nginx 文件中插入一下啟動腳本代碼,啟動腳本代碼來源網絡復制,實測有效:

        #!?/bin/bash  
        #?chkconfig:?-?85?15  
        PATH=/usr/local/nginx  
        DESC="nginx?daemon"  
        NAME=nginx  
        DAEMON=PATH/sbin/NAME  
        CONFIGFILE=PATH/conf/NAME.conf  
        PIDFILE=PATH/logs/NAME.pid  
        scriptNAME=/etc/init.d/NAME  
        set?-e  
        [?-x?"DAEMON"?]?||?exit?0  
        do_start()?{  
        DAEMON?-c?CONFIGFILE?||?echo?-n?"nginx?already?running"  
        }  
        do_stop()?{  
        DAEMON?-s?stop?||?echo?-n?"nginx?not?running"  
        }  
        do_reload()?{DAEMON?-s?reload?||?echo?-n?"nginx?can't?reload"  
        }  
        case?"1"?in  
        start)  
        echo?-n?"Starting?DESC:?NAME"  
        do_start  
        echo?"."  
        ;;  
        stop)  
        echo?-n?"Stopping?DESC:?NAME"  
        do_stop  
        echo?"."  
        ;;  
        reload|graceful)  
        echo?-n?"Reloading?DESC?configuration..."  
        do_reload  
        echo?"."  
        ;;  
        restart)  
        echo?-n?"Restarting?DESC:?NAME"  
        do_stop  
        do_start  
        echo?"."  
        ;;  
        *)  
        echo?"Usage:?$scriptNAME?{start|stop|reload|restart}"?>&2  
        exit?3  
        ;;  
        esac  
        exit?0  
        

        設置所有人都有對這個啟動腳本 nginx 文件的執行權限:

        chmod?a+x?/etc/init.d/nginx  
        

        把 nginx 加入系統服務中:

        chkconfig?--add?nginx  
        

        把服務設置為開機啟動:

        chkconfig?nginx?on  
        

        reboot 重啟系統生效,可以使用上面 systemctl 方法相同的命令:

        systemctl?start?nginx.service?#?啟動nginx服務  
        systemctl?enable?nginx.service?#?設置開機啟動  
        systemctl?disable?nginx.service?#?停止開機自啟動  
        systemctl?status?nginx.service?#?查看服務當前狀態  
        systemctl?restart?nginx.service?#?重新啟動服務  
        systemctl?is-enabled?nginx.service?#查詢服務是否開機啟動  
        

        如果服務啟動的時候出現 Restarting nginx daemon: nginxnginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed (2: No such file or directory) nginx not running 的錯誤,通過 nginx -c 參數指定配置文件即可解決

        /usr/local/nginx/sbin/nginx?-c?/usr/local/nginx/conf/nginx.conf  
        

        如果服務啟動中出現 nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) 的錯誤,可以先通過 service nginx stop 停止服務,再啟動就好。

        配置 nginx 全局可用

        當你每次改了 nginx.conf 配置文件的內容都需要重新到 nginx 啟動目錄去執行命令,或者通過 -p 參數指向特定目錄,會不會感覺很麻煩?

        例如:直接執行 nginx \-s reload 會報錯 -bash: nginx: command not found,需要到 /usr/local/nginx/sbin 目錄下面去執行,并且是執行 ./nginx \-s reload 。

        這里有兩種方式可以解決,一種是通過腳本對 nginx 命令包裝,這里介紹另外一種比較簡單:通過把 nginx 配置到環境變量里,用 nginx 執行指令即可。步驟如下:

        1、編輯 /etc/profile

        vi?/etc/profile  
        

        2、在最后一行添加配置,:wq 保存

        export?PATH=$PATH:/usr/local/nginx/sbin  
        

        3、使配置立即生效

        source?/etc/profile  
        

        這樣就可以愉快的直接在全局使用 nginx 命令了。

        nginx 常用功能

        反向代理

        我們最常說的反向代理的是通過反向代理解決跨域問題。

        其實反向代理還可以用來控制緩存(代理緩存 proxy cache),進行訪問控制等等,以及后面說的負載均衡其實都是通過反向代理來實現的。

        server?{  
        ????listen????8080;  
        ????????#?用戶訪問?ip:8080/test?下的所有路徑代理到?github  
        ????????location?/test?{  
        ?????????proxy_pass???https://github.com;  
        ????????}  
        
        ????????#?所有?/api?下的接口訪問都代理到本地的?8888?端口  
        ????????#?例如你本地運行的?java?服務的端口是?8888,接口都是以?/api?開頭  
        ????????location?/api?{  
        ????????????proxy_pass???http://127.0.0.1:8888;  
        ????????}  
        
        }  
        

        訪問控制

        server?{  
        ???location?~?^/index.html?{  
        ???????#?匹配?index.html?頁面?除了?127.0.0.1?以外都可以訪問  
        ???????deny?192.168.1.1;  
        ???????deny?192.168.1.2;  
        ???????allow?all;  
        ?}  
        }  
        

        上面的命令表示禁止 192.168.1.1 和 192.168.1.2 兩個 ip 訪問,其它全部允許。從上到下的順序,匹配到了便跳出,可以按你的需求設置。

        負載均衡

        通過負載均衡充利用服務器資源,nginx 目前支持自帶 4 種負載均衡策略,還有 2 種常用的第三方策略。

        輪詢策略(默認)

        每個請求按時間順序逐一分配到不同的后端服務器,如果有后端服務器掛掉,能自動剔除。但是如果其中某一臺服務器壓力太大,出現延遲,會影響所有分配在這臺服務器下的用戶。

        http?{  
        ????upstream?test.com?{  
        ????????server?192.168.1.12:8887;  
        ????????server?192.168.1.13:8888;  
        ????}  
        ????server?{  
        ????????location?/api?{  
        ????????????proxy_pass??http://test.com;  
        ????????}  
        ????}  
        }  
        

        根據服務器權重

        例如要配置:10 次請求中大概 1 次訪問到 8888 端口,9 次訪問到 8887 端口:

        http?{  
        ????upstream?test.com?{  
        ????????server?192.168.1.12:8887?weight=9;  
        ????????server?192.168.1.13:8888?weight=1;  
        ????}  
        ????server?{  
        ????????location?/api?{  
        ????????????proxy_pass??http://test.com;  
        ????????}  
        ????}  
        }  
        

        客戶端 ip 綁定(ip_hash)

        來自同一個 ip 的請求永遠只分配一臺服務器,有效解決了動態網頁存在的 session 共享問題。例如:比如把登錄信息保存到了 session 中,那么跳轉到另外一臺服務器的時候就需要重新登錄了。

        所以很多時候我們需要一個客戶只訪問一個服務器,那么就需要用 ip_hash 了。

        http?{  
        ????upstream?test.com?{  
        ?????ip_hash;  
        ????????server?192.168.1.12:8887;  
        ????????server?192.168.1.13:8888;  
        ????}  
        ????server?{  
        ????????location?/api?{  
        ????????????proxy_pass??http://test.com;  
        ????????}  
        ????}  
        }  
        

        最小連接數策略

        將請求優先分配給壓力較小的服務器,它可以平衡每個隊列的長度,并避免向壓力大的服務器添加更多的請求。

        http?{  
        ????upstream?test.com?{  
        ?????least_conn;  
        ????????server?192.168.1.12:8887;  
        ????????server?192.168.1.13:8888;  
        ????}  
        ????server?{  
        ????????location?/api?{  
        ????????????proxy_pass??http://test.com;  
        ????????}  
        ????}  
        }  
        

        最快響應時間策略(依賴于第三方 NGINX Plus)

        依賴于 NGINX Plus,優先分配給響應時間最短的服務器。

        http?{  
        ????upstream?test.com?{  
        ?????fair;  
        ????????server?192.168.1.12:8887;  
        ????????server?192.168.1.13:8888;  
        ????}  
        ????server?{  
        ????????location?/api?{  
        ????????????proxy_pass??http://test.com;  
        ????????}  
        ????}  
        }  
        

        按訪問 url 的 hash 結果(第三方)

        按訪問 url 的 hash 結果來分配請求,使每個 url 定向到同一個后端服務器,后端服務器為緩存時比較有效。在 upstream 中加入 hash 語句,server 語句中不能寫入 weight 等其他的參數,hash_method 是使用的 hash 算法

        http?{  
        ????upstream?test.com?{  
        ?????hash?$request_uri;  
        ?????hash_method?crc32;  
        ?????server?192.168.1.12:8887;  
        ?????server?192.168.1.13:8888;  
        ????}  
        ????server?{  
        ????????location?/api?{  
        ????????????proxy_pass??http://test.com;  
        ????????}  
        ????}  
        }  
        

        采用 HAproxy 的 loadbalance uri 或者 nginx 的 upstream_hash 模塊,都可以做到針對 url 進行哈希算法式的負載均衡轉發。

        gzip 壓縮

        開啟 gzip 壓縮可以大幅減少 http 傳輸過程中文件的大小,可以極大的提高網站的訪問速度,基本是必不可少的優化操作:

        gzip??on;?#?開啟gzip?壓縮  
        #?gzip_types  
        #?gzip_static?on;  
        #?gzip_proxied?expired?no-cache?no-store?private?auth;  
        #?gzip_buffers?16?8k;  
        gzip_min_length?1k;  
        gzip_comp_level?4;  
        gzip_http_version?1.0;  
        gzip_vary?off;  
        gzip_disable?"MSIE?[1-6]\.";  
        

        解釋一下:

        1. gzip_types:要采用 gzip 壓縮的 MIME 文件類型,其中 text/html 被系統強制啟用;
        2. gzip_static:默認 off,該模塊啟用后,Nginx 首先檢查是否存在請求靜態文件的 gz 結尾的文件,如果有則直接返回該 .gz 文件內容;
        3. gzip_proxied:默認 off,nginx 做為反向代理時啟用,用于設置啟用或禁用從代理服務器上收到相應內容 gzip 壓縮;
        4. gzip_buffers:獲取多少內存用于緩存壓縮結果,16 8k 表示以 8k*16 為單位獲得;
        5. gzip_min_length:允許壓縮的頁面最小字節數,頁面字節數從 header 頭中的 Content-Length 中進行獲取。默認值是 0,不管頁面多大都壓縮。建議設置成大于 1k 的字節數,小于 1k 可能會越壓越大;
        6. gzip_comp_level:gzip 壓縮比,壓縮級別是 1-9,1 壓縮級別最低,9 最高,級別越高壓縮率越大,壓縮時間越長,建議 4-6;
        7. gzip_http_version:默認 1.1,啟用 gzip 所需的 HTTP 最低版本;
        8. gzip_vary:用于在響應消息頭中添加 Vary:Accept-Encoding,使代理服務器根據請求頭中的 Accept-Encoding 識別是否啟用 gzip 壓縮;
        9. gzip_disable 指定哪些不需要 gzip 壓縮的瀏覽器

        其中第 2 點,普遍是結合前端打包的時候打包成 gzip 文件后部署到服務器上,這樣服務器就可以直接使用 gzip 的文件了,并且可以把壓縮比例提高,這樣 nginx 就不用壓縮,也就不會影響速度。一般不追求極致的情況下,前端不用做任何配置就可以使用啦\~

        附前端 webpack 開啟 gzip 壓縮配置,在 vue-cli3 的 vue.config.js 配置文件中:

        const?CompressionWebpackPlugin?=?require('compression-webpack-plugin')  
        
        module.exports?=?{  
        ??//?gzip?配置  
        ??configureWebpack:?config?=>?{  
        ????if?(process.env.NODE_ENV?===?'production')?{  
        ??????//?生產環境  
        ??????return?{  
        ????????plugins:?[new?CompressionWebpackPlugin({  
        ??????????test:?/\.js|\.html|\.css/,????//?匹配文件名  
        ??????????threshold:?1024,???????????????//?文件壓縮閾值,對超過?1k?的進行壓縮  
        ??????????deleteOriginalAssets:?false?????//?是否刪除源文件  
        ????????})]  
        ??????}  
        ????}  
        ??},  
        ??...  
        }  
        

        HTTP 服務器

        nginx 本身也是一個靜態資源的服務器,當只有靜態資源的時候,就可以使用 nginx 來做服務器:

        server?{  
        ??listen???????80;  
        ??server_name??localhost;  
        
        ??location?/?{  
        ??????root???/usr/local/app;  
        ??????index??index.html;  
        ??}  
        }  
        

        這樣如果訪問 http://ip 就會默認訪問到 /usr/local/app 目錄下面的 index.html,如果一個網站只是靜態頁面的話,那么就可以通過這種方式來實現部署,比如一個靜態官網。

        動靜分離

        就是把動態和靜態的請求分開。方式主要有兩種:

        • 一種是純粹把靜態文件獨立成單獨的域名,放在獨立的服務器上,也是目前主流推崇的方案
        • 一種方法就是動態跟靜態文件混合在一起發布, 通過 nginx 配置來分開
        #?所有靜態請求都由nginx處理,存放目錄為?html  
        location?~?\.(gif|jpg|jpeg|png|bmp|swf|css|js)?{  
        ????root????/usr/local/resource;  
        ????expires?????10h;?#?設置過期時間為10小時  
        }  
        
        #?所有動態請求都轉發給?tomcat?處理  
        location?~?\.(jsp|do)?{  
        ????proxy_pass??127.0.0.1:8888;  
        }  
        

        注意上面設置了 expires,當 nginx 設置了 expires 后,例如設置為:expires 10d; 那么,所在的 location 或 if 的內容,用戶在 10 天內請求的時候,都只會訪問瀏覽器中的緩存,而不會去請求 nginx 。

        請求限制

        對于大流量惡意的訪問,會造成帶寬的浪費,給服務器增加壓力??梢酝ㄟ^ nginx 對于同一 IP 的連接數以及并發數進行限制。合理的控制還可以用來防止 DDos 和 CC 攻擊。

        關于請求限制主要使用 nginx 默認集成的 2 個模塊:

        • limit_conn_module 連接頻率限制模塊
        • limit_req_module 請求頻率限制模塊

        涉及到的配置主要是:

        • limit_req_zone 限制請求數
        • limit_conn_zone 限制并發連接數

        通過 limit_req_zone 限制請求數

        http{  
        ????limit_conn_zone?$binary_remote_addrzone=limit:10m;?//?設置共享內存空間大  
        ????server{  
        ?????location?/{  
        ??????????? limit_conn addr 5;?#?同一用戶地址同一時間只允許有5個連接。  
        ????????}  
        ????}  
        }  
        

        如果共享內存空間被耗盡,服務器將會對后續所有的請求返回 503 (Service Temporarily Unavailable) 錯誤。

        當多個 limit_conn_zone 指令被配置時,所有的連接數限制都會生效。比如,下面配置不僅會限制單一 IP 來源的連接數,同時也會限制單一虛擬服務器的總連接數:

        limit_conn_zone?binary_remote_addr?zone=perip:10m;  
        limit_conn_zone?server_name?zone=perserver:10m;  
        server?{  
        ????limit_conn?perip?10;?#?限制每個?ip?連接到服務器的數量  
        ????limit_conn?perserver?2000;?#?限制連接到服務器的總數  
        }  
        

        通過 limit_conn_zone 限制并發連接數

        limit_req_zone?$binary_remote_addr?zone=creq:10?mrate=10r/s;  
        server{  
        ????location?/{  
        ????????limit_req?zone=creq?burst=5;  
        ????}  
        }  
        

        限制平均每秒不超過一個請求,同時允許超過頻率限制的請求數不多于 5 個。如果不希望超過的請求被延遲,可以用 nodelay 參數,如:

        limit_req zone=creq burst=5 nodelay;
        

        這里只是簡單講講,讓大家有這個概念,配置的時候可以深入去找找資料。

        正向代理

        正向代理,意思是一個位于客戶端和原始服務器(origin server)之間的服務器,為了從原始服務器取得內容,客戶端向代理發送一個請求并指定目標(原始服務器),然后代理向原始服務器轉交請求并將獲得的內容返回給客戶端??蛻舳瞬拍苁褂谜虼?,比如我們使用的 VPN 服務就是正向代理,直觀區別:

        配置正向代理:

        resolver?8.8.8.8?#?谷歌的域名解析地址  
        server?{  
        ????resolver_timeout?5s;?//?設超時時間  
        ????location?/?{  
        ????????#?當客戶端請求我的時候,我會把請求轉發給它  
        ????????#?host?要訪問的主機名?request_uri?請求路徑  
        ????????proxy_pass?http://hostrequest_uri;  
        ????}  
        }  
        

        正向代理的對象是客戶端,服務器端看不到真正的客戶端。

        圖片防盜鏈

        server?{  
        ????listen???????80;  
        ????server_name??*.test;  
        
        ????#?圖片防盜鏈  
        ????location?~*?\.(gif|jpg|jpeg|png|bmp|swf)?{  
        ????????valid_referers?none?blocked?server_names?~\.google\.?~\.baidu\.?*.qq.com;??#?只允許本機?IP?外鏈引用,將百度和谷歌也加入白名單有利于?SEO  
        ????????if?(invalid_referer){  
        ????????????return?403;  
        ????????}  
        ????}  
        }  
        

        以上設置就能防止其它網站利用外鏈訪問我們的圖片,有利于節省流量

        適配 PC 或移動設備

        根據用戶設備不同返回不同樣式的站點,以前經常使用的是純前端的自適應布局,但是復雜的網站并不適合響應式,無論是復雜性和易用性上面還是不如分開編寫的好,比如我們常見的淘寶、京東。

        根據用戶請求的 user-agent 來判斷是返回 PC 還是 H5 站點:

        server?{  
        ????listen?80;  
        ????server_name?test.com;  
        
        ????location?/?{  
        ?????root??/usr/local/app/pc;?#?pc?的?html?路徑  
        ????????if?($http_user_agent?~*?'(Android|webOS|iPhone|iPod|BlackBerry)')?{  
        ????????????root?/usr/local/app/mobile;?#?mobile?的?html?路徑  
        ????????}  
        ????????index?index.html;  
        ????}  
        }  
        

        設置二級域名

        新建一個 server 即可:

        server?{  
        ????listen?80;  
        ????server_name?admin.test.com;?//?二級域名  
        
        ????location?/?{  
        ????????root??/usr/local/app/admin;?#?二級域名的?html?路徑  
        ????????index?index.html;  
        ????}  
        }  
        

        配置 HTTPS

        這里我使用的是 certbot 免費證書,但申請一次有效期只有 3 個月(好像可以用 crontab 嘗試配置自動續期,我暫時沒試過):

        先安裝 certbot

        wget?https://dl.eff.org/certbot-auto  
        chmod?a+x?certbot-auto  
        

        申請證書(注意:需要把要申請證書的域名先解析到這臺服務器上,才能申請):

        sudo?./certbot-auto?certonly?--standalone?--email?admin@abc.com?-d?test.com?-d?www.test.com  
        

        執行上面指令,按提示操作。

        Certbot 會啟動一個臨時服務器來完成驗證(會占用 80 端口或 443 端口,因此需要暫時關閉 Web 服務器),然后 Certbot 會把證書以文件的形式保存,包括完整的證書鏈文件和私鑰文件。

        文件保存在 /etc/letsencrypt/live/ 下面的域名目錄下。

        修改 nginx 配置:

        server{  
        ????listen?443?ssl?http2;?//?這里還啟用了?http/2.0  
        
        ????ssl_certificate?/etc/letsencrypt/live/test.com/fullchain.pem;?#?證書文件地址  
        ????ssl_certificate_key?/etc/letsencrypt/live/test.com/privkey.pem;?#?私鑰文件地址  
        
        ????server_name?test.com?www.test.com;?//?證書綁定的域名  
        }  
        

        配置 HTTP 轉 HTTPS

        server?{  
        ????listen??????80;  
        ????server_name?test.com?www.test.com;  
        
        ????#?單域名重定向  
        ????if?(host?=?'www.sherlocked93.club'){  
        ????????return?301?https://www.sherlocked93.clubrequest_uri;  
        ????}  
        
        ????#?全局非?https?協議時重定向  
        ????if?(scheme?!=?'https')?{  
        ????????return?301?https://server_namerequest_uri;  
        ????}  
        
        ????#?或者全部重定向  
        ????return?301?https://server_name$request_uri;  
        }  
        
        

        以上配置選擇自己需要的一條即可,不用全部加。

        單頁面項目 history 路由配置

        server?{  
        ????listen???????80;  
        ????server_name??fe.sherlocked93.club;  
        
        ????location?/?{  
        ????????root???????/usr/local/app/dist;??#?vue?打包后的文件夾  
        ????????index??????index.html?index.htm;  
        ????????try_files??uri?uri/?/index.html?@rewrites;?#?默認目錄下的?index.html,如果都不存在則重定向  
        
        ????????expires?-1;??????????????????????????#?首頁一般沒有強制緩存  
        ????????add_header?Cache-Control?no-cache;  
        ????}  
        
        ????location?@rewrites?{?//?重定向設置  
        ????????rewrite?^(.+)$?/index.html?break;  
        ????}  
        }  
        

        vue-router 官網只有一句話 try_files uriuri/ /index.html; ,而上面做了一些重定向處理。

        配置高可用集群(雙機熱備)

        當主 nginx 服務器宕機之后,切換到備份的 nginx 服務器

        首先安裝 keepalived:

        yum?install?keepalived?-y  
        

        然后編輯 /etc/keepalived/keepalived.conf 配置文件,并在配置文件中增加 vrrp_script 定義一個外圍檢測機制,并在 vrrp_instance 中通過定義 track_script 來追蹤腳本執行過程,實現節點轉移:

        global_defs{  
        ???notification_email?{  
        ????????cchroot@gmail.com  
        ???}  
        ???notification_email_from?test@firewall.loc  
        ???smtp_server?127.0.0.1  
        ???smtp_connect_timeout?30?//?上面都是郵件配置  
        ???router_id?LVS_DEVEL?????//?當前服務器名字,用?hostname?命令來查看  
        }  
        vrrp_script?chk_maintainace?{?//?檢測機制的腳本名稱為chk_maintainace  
        ????script?"[[?-e/etc/keepalived/down?]]?&&?exit?1?||?exit?0"?//?可以是腳本路徑或腳本命令  
        ????//?script?"/etc/keepalived/nginx_check.sh"????//?比如這樣的腳本路徑  
        ????interval?2??//?每隔2秒檢測一次  
        ????weight?-20??//?當腳本執行成立,那么把當前服務器優先級改為-20  
        }  
        vrrp_instanceVI_1?{???//?每一個vrrp_instance就是定義一個虛擬路由器  
        ????state?MASTER??????//?主機為MASTER,備用機為BACKUP  
        ????interface?eth0????//?網卡名字,可以從ifconfig中查找  
        ????virtual_router_id?51?//?虛擬路由的id號,一般小于255,主備機id需要一樣  
        ????priority?100??????//?優先級,master的優先級比backup的大  
        ????advert_int?1??????//?默認心跳間隔  
        ????authentication?{??//?認證機制  
        ????????auth_type?PASS  
        ????????auth_pass?1111???//?密碼  
        ????}  
        ????virtual_ipaddress?{??//?虛擬地址vip  
        ???????172.16.2.8  
        ????}  
        }  
        

        其中檢測腳本 nginx_check.sh,這里提供一個:

        #!/bin/bash  
        A=`ps?-C?nginx?--no-header?|?wc?-l`  
        if?[?$A?-eq?0?];then  
        ????/usr/sbin/nginx?#?嘗試重新啟動nginx  
        ????sleep?2?????????#?睡眠2秒  
        ????if?[?`ps?-C?nginx?--no-header?|?wc?-l`?-eq?0?];then  
        ??????? killall keepalived #?啟動失敗,將keepalived服務殺死。將vip漂移到其它備份節點  
        ????fi  
        fi  
        

        復制一份到備份服務器,備份 nginx 的配置要將 state 后改為 BACKUP,priority 改為比主機小。設置完畢后各自 service keepalived start 啟動,經過訪問成功之后,可以把 Master 機的 keepalived 停掉,此時 Master 機就不再是主機了 service keepalived stop,看訪問虛擬 IP 時是否能夠自動切換到備機 ip addr。

        再次啟動 Master 的 keepalived,此時 vip 又變到了主機上。

        配置高可用集群的內容來源于:Nginx 從入門到實踐,萬字詳解!

        其它功能和技巧

        代理緩存

        nginx 的 http_proxy 模塊,提供類似于 Squid 的緩存功能,使用 proxy_cache_path 來配置。

        nginx 可以對訪問過的內容在 nginx 服務器本地建立副本,這樣在一段時間內再次訪問該數據,就不需要通過 nginx 服務器再次向后端服務器發出請求,減小數據傳輸延遲,提高訪問速度:

        proxy_cache_path?usr/local/cache?levels=1:2?keys_zone=my_cache:10m;  
        
        server?{  
        ??listen???????80;  
        ??server_name??test.com;  
        
        ??location?/?{  
        ??????proxy_cache?my_cache;  
        ??????proxy_pass?http://127.0.0.1:8888;  
        ??????proxy_set_header?Host?$host;  
        ??}  
        }  
        

        上面的配置表示:nginx 提供一塊 10 M 的內存用于緩存,名字為 my_cache, levels 等級為 1:2,緩存存放的路徑為 usr/local/cache。

        訪問日志

        訪問日志默認是注釋的狀態,需要可以打開和進行更詳細的配置,一下是 nginx 的默認配置:

        http?{  
        ????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;  
        }  
        

        錯誤日志

        錯誤日志放在 main 全局區塊中,童鞋們打開 nginx.conf 就可以看見在配置文件中和下面一樣的代碼了:

        #error_log??logs/error.log;  
        #error_log??logs/error.log??notice;  
        #error_log??logs/error.log??info;  
        

        nginx 錯誤日志默認配置為:

        error_log logs/error.log error;
        

        靜態資源服務器

        server?{  
        ????listen???????80;  
        ????server_name??static.bin;  
        ????charset?utf-8;????#?防止中文文件名亂碼  
        
        ????location?/download?{  
        ????????alias???????????/usr/share/nginx/static;??#?靜態資源目錄  
        
        ????????autoindex???????????????on;????#?開啟靜態資源列目錄,瀏覽目錄權限  
        ????????autoindex_exact_size????off;???# on(默認)顯示文件的確切大小,單位是byte;off顯示文件大概大小,單位KB、MB、GB  
        ????????autoindex_localtime?????off;???# off(默認)時顯示的文件時間為GMT時間;on顯示的文件時間為服務器時間  
        ????}  
        }  
        

        禁止指定 user_agent

        nginx 可以禁止指定的瀏覽器和爬蟲框架訪問:

        #?http_user_agent?為瀏覽器標識  
        #?禁止?user_agent?為baidu、360和sohu,~*表示不區分大小寫匹配  
        if?(http_user_agent?~*?'baidu|360|sohu')?{  
        ????return?404;  
        }  
        
        #?禁止?Scrapy?等工具的抓取  
        if?(http_user_agent?~*?(Scrapy|Curl|HttpClient))?{  
        ????return?403;  
        `
        
        #### 請求過濾
        
        **根據請求類型過濾**
        
        `#?非指定請求全返回?403  
        if?(?request_method?!~?^(GET|POST|HEAD)?)?{  
        ????return?403;  
        }  
        

        根據狀態碼過濾

        error_page?502?503?/50x.html;  
        location?=?/50x.html?{  
        ????root?/usr/share/nginx/html;  
        }  
        

        這樣實際上是一個內部跳轉,當訪問出現 502、503 的時候就能返回 50x.html 中的內容,這里需要注意是否可以找到 50x.html 頁面,所以加了個 location 保證找到你自定義的 50x 頁面。

        根據 URL 名稱過濾

        if?(host?=?zy.com'?)?{  
        ?????#其中?1是取自regex部分()里的內容,匹配成功后跳轉到的URL。  
        ???? rewrite ^/(.*)? http://www.zy.com/1  permanent;  
        }  
        
        location?/test?{  
        ????//?/test?全部重定向到首頁  
        ????rewrite??^(.*)$?/index.html??redirect;  
        }  
        

        ab 命令

        ab 命令全稱為:Apache bench,是 Apache 自帶的壓力測試工具,也可以測試 Nginx、IIS 等其他 Web 服務器:

        • -n 總共的請求數
        • -c 并發的請求數
        • -t 測試所進行的最大秒數,默認值 為 50000
        • -p 包含了需要的 POST 的數據文件
        • -T POST 數據所使用的 Content-type 頭信息
        ab -n 1000?-c 5000 http://127.0.0.1/?#?每次發送1000并發的請求數,請求數總數為5000。  
        

        測試前需要安裝 httpd-tools:yum install httpd-tools

        泛域名路徑分離

        這是一個非常實用的技能,經常有時候我們可能需要配置一些二級或者三級域名,希望通過 nginx 自動指向對應目錄,比如:

        1. test1.doc.test.club 自動指向 /usr/local/html/doc/test1 服務器地址;
        2. test2.doc.test.club 自動指向 /usr/local/html/doc/test2 服務器地址;
        server?{  
        ????listen???????80;  
        ????server_name??~^([\w-]+)\.doc\.test\.club;  
        
        ????root?/usr/local/html/doc/1;  
        }  
        

        泛域名轉發

        和之前的功能類似,有時候我們希望把二級或者三級域名鏈接重寫到我們希望的路徑,讓后端就可以根據路由解析不同的規則:

        1. test1.serv.test.club/api\?name=a 自動轉發到 127.0.0.1:8080/test1/api\?name=a
        2. test2.serv.test.club/api\?name=a 自動轉發到 127.0.0.1:8080/test2/api\?name=a
        server?{  
        ????listen???????80;  
        ????server_name?~^([\w-]+)\.serv\.test\.club;  
        
        ????location?/?{  
        ????????proxy_set_header????????X-Real-IP?remote_addr;  
        ????????proxy_set_header????????X-Forwarded-For?proxy_add_x_forwarded_for;  
        ????????proxy_set_header????????Host?http_host;  
        ????????proxy_set_header????????X-NginX-Proxy?true;  
        ????????proxy_pass??????????????http://127.0.0.1:8080/1request_uri;  
        ????}  
        }  
        

        常見問題

        nginx 中怎么設置變量

        或許你不知道,nginx 的配置文件使用的是一門微型的編程語言。既然是編程語言,一般也就少不了“變量”這種東西,但是在 nginx 配置中,變量只能存放一種類型的值,因為也只存在一種類型的值,那就是字符串。

        例如我們在 nginx.conf 中有這樣一行配置:

        set?$name?"chroot";  
        

        上面使用了 set 配置指令對變量 $name 進行了賦值操作,把 “chroot” 賦值給了 $name。nginx 變量名前面有一個 $ 符號,這是記法上的要求。所有的 Nginx 變量在 Nginx 配置文件中引用時都須帶上 $ 前綴。這種表示方法和 Perl、PHP 這些語言是相似的。

        這種表示方法的用處在哪里呢,那就是可以直接把變量嵌入到字符串常量中以構造出新的字符串,例如你需要進行一個字符串拼接:

        server?{  
        ??listen???????80;  
        ??server_name??test.com;  
        
        ??location?/?{  
        ?????set?temp?hello;  
        ?????return?"temp?world";  
        ??}  
        }  
        

        以上當匹配成功的時候就會返回字符串 “hello world” 了。需要注意的是,當引用的變量名之后緊跟著變量名的構成字符時(比如后跟字母、數字以及下劃線),我們就需要使用特別的記法來消除歧義,例如:

        server?{  
        ??listen???????80;  
        ??server_name??test.com;  
        
        ??location?/?{  
        ?????set?temp?"hello?";  
        ?????return?"{temp}world";  
        ??}  
        }  
        

        這里,我們在配置指令的參數值中引用變量 $temp 的時候,后面緊跟著 world 這個單詞,所以如果直接寫作 "$tempworld" 則 nginx 的計算引擎會將之識別為引用了變量 $tempworld. 為了解決這個問題,nginx 的字符串支持使用花括號在 $ 之后把變量名圍起來,比如這里的 ${temp},所以 上面這個例子返回的還是 “hello world”:

        $?curl?'http://test.com/'  
        ????hello?world  
        

        還需要注意的是,若是想輸出 $ 符號本身,可以這樣做:

        geo?dollar?{  
        ????default?"";  
        }  
        server?{  
        ????listen???????80;  
        ????server_name??test.com;  
        
        ????location?/?{  
        ????????set?temp?"hello?";  
        ????????return?"{temp}world:?$dollar";  
        ????}  
        }  
        

        上面用到了標準模塊 ngx_geo 提供的配置指令 geo 來為變量 $dollar 賦予字符串 "$" ,這樣,這里的返回值就是 “hello world: \$” 了。

        附 nginx 內置預定義變量

        按字母順序,變量名與對應定義:

        • $arg_PARAMETER #GET 請求中變量名 PARAMETER 參數的值
        • $args #這個變量等于 GET 請求中的參數,例如,foo=123\&bar=blahblah;這個變量可以被修改
        • $binary_remote_addr* #二進制碼形式的客戶端地址
        • $body_bytes_sent #傳送頁面的字節數
        • $content_length #請求頭中的 Content-length 字段
        • $content_type #請求頭中的 Content-Type 字段
        • $cookie_COOKIE #cookie COOKIE 的值
        • $document_root #當前請求在 root 指令中指定的值
        • $document_uri #與 \$uri 相同
        • $host* #請求中的主機頭(Host)字段,如果請求中的主機頭不可用或者空,則為處理請求的 server 名稱(處理請求的 server 的 server_name 指令的值)。值為小寫,不包含端口
        • $hostname #機器名使用 gethostname 系統調用的值
        • $http_HEADER #HTTP 請求頭中的內容,HEADER 為 HTTP 請求中的內容轉為小寫,-變為_(破折號變為下劃線),例如:$http_user_agent (Uaer-Agent 的值)
        • $sent_http_HEADER #HTTP 響應頭中的內容,HEADER 為 HTTP 響應中的內容轉為小寫,-變為_(破折號變為下劃線),例如:$sent_http_cache_control、$sent_http_content_type
        • $is_args #如果 \$args 設置,值為”\?”,否則為””
        • $limit_rate #這個變量可以限制連接速率
        • $nginx_version #當前運行的 nginx 版本號
        • $query_string #與 \$args 相同
        • $remote_addr #客戶端的 IP 地址
        • $remote_port #客戶端的端口
        • $remote_port #已經經過 Auth Basic Module 驗證的用戶名
        • $request_filename #當前連接請求的文件路徑,由 root 或 alias 指令與 URI 請求生成
        • $request_body #這個變量(0.7.58+)包含請求的主要信息。在使用 proxy_pass 或 fastcgi_pass 指令的 location 中比較有意義
        • $request_body_file #客戶端請求主體信息的臨時文件名
        • $request_completion #如果請求成功,設為”OK”;如果請求未完成或者不是一系列請求中最后一部分則設為空
        • $request_method #這個變量是客戶端請求的動作,通常為 GET 或 POST。包括 0.8.20 及之前的版本中,這個變量總為 main request 中的動作,如果當前請求是一個子請求,并不使用這個當前請求的動作
        • $request_uri #這個變量等于包含一些客戶端請求參數的原始 URI,它無法修改,請查看 \$uri 更改或重寫 URI
        • $scheme #所用的協議,例如 http 或者是 https,例如
        • $server_addr #服務器地址,在完成一次系統調用后可以確定這個值,如果要繞開系統調用,則必須在 listen 中指定地址并且使用 bind 參數
        • $server_name #服務器名稱
        • $server_port #請求到達服務器的端口號
        • $server_protocol #請求使用的協議,通常是 HTTP/1.0、HTTP/1.1 或 HTTP/2
        • $uri #請求中的當前 URI(不帶請求參數,參數位于 args ) , 不 同 于 瀏 覽 器 傳 遞 的 args),不同于瀏覽器傳遞的 args),不同于瀏覽器傳遞的 request_uri 的值,它可以通過內部重定向,或者使用 index 指令進行修改。不包括協議和主機名,例如 /foo/bar.html

        附 nginx 模塊

        nginx 模塊分類

        • 核心模塊:nginx 最基本最核心的服務,如進程管理、權限控制、日志記錄;
        • 標準 HTTP 模塊:nginx 服務器的標準 HTTP 功能;
        • 可選 HTTP 模塊:處理特殊的 HTTP 請求
        • 郵件服務模塊:郵件服務
        • 第三方模塊:作為擴展,完成特殊功能

        模塊清單

        核心模塊

        • ngx_core
        • ngx_errlog
        • ngx_conf
        • ngx_events
        • ngx_event_core
        • ngx_epll
        • ngx_regex

        標準 HTTP 模塊

        • ngx_http
        • ngx_http_core #配置端口,URI 分析,服務器相應錯誤處理,別名控制 (alias) 等
        • ngx_http_log #自定義 access 日志
        • ngx_http_upstream #定義一組服務器,可以接受來自 proxy, Fastcgi,Memcache 的重定向;主要用作負載均衡
        • ngx_http_static
        • ngx_http_autoindex #自動生成目錄列表
        • ngx_http_index #處理以/結尾的請求,如果沒有找到 index 頁,則看是否開啟了 random_index;如開啟,則用之,否則用 autoindex
        • ngx_http_auth_basic #基于 http 的身份認證 (auth_basic)
        • ngx_http_access #基于 IP 地址的訪問控制 (deny,allow)
        • ngx_http_limit_conn #限制來自客戶端的連接的響應和處理速率
        • ngx_http_limit_req #限制來自客戶端的請求的響應和處理速率
        • ngx_http_geo
        • ngx_http_map #創建任意的鍵值對變量
        • ngx_http_split_clients
        • ngx_http_referer #過濾 HTTP 頭中 Referer 為空的對象
        • ngx_http_rewrite #通過正則表達式重定向請求
        • ngx_http_proxy
        • ngx_http_fastcgi #支持 fastcgi
        • ngx_http_uwsgi
        • ngx_http_scgi
        • ngx_http_memcached
        • ngx_http_empty_gif #從內存創建一個 1×1 的透明 gif 圖片,可以快速調用
        • ngx_http_browser #解析 http 請求頭部的 User-Agent 值
        • ngx_http_charset #指定網頁編碼
        • ngx_http_upstream_ip_hash
        • ngx_http_upstream_least_conn
        • ngx_http_upstream_keepalive
        • ngx_http_write_filter
        • ngx_http_header_filter
        • ngx_http_chunked_filter
        • ngx_http_range_header
        • ngx_http_gzip_filter
        • ngx_http_postpone_filter
        • ngx_http_ssi_filter
        • ngx_http_charset_filter
        • ngx_http_userid_filter
        • ngx_http_headers_filter #設置 http 響應頭
        • ngx_http_copy_filter
        • ngx_http_range_body_filter
        • ngx_http_not_modified_filter

        可選 HTTP 模塊:

        • ngx_http_addition #在響應請求的頁面開始或者結尾添加文本信息
        • ngx_http_degradation #在低內存的情況下允許服務器返回 444 或者 204 錯誤
        • ngx_http_perl
        • ngx_http_flv #支持將 Flash 多媒體信息按照流文件傳輸,可以根據客戶端指定的開始位置返回 Flash
        • ngx_http_geoip #支持解析基于 GeoIP 數據庫的客戶端請求
        • ngx_google_perftools
        • ngx_http_gzip #gzip 壓縮請求的響應
        • ngx_http_gzip_static #搜索并使用預壓縮的以.gz 為后綴的文件代替一般文件響應客戶端請求
        • ngx_http_image_filter #支持改變 png,jpeg,gif 圖片的尺寸和旋轉方向
        • ngx_http_mp4 #支持.mp4,.m4v,.m4a 等多媒體信息按照流文件傳輸,常與 ngx_http_flv 一起使用
        • ngx_http_random_index #當收到 / 結尾的請求時,在指定目錄下隨機選擇一個文件作為 index
        • ngx_http_secure_link #支持對請求鏈接的有效性檢查
        • ngx_http_ssl #支持 https
        • ngx_http_stub_status
        • ngx_http_sub_module #使用指定的字符串替換響應中的信息
        • ngx_http_dav #支持 HTTP 和 WebDAV 協議中的 PUT/DELETE/MKCOL/COPY/MOVE 方法
        • ngx_http_xslt #將 XML 響應信息使用 XSLT 進行轉換

        郵件服務模塊:

        • ngx_mail_core
        • ngx_mail_pop3
        • ngx_mail_imap
        • ngx_mail_smtp
        • ngx_mail_auth_http
        • ngx_mail_proxy
        • ngx_mail_ssl

        第三方模塊

        • echo-nginx-module #支持在 nginx 配置文件中使用 echo/sleep/time/exec 等類 Shell 命令
        • memc-nginx-module
        • rds-json-nginx-module #使 nginx 支持 json 數據的處理
        • lua-nginx-module

        文章轉載:騰訊技術工程
        (版權歸原作者所有,侵刪)

        本文鏈接:http://www.abandonstatusquo.com/40021.html

        網友評論comments

        發表評論

        您的電子郵箱地址不會被公開。

        暫無評論

        Copyright ? 2012-2022 YUNWEIPAI.COM - 運維派 京ICP備16064699號-6
        掃二維碼
        掃二維碼
        返回頂部
        十分钟免费观看视频高清下载