Nginx 極簡教程(快速入門)

做者:dunwujavascript

github.com/dunwu/nginx-tutorialcss

(點擊便可跳轉閱讀)html

1. SpringBoot內容聚合前端

2. 面試題內容聚合java

3. 設計模式內容聚合node

4. 排序算法內容聚合linux

5. 多線程內容聚合nginx

Nginx 極簡教程

本項目是一個 Nginx 極簡教程,目的在於幫助新手快速入門 Nginx。git

示例Demo:github

https://github.com/dunwu/nginx-tutorial/tree/master/demos

Demo目錄中的示例模擬了工做中的一些經常使用實戰場景,而且均可以經過腳本一鍵式啓動,讓您能夠快速看到演示效果。

簡介

什麼是 Nginx?

Nginx (engine x) 是一款輕量級的 Web 服務器 、反向代理服務器及電子郵件(IMAP/POP3)代理服務器。

Nginx 極簡教程(快速入門)

什麼是反向代理?

反向代理(Reverse Proxy)方式是指以代理服務器來接受 internet 上的鏈接請求,而後將請求轉發給內部網絡上的服務器,並將從服務器上獲得的結果返回給 internet 上請求鏈接的客戶端,此時代理服務器對外就表現爲一個反向代理服務器。

Nginx 極簡教程(快速入門)

Nginx 入門

詳細安裝方法請參考:

https://github.com/dunwu/nginx-tutorial/blob/master/install-nginx.md

nginx 的使用比較簡單,就是幾條命令。

經常使用到的命令以下:

nginx -s stop       快速關閉Nginx,可能不保存相關信息,並迅速終止web服務。
nginx -s quit       平穩關閉Nginx,保存相關信息,有安排的結束web服務。
nginx -s reload     因改變了Nginx相關配置,須要從新加載配置而重載。
nginx -s reopen     從新打開日誌文件。
nginx -c filename   爲 Nginx 指定一個配置文件,來代替缺省的。
nginx -t            不運行,僅僅測試配置文件。nginx 將檢查配置文件的語法的正確性,並嘗試打開配置文件中所引用到的文件。
nginx -v            顯示 nginx 的版本。
nginx -V            顯示 nginx 的版本,編譯器版本和配置參數。

若是不想每次都敲命令,能夠在 nginx 安裝目錄下新添一個啓動批處理文件startup.bat,雙擊便可運行。內容以下:

@echo off
rem 若是啓動前已經啓動nginx並記錄下pid文件,會kill指定進程
nginx.exe -s stop

rem 測試配置文件語法正確性
nginx.exe -t -c conf/nginx.conf

rem 顯示版本信息
nginx.exe -v

rem 按照指定配置去啓動nginx
nginx.exe -c conf/nginx.conf

若是是運行在 Linux 下,寫一個 shell 腳本,大同小異。

Nginx 實戰

我始終認爲,各類開發工具的配置仍是結合實戰來說述,會讓人更易理解。

Http 反向代理

咱們先實現一個小目標:不考慮複雜的配置,僅僅是完成一個 http 反向代理。

nginx.conf 配置文件以下:

注:conf/nginx.conf 是 nginx 的默認配置文件。你也可使用 nginx -c 指定你的配置文件

#運行用戶
#user somebody;

#啓動進程,一般設置成和cpu的數量相等
worker_processes  1;

#全局錯誤日誌
error_log  D:/Tools/nginx-1.10.1/logs/error.log;
error_log  D:/Tools/nginx-1.10.1/logs/notice.log  notice;
error_log  D:/Tools/nginx-1.10.1/logs/info.log  info;

#PID文件,記錄當前啓動的nginx的進程ID
pid        D:/Tools/nginx-1.10.1/logs/nginx.pid;

#工做模式及鏈接數上限
events {
    worker_connections 1024;    #單個後臺worker process進程的最大併發連接數
}

#設定http服務器,利用它的反向代理功能提供負載均衡支持
http {
    #設定mime類型(郵件支持類型),類型由mime.types文件定義
    include       D:/Tools/nginx-1.10.1/conf/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    D:/Tools/nginx-1.10.1/logs/access.log main;
    rewrite_log     on;

    #sendfile 指令指定 nginx 是否調用 sendfile 函數(zero copy 方式)來輸出文件,對於普通應用,
    #必須設爲 on,若是用來進行下載等應用磁盤IO重負載應用,可設置爲 off,以平衡磁盤與網絡I/O處理速度,下降系統的uptime.
    sendfile        on;
    #tcp_nopush     on;

    #鏈接超時時間
    keepalive_timeout  120;
    tcp_nodelay        on;

    #gzip壓縮開關
    #gzip  on;

    #設定實際的服務器列表
    upstream zp_server1{
        server 127.0.0.1:8089;
    }

    #HTTP服務器
    server {
        #監聽80端口,80端口是知名端口號,用於HTTP協議
        listen       80;

        #定義使用www.xx.com訪問
        server_name  www.helloworld.com;

        #首頁
        index index.html

        #指向webapp的目錄
        root D:1_WorkspaceProjectgithubzpSpringNotesspring-securityspring-shirosrcmainwebapp;

        #編碼格式
        charset utf-8;

        #代理配置參數
        proxy_connect_timeout 180;
        proxy_send_timeout 180;
        proxy_read_timeout 180;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarder-For $remote_addr;

        #反向代理的路徑(和upstream綁定),location 後面設置映射的路徑
        location / {
            proxy_pass http://zp_server1;
        }

        #靜態文件,nginx本身處理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            root D:1_WorkspaceProjectgithubzpSpringNotesspring-securityspring-shirosrcmainwebappviews;
            #過時30天,靜態文件不怎麼更新,過時能夠設大一點,若是頻繁更新,則能夠設置得小一點。
            expires 30d;
        }

        #設定查看Nginx狀態的地址
        location /NginxStatus {
            stub_status           on;
            access_log            on;
            auth_basic            "NginxStatus";
            auth_basic_user_file  conf/htpasswd;
        }

        #禁止訪問 .htxxx 文件
        location ~ /.ht {
            deny all;
        }

        #錯誤處理頁面(可選擇性配置)
        #error_page   404              /404.html;
        #error_page   500 502 503 504  /50x.html;
        #location = /50x.html {
        #    root   html;
        #}
    }
}

好了,讓咱們來試試吧:

  1. 啓動 webapp,注意啓動綁定的端口要和 nginx 中的 upstream 設置的端口保持一致。

  2. 更改 host:在 C:WindowsSystem32driversetc 目錄下的 host 文件中添加一條 DNS 記錄127.0.0.1 www.helloworld.com

  3. 啓動前文中 startup.bat 的命令

  4. 在瀏覽器中訪問 www.helloworld.com,不出意外,已經能夠訪問了。

Https 反向代理

一些對安全性要求比較高的站點,可能會使用 HTTPS(一種使用 ssl 通訊標準的安全 HTTP 協議)。

這裏不科普 HTTP 協議和 SSL 標準。可是,使用 nginx 配置 https 須要知道幾點:

  • HTTPS 的固定端口號是 443,不一樣於 HTTP 的 80 端口

  • SSL 標準須要引入安全證書,因此在 nginx.conf 中你須要指定證書和它對應的 key

其餘和 http 反向代理基本同樣,只是在 Server 部分配置有些不一樣。

  #HTTP服務器
  server {
      #監聽443端口。443爲知名端口號,主要用於HTTPS協議
      listen       443 ssl;

      #定義使用www.xx.com訪問
      server_name  www.helloworld.com;

      #ssl證書文件位置(常見證書文件格式爲:crt/pem)
      ssl_certificate      cert.pem;
      #ssl證書key位置
      ssl_certificate_key  cert.key;

      #ssl配置參數(選擇性配置)
      ssl_session_cache    shared:SSL:1m;
      ssl_session_timeout  5m;
      #數字簽名,此處使用MD5
      ssl_ciphers  HIGH:!aNULL:!MD5;
      ssl_prefer_server_ciphers  on;

      location / {
          root   /root;
          index  index.html index.htm;
      }
  }

負載均衡

前面的例子中,代理僅僅指向一個服務器。

可是,網站在實際運營過程當中,大部分都是以集羣的方式運行,這時須要使用負載均衡來分流。nginx 也能夠實現簡單的負載均衡功能。

假設這樣一個應用場景:將應用部署在 192.168.1.11:80、192.168.1.12:80、192.168.1.13:80 三臺 linux 環境的服務器上。網站域名叫 www.helloworld.com,公網 IP 爲 192.168.1.11。在公網 IP 所在的服務器上部署 nginx,對全部請求作負載均衡處理(下面例子中使用的是加權輪詢策略)。

nginx.conf 配置以下:

http {
     #設定mime類型,類型由mime.type文件定義
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    #設定日誌格式
    access_log    /var/log/nginx/access.log;

    #設定負載均衡的服務器列表
    upstream load_balance_server {
        #weigth參數表示權值,權值越高被分配到的概率越大
        server 192.168.1.11:80   weight=5;
        server 192.168.1.12:80   weight=1;
        server 192.168.1.13:80   weight=6;
    }

   #HTTP服務器
   server {
        #偵聽80端口
        listen       80;

        #定義使用www.xx.com訪問
        server_name  www.helloworld.com;

        #對全部請求進行負載均衡請求
        location / {
            root        /root;                 #定義服務器的默認網站根目錄位置
            index       index.html index.htm;  #定義首頁索引文件的名稱
            proxy_pass  http://load_balance_server ;#請求轉向load_balance_server 定義的服務器列表

            #如下是一些反向代理的配置(可選擇性配置)
            #proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            #後端的Web服務器能夠經過X-Forwarded-For獲取用戶真實IP
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_connect_timeout 90;          #nginx跟後端服務器鏈接超時時間(代理鏈接超時)
            proxy_send_timeout 90;             #後端服務器數據回傳時間(代理髮送超時)
            proxy_read_timeout 90;             #鏈接成功後,後端服務器響應時間(代理接收超時)
            proxy_buffer_size 4k;              #設置代理服務器(nginx)保存用戶頭信息的緩衝區大小
            proxy_buffers 32k;               #proxy_buffers緩衝區,網頁平均在32k如下的話,這樣設置
            proxy_busy_buffers_size 64k;       #高負荷下緩衝大小(proxy_buffers*2)
            proxy_temp_file_write_size 64k;    #設定緩存文件夾大小,大於這個值,將從upstream服務器傳

            client_max_body_size 10m;          #容許客戶端請求的最大單文件字節數
            client_body_buffer_size 128k;      #緩衝區代理緩衝用戶端請求的最大字節數
        }
    }
}

負載均衡策略

Nginx 提供了多種負載均衡策略,讓咱們來一一瞭解一下:

負載均衡策略在各類分佈式系統中基本上原理一致,對於原理有興趣,不妨參考:

https://dunwu.github.io/javaweb/#/theory/load-balance

輪詢
upstream bck_testing_01 {
  # 默認全部服務器權重爲 1
  server 192.168.250.220:8080
  server 192.168.250.221:8080
  server 192.168.250.222:8080
}
加權輪詢
upstream bck_testing_01 {
  server 192.168.250.220:8080   weight=3
  server 192.168.250.221:8080              # default weight=1
  server 192.168.250.222:8080              # default weight=1
}
最少鏈接
upstream bck_testing_01 {
  least_conn;

  # with default weight for all (weight=1)
  server 192.168.250.220:8080
  server 192.168.250.221:8080
  server 192.168.250.222:8080
}
加權最少鏈接
upstream bck_testing_01 {
  least_conn;

  server 192.168.250.220:8080   weight=3
  server 192.168.250.221:8080              # default weight=1
  server 192.168.250.222:8080              # default weight=1
}
IP Hash
upstream bck_testing_01 {

  ip_hash;

  # with default weight for all (weight=1)
  server 192.168.250.220:8080
  server 192.168.250.221:8080
  server 192.168.250.222:8080

}
普通 Hash
upstream bck_testing_01 {

  hash $request_uri;

  # with default weight for all (weight=1)
  server 192.168.250.220:8080
  server 192.168.250.221:8080
  server 192.168.250.222:8080

}

網站有多個 webapp 的配置

當一個網站功能愈來愈豐富時,每每須要將一些功能相對獨立的模塊剝離出來,獨立維護。這樣的話,一般,會有多個 webapp。

舉個例子:假如 www.helloworld.com 站點有好幾個 webapp,finance(金融)、product(產品)、admin(用戶中心)。訪問這些應用的方式經過上下文(context)來進行區分:

www.helloworld.com/finance/

www.helloworld.com/product/

www.helloworld.com/admin/

咱們知道,http 的默認端口號是 80,若是在一臺服務器上同時啓動這 3 個 webapp 應用,都用 80 端口,確定是不成的。因此,這三個應用須要分別綁定不一樣的端口號。

那麼,問題來了,用戶在實際訪問 www.helloworld.com 站點時,訪問不一樣 webapp,總不會還帶着對應的端口號去訪問吧。因此,你再次須要用到反向代理來作處理。

配置也不難,來看看怎麼作吧:

http {
    #此處省略一些基本配置

    upstream product_server{
        server www.helloworld.com:8081;
    }

    upstream admin_server{
        server www.helloworld.com:8082;
    }

    upstream finance_server{
        server www.helloworld.com:8083;
    }

    server {
        #此處省略一些基本配置
        #默認指向product的server
        location / {
            proxy_pass http://product_server;
        }

        location /product/{
            proxy_pass http://product_server;
        }

        location /admin/ {
            proxy_pass http://admin_server;
        }

        location /finance/ {
            proxy_pass http://finance_server;
        }
    }
}

靜態站點

有時候,咱們須要配置靜態站點(即 html 文件和一堆靜態資源)。

舉例來講:若是全部的靜態資源都放在了 /app/dist 目錄下,咱們只須要在 nginx.conf 中指定首頁以及這個站點的 host 便可。

配置以下:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    gzip on;
    gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/javascript image/jpeg image/gif image/png;
    gzip_vary on;

    server {
        listen       80;
        server_name  static.zp.cn;

        location / {
            root /app/dist;
            index index.html;
            #轉發任何請求到 index.html
        }
    }
}

而後,添加 HOST:

127.0.0.1 static.zp.cn

此時,在本地瀏覽器訪問 static.zp.cn ,就能夠訪問靜態站點了。

搭建文件服務器

有時候,團隊須要歸檔一些數據或資料,那麼文件服務器必不可少。使用 Nginx 能夠很是快速便捷的搭建一個簡易的文件服務。

Nginx 中的配置要點:

  • 將 autoindex 開啓能夠顯示目錄,默認不開啓。

  • 將 autoindex_exact_size 開啓能夠顯示文件的大小。

  • 將 autoindex_localtime 開啓能夠顯示文件的修改時間。

  • root 用來設置開放爲文件服務的根路徑。

  • charset 設置爲 charset utf-8,gbk;,能夠避免中文亂碼問題(windows 服務器下設置後,依然亂碼,本人暫時沒有找到解決方法)。

一個最簡化的配置以下:

autoindex on;# 顯示目錄
autoindex_exact_size on;# 顯示文件大小
autoindex_localtime on;# 顯示文件時間

server {
    charset      utf-8,gbk; # windows 服務器下設置後,依然亂碼,暫時無解
    listen       9050 default_server;
    listen       [::]:9050 default_server;
    server_name  _;
    root         /share/fs;
}

解決跨域

web 領域開發中,常常採用先後端分離模式。這種模式下,前端和後端分別是獨立的 web 應用程序,例如:後端是 Java 程序,前端是 React 或 Vue 應用。

各自獨立的 web app 在互相訪問時,勢必存在跨域問題。解決跨域問題通常有兩種思路:

  1. CORS

在後端服務器設置 HTTP 響應頭,把你須要容許訪問的域名加入 Access-Control-Allow-Origin 中。

  1. jsonp

把後端根據請求,構造 json 數據,並返回,前端用 jsonp 跨域。

這兩種思路,本文不展開討論。

須要說明的是,nginx 根據第一種思路,也提供了一種解決跨域的解決方案。

舉例:www.helloworld.com 網站是由一個前端 app ,一個後端 app 組成的。前端端口號爲 9000, 後端端口號爲 8080。

前端和後端若是使用 http 進行交互時,請求會被拒絕,由於存在跨域問題。來看看,nginx 是怎麼解決的吧:

首先,在 enable-cors.conf 文件中設置 cors :

# allow origin list
set $ACAO '*';

# set single origin
if ($http_origin ~* (www.helloworld.com)$) {
  set $ACAO $http_origin;
}

if ($cors = "trueget") {
    add_header 'Access-Control-Allow-Origin' "$http_origin";
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}

if ($request_method = 'OPTIONS') {
  set $cors "${cors}options";
}

if ($request_method = 'GET') {
  set $cors "${cors}get";
}

if ($request_method = 'POST') {
  set $cors "${cors}post";
}

接下來,在你的服務器中 include enable-cors.conf 來引入跨域配置:

# ----------------------------------------------------
# 此文件爲項目 nginx 配置片斷
# 能夠直接在 nginx config 中 include(推薦)
# 或者 copy 到現有 nginx 中,自行配置
# www.helloworld.com 域名需配合 dns hosts 進行配置
# 其中,api 開啓了 cors,需配合本目錄下另外一份配置文件
# ----------------------------------------------------
upstream front_server{
  server www.helloworld.com:9000;
}
upstream api_server{
  server www.helloworld.com:8080;
}

server {
  listen       80;
  server_name  www.helloworld.com;

  location ~ ^/api/ {
    include enable-cors.conf;
    proxy_pass http://api_server;
    rewrite "^/api/(.*)$" /$1 break;
  }

  location ~ ^/ {
    proxy_pass http://front_server;
  }
}

到此,就完成了。

參考

http://tool.oschina.net/apidocs/apidoc?api=nginx-zhhttp://tengine.taobao.org/book/index.htmlhttps://github.com/trimstray/nginx-admins-handbookhttps://nginxconfig.io/

相關文章
相關標籤/搜索