超實用的 Nginx 極簡教程,覆蓋了常用場景
概述
什么是 Nginx?
Nginx (engine x) 是一款輕量級的 Web 服務器 、反向署理服務器及電子郵件(IMAP/POP3)署理服務器。
什么是反向署理?
反向署理(Reverse Proxy)方法是指以署理服務器來接受 internet 上的銜接懇求,然后將懇求轉發(fā)給內部網絡上的服務器,并將從服務器上得到的結果返回給 internet 上懇求銜接的客戶端,此時署理服務器對外就表現(xiàn)為一個反向署理服務器。
裝置與運用
裝置
具體裝置方法請參閱:Nginx 裝置
運用
nginx 的運用比較簡單,便是幾條指令。
常用到的指令如下:
nginx -s stop 快速封閉Nginx,或許不保存相關信息,并敏捷終止web服務。 nginx -s quit 平穩(wěn)封閉Nginx,保存相關信息,有安排的結束web服務。 nginx -s reload 因改變了Nginx相關裝備,需求從頭加載裝備而重載。 nginx -s reopen 從頭打開日志文件。 nginx -c filename 為 Nginx 指定一個裝備文件,來代替缺省的。 nginx -t 不運轉,而只是測驗裝備文件。nginx 將查看裝備文件的語法的正確性,并嘗試打開裝備文件中所引用到的文件。 nginx -v 顯現(xiàn) nginx 的版別。 nginx -V 顯現(xiàn) nginx 的版別,編譯器版別和裝備參數(shù)。
假設不想每次都敲指令,能夠在 nginx 裝置目錄下新添一個發(fā)動批處理文件startup.bat ,雙擊即可運轉。內容如下:
@echo off rem 假設發(fā)動前現(xiàn)已發(fā)動nginx并記載下pid文件,會kill指定進程 nginx.exe -s stop rem 測驗裝備文件語法正確性 nginx.exe -t -c conf/nginx.conf rem 顯現(xiàn)版別信息 nginx.exe -v rem 按照指定裝備去發(fā)動nginx nginx.exe -c conf/nginx.conf
假設是運轉在 Linux 下,寫一個 shell 腳本,迥然不同。
nginx 裝備實戰(zhàn)
我始終認為,各種開發(fā)工具的裝備還是結合實戰(zhàn)來講述,會讓人更易了解。
http 反向署理裝備
我們先完成一個小方針:不考慮復雜的裝備,只是是完成一個 http 反向署理。
nginx.conf 裝備文件如下:注:conf / nginx.conf 是 nginx 的默許裝備文件。你也能夠運用 nginx -c 指定你的裝備文件
#運轉用戶 #user somebody; #發(fā)動進程,一般設置成和cpu的數(shù)量相等 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文件,記載當前發(fā)動的nginx的進程ID pid D:/Tools/nginx-1.10.1/logs/nginx.pid; #工作形式及銜接數(shù)上限 events { worker_connections 1024; #單個后臺worker process進程的最大并發(fā)鏈接數(shù) } #設定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 函數(shù)(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 { #監(jiān)聽80端口,80端口是聞名端口號,用于HTTP協(xié)議 listen 80; #界說運用www.xx.com拜訪 server_name www.helloworld.com; #主頁 index index.html #指向webapp的目錄 root D:\01_Workspace\Project\github\zp\SpringNotes\spring-security\spring-shiro\src\main\webapp; #編碼格局 charset utf-8; #署理裝備參數(shù) 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; } #靜態(tài)文件,nginx自己處理 location ~ ^/(images|javascript|js|css|flash|media|static)/ { root D:\01_Workspace\Project\github\zp\SpringNotes\spring-security\spring-shiro\src\main\webapp\views; #過期30天,靜態(tài)文件不怎樣更新,過期能夠設大一點,假設頻頻更新,則能夠設置得小一點。 expires 30d; } #設定查看Nginx狀態(tài)的地址 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; #} } }
好了,讓我們來試試吧:
- 發(fā)動 webapp,注意發(fā)動綁定的端口要和 nginx 中的upstream設置的端口保持一致。
- 更改 host:在 C:\Windows\System32\drivers\etc 目錄下的 host 文件中增加一條 DNS 記載
127.0.0.1 www.helloworld.com
- 發(fā)動前文中 startup.bat 的指令
- 在瀏覽器中拜訪 www.helloworld.com,不出意外,現(xiàn)已能夠拜訪了。
負載均衡裝備
上一個比如中,署理只是指向一個服務器。
可是,網站在實踐運營過程中,八成都是有多臺服務器運轉著相同的 app,這時需求運用負載均衡來分流。
nginx 也能夠完成簡單的負載均衡功用。
假設這樣一個運用場景:將運用布置在 192.168.1.11:80、192.168.1.12:80、192.168.1.13:80 三臺 linux 環(huán)境的服務器上。網站域名叫 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參數(shù)表明權值,權值越高被分配到的幾率越大 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; #后端服務器數(shù)據(jù)回傳時刻(署理發(fā)送超時) proxy_read_timeout 90; #銜接成功后,后端服務器呼應時刻(署理接收超時) proxy_buffer_size 4k; #設置署理服務器(nginx)保存用戶頭信息的緩沖區(qū)巨細 proxy_buffers 4 32k; #proxy_buffers緩沖區(qū),網頁平均在32k以下的話,這樣設置 proxy_busy_buffers_size 64k; #高負荷下緩沖巨細(proxy_buffers*2) proxy_temp_file_write_size 64k; #設定緩存文件夾巨細,大于這個值,將從upstream服務器傳 client_max_body_size 10m; #允許客戶端懇求的最大單文件字節(jié)數(shù) client_body_buffer_size 128k; #緩沖區(qū)署理緩沖用戶端懇求的最大字節(jié)數(shù) } } }
網站有多個 webapp 的裝備
當一個網站功用越來越豐厚時,往往需求將一些功用相對獨立的模塊剝離出來,獨立維護。這樣的話,一般,會有多個 webapp。
舉個比如:假設 www.helloworld.com 站點有好幾個 webapp,finance(金融)、product(產品)、admin(用戶中心)。拜訪這些運用的方法通過上下文(context)來進行區(qū)別:
www.helloworld.com/finance/
www.helloworld.com/product/
www.helloworld.com/admin/
我們知道,http 的默許端口號是 80,假設在一臺服務器上同時發(fā)動這 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; } } }
https 反向署理裝備
一些對安全性要求比較高的站點,或許會運用 HTTPS(一種運用 ssl 通訊規(guī)范的安全 HTTP 協(xié)議)。
這里不科普 HTTP 協(xié)議和 SSL 規(guī)范。可是,運用 nginx 裝備 https 需求知道幾點:
- HTTPS 的固定端口號是 443,不同于 HTTP 的 80 端口
- SSL 規(guī)范需求引進安全證書,所以在 nginx.conf 中你需求指定證書和它對應的 key
其他和 http 反向署理根本一樣,只是在Server部分裝備有些不同。
#HTTP服務器 server { #監(jiān)聽443端口。443為聞名端口號,首要用于HTTPS協(xié)議 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裝備參數(shù)(選擇性裝備) ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; #數(shù)字簽名,此處運用MD5 ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location / { root /root; index index.html index.htm; } }
靜態(tài)站點裝備
有時候,我們需求裝備靜態(tài)站點(即 html 文件和一堆靜態(tài)資源)。
舉例來說:假設一切的靜態(tài)資源都放在了/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; #轉發(fā)任何懇求到 index.html } } }
然后,增加 HOST:
127.0.0.1 static.zp.cn
此時,在本地瀏覽器拜訪 static.zp.cn ,就能夠拜訪靜態(tài)站點了。
建立文件服務器
有時候,團隊需求歸檔一些數(shù)據(jù)或資料,那么文件服務器必不可少。運用 Nginx 能夠十分快速便捷的建立一個簡易的文件服務。
Nginx 中的裝備關鍵:
- 將 autoindex 敞開能夠顯現(xiàn)目錄,默許不敞開。
- 將 autoindex_exact_size 敞開能夠顯現(xiàn)文件的巨細。
- 將 autoindex_localtime 敞開能夠顯現(xiàn)文件的修正時刻。
- root 用來設置開放為文件服務的根途徑。
- charset 設置為charset utf-8,gbk;,能夠避免中文亂碼問題(windows 服務器下設置后,仍然亂碼,自己暫時沒有找到處理方法)。
一個最簡化的裝備如下:
autoindex on;# 顯現(xiàn)目錄 autoindex_exact_size on;# 顯現(xiàn)文件巨細 autoindex_localtime on;# 顯現(xiàn)文件時刻 server { charset utf-8,gbk; # windows 服務器下設置后,仍然亂碼,暫時無解 listen 9050 default_server; listen [::]:9050 default_server; server_name _; root /share/fs; }
跨域處理方案
web 領域開發(fā)中,常常采用前后端別離形式。這種形式下,前端和后端分別是獨立的 web 運用程序,例如:后端是 Java 程序,前端是 React 或 Vue 運用。
各自獨立的 web app 在互相拜訪時,勢必存在跨域問題。處理跨域問題一般有兩種思路:
- CORS
在后端服務器設置 HTTP 呼應頭,把你需求運轉拜訪的域名參加參加Access-Control-Allow-Origin中。
- jsonp
把后端依據(jù)懇求,結構 json 數(shù)據(jù),并返回,前端用 jsonp 跨域。
這兩種思路,本文不展開討論。
需求闡明的是,nginx 依據(jù)第一種思路,也供給了一種處理跨域的處理方案。
舉例: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 到現(xiàn)有 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; } }
到此,就完成了。