Nginx從入門到干活,看這一篇足矣


本文是一個(gè) Nginx 極簡(jiǎn)教程,目的在于幫助新手快速入門 Nginx,轉(zhuǎn)載自其他公眾號(hào),方便讀者也方便自己收藏。
Nginx 簡(jiǎn)介

什么是 Nginx?
Nginx(engine x)是一款輕量級(jí)的 Web 服務(wù)器 、反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器。
什么是反向代理?
反向代理(Reverse Proxy)方式是指以代理服務(wù)器來(lái)接受 internet 上的連接請(qǐng)求,然后將請(qǐng)求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,并將從服務(wù)器上得到的結(jié)果返回給 internet 上請(qǐng)求連接的客戶端。

Nginx 入門
https://github.com/dunwu/nginx-tutorial/blob/master/docs/nginx-ops.md
Nginx 的使用比較簡(jiǎn)單,就是幾條命令。
nginx?-s stop ??????快速關(guān)閉 Nginx,可能不保存相關(guān)信息,并迅速終止 Web 服務(wù)。
nginx -s quit ??????平穩(wěn)關(guān)閉 Nginx,保存相關(guān)信息,有安排的結(jié)束 Web 服務(wù)。
nginx -s reload ????因改變了 Nginx 相關(guān)配置,需要重新加載配置而重載。
nginx -s reopen ????重新打開日志文件。
nginx -c filename ??為 Nginx 指定一個(gè)配置文件,來(lái)代替缺省的。
nginx -t ???????????不運(yùn)行,僅僅測(cè)試配置文件。Nginx 將檢查配置文件的語(yǔ)法的正確性,并嘗試打開配置文件中所引用到的文件。
nginx -v ???????????顯示 Nginx 的版本。
nginx -V ???????????顯示 Nginx 的版本,編譯器版本和配置參數(shù)。
如果不想每次都敲命令,可以在 Nginx 安裝目錄下新添一個(gè)啟動(dòng)批處理文件 startup.bat,雙擊即可運(yùn)行。
@echo?off
rem?如果啟動(dòng)前已經(jīng)啟動(dòng)?Nginx?并記錄下?pid?文件,會(huì)?kill?指定進(jìn)程
nginx.exe?-s?stop
rem?測(cè)試配置文件語(yǔ)法正確性
nginx.exe?-t?-c?conf/nginx.conf
rem?顯示版本信息
nginx.exe?-v
rem?按照指定配置去啟動(dòng)?Nginx
nginx.exe?-c?conf/nginx.conf
如果是運(yùn)行在 Linux 下,寫一個(gè) shell 腳本,大同小異。
Nginx 實(shí)戰(zhàn)
我始終認(rèn)為,各種開發(fā)工具的配置還是結(jié)合實(shí)戰(zhàn)來(lái)講述,會(huì)讓人更易理解。
HTTP 反向代理
我們先實(shí)現(xiàn)一個(gè)小目標(biāo):不考慮復(fù)雜的配置,僅僅是完成一個(gè) HTTP 反向代理。
#運(yùn)行用戶
#user?somebody;
#啟動(dòng)進(jìn)程,通常設(shè)置成和?CPU?的數(shù)量相等
worker_processes??1;
#全局錯(cuò)誤日志
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?文件,記錄當(dāng)前啟動(dòng)的?Nginx?的進(jìn)程?ID
pid????????D:/Tools/nginx-1.10.1/logs/nginx.pid;
#工作模式及連接數(shù)上限
events?{
????worker_connections?1024;????#單個(gè)后臺(tái)worker?process進(jìn)程的最大并發(fā)鏈接數(shù)
}
#設(shè)定?HTTP?服務(wù)器,利用它的反向代理功能提供負(fù)載均衡支持
http?{
????#設(shè)定?mime?類型(郵件支持類型),類型由?mime.types?文件定義
????include???????D:/Tools/nginx-1.10.1/conf/mime.types;
????default_type??application/octet-stream;
????#設(shè)定日志
?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?是否調(diào)用?sendfile?函數(shù)(zero?copy?方式)來(lái)輸出文件,對(duì)于普通應(yīng)用,
????#必須設(shè)為?on,如果用來(lái)進(jìn)行下載等應(yīng)用磁盤?IO?重負(fù)載應(yīng)用,可設(shè)置為?off,以平衡磁盤與網(wǎng)絡(luò)?I/O?處理速度,降低系統(tǒng)的?uptime.
????sendfile????????on;
????#tcp_nopush?????on;
????#連接超時(shí)時(shí)間
????keepalive_timeout??120;
????tcp_nodelay????????on;
?#gzip?壓縮開關(guān)
?#gzip??on;
????#設(shè)定實(shí)際的服務(wù)器列表
????upstream?zp_server1{
????????server?127.0.0.1:8089;
????}
????#HTTP?服務(wù)器
????server?{
????????#監(jiān)聽(tīng)?80?端口,80?端口是知名端口號(hào),用于?HTTP?協(xié)議
????????listen???????80;
????????#定義使用?www.xx.com?訪問(wèn)
????????server_name??www.helloworld.com;
??#首頁(yè)
??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?后面設(shè)置映射的路徑
????????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;
????????????#過(guò)期 30?天,靜態(tài)文件不怎么更新,過(guò)期可以設(shè)大一點(diǎn),如果頻繁更新,則可以設(shè)置得小一點(diǎn)。
????????????expires?30d;
????????}
????????#設(shè)定查看?Nginx?狀態(tài)的地址
????????location?/NginxStatus?{
????????????stub_status???????????on;
????????????access_log????????????on;
????????????auth_basic????????????"NginxStatus";
????????????auth_basic_user_file??conf/htpasswd;
????????}
????????#禁止訪問(wèn)?.htxxx?文件
????????location?~?/\.ht?{
????????????deny?all;
????????}
??#錯(cuò)誤處理頁(yè)面(可選擇性配置)
??#error_page???404??????????????/404.html;
??#error_page???500?502?503?504??/50x.html;
????????#location?=?/50x.html?{
????????#????root???html;
????????#}
????}
}
注:conf/nginx.conf 是 Nginx 的默認(rèn)配置文件。你也可以使用 nginx -c 指定你的配置文件。
好了,讓我們來(lái)試試吧:
啟動(dòng) webapp,注意啟動(dòng)綁定的端口要和 Nginx 中的 upstream 設(shè)置的端口保持一致。
更改 host,在 C:\Windows\System32\drivers\etc 目錄下的 host 文件中添加一條 DNS 記錄:
127.0.0.1?www.helloworld.com
啟動(dòng)前文中 startup.bat 的命令。
在瀏覽器中訪問(wèn) www.helloworld.com,不出意外,已經(jīng)可以訪問(wèn)了。
HTTPS 反向代理
一些對(duì)安全性要求比較高的站點(diǎn),可能會(huì)使用 HTTPS(一種使用 ssl 通信標(biāo)準(zhǔn)的安全 HTTP 協(xié)議)。
這里不科普 HTTP 協(xié)議和 SSL 標(biāo)準(zhǔn)。但是,使用 Nginx 配置 HTTPS 需要知道幾點(diǎn):
HTTPS 的固定端口號(hào)是 443,不同于 HTTP 的 80 端口。
SSL 標(biāo)準(zhǔn)需要引入安全證書,所以在 nginx.conf 中你需要指定證書和它對(duì)應(yīng)的 key。
其他和 HTTP 反向代理基本一樣,只是在 Server 部分配置有些不同。
#HTTP?服務(wù)器
??server?{
??????#監(jiān)聽(tīng) 443 端口。443 為知名端口號(hào),主要用于 HTTPS 協(xié)議
??????listen???????443?ssl;
??????#定義使用?www.xx.com?訪問(wèn)
??????server_name??www.helloworld.com;
??????#ssl 證書文件位置(常見(jiàn)證書文件格式為: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;
??????}
??}
負(fù)載均衡
Nginx 也可以實(shí)現(xiàn)簡(jiǎn)單的負(fù)載均衡功能。

假設(shè)這樣一個(gè)應(yīng)用場(chǎng)景:將應(yīng)用部署在 192.168.1.11:80、192.168.1.12:80、192.168.1.13:80 三臺(tái) Linux 環(huán)境的服務(wù)器上。網(wǎng)站域名叫 www.helloworld.com,公網(wǎng) IP 為 192.168.1.11。
在公網(wǎng) IP 所在的服務(wù)器上部署 Nginx,對(duì)所有請(qǐng)求做負(fù)載均衡處理(下面例子中使用的是加權(quán)輪詢策略)。
nginx.conf 配置如下:
http?{
?????#設(shè)定?mime?類型,類型由?mime.type?文件定義
????include???????/etc/nginx/mime.types;
????default_type??application/octet-stream;
????#設(shè)定日志格式
????access_log????/var/log/nginx/access.log;
????#設(shè)定負(fù)載均衡的服務(wù)器列表
????upstream?load_balance_server?{
????????#weigth?參數(shù)表示權(quán)值,權(quán)值越高被分配到的幾率越大
????????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?服務(wù)器
???server?{
????????#偵聽(tīng)?80?端口
????????listen???????80;
????????#定義使用?www.xx.com?訪問(wèn)
????????server_name??www.helloworld.com;
????????#對(duì)所有請(qǐng)求進(jìn)行負(fù)載均衡請(qǐng)求
????????location?/?{
????????????root????????/root;?????????????????#定義服務(wù)器的默認(rèn)網(wǎng)站根目錄位置
????????????index???????index.html?index.htm;??#定義首頁(yè)索引文件的名稱
????????????proxy_pass??http://load_balance_server?;#請(qǐng)求轉(zhuǎn)向load_balance_server?定義的服務(wù)器列表
????????????#以下是一些反向代理的配置(可選擇性配置)
????????????#proxy_redirect?off;
????????????proxy_set_header?Host?$host;
????????????proxy_set_header?X-Real-IP?$remote_addr;
????????????#后端的?Web?服務(wù)器可以通過(guò)?X-Forwarded-For?獲取用戶真實(shí)?IP
????????????proxy_set_header?X-Forwarded-For?$remote_addr;
????????????proxy_connect_timeout?90;??????????#Nginx?跟后端服務(wù)器連接超時(shí)時(shí)間(代理連接超時(shí))
????????????proxy_send_timeout?90;?????????????#后端服務(wù)器數(shù)據(jù)回傳時(shí)間(代理發(fā)送超時(shí))
????????????proxy_read_timeout?90;?????????????#連接成功后,后端服務(wù)器響應(yīng)時(shí)間(代理接收超時(shí))
????????????proxy_buffer_size?4k;??????????????#設(shè)置代理服務(wù)器(Nginx)保存用戶頭信息的緩沖區(qū)大小
????????????proxy_buffers?4?32k;???????????????#proxy_buffers?緩沖區(qū),網(wǎng)頁(yè)平均在?32k?以下的話,這樣設(shè)置
????????????proxy_busy_buffers_size?64k;???????#高負(fù)荷下緩沖大小(proxy_buffers*2)
????????????proxy_temp_file_write_size?64k;????#設(shè)定緩存文件夾大小,大于這個(gè)值,將從?upstream?服務(wù)器傳
????????????client_max_body_size?10m;??????????#允許客戶端請(qǐng)求的最大單文件字節(jié)數(shù)
????????????client_body_buffer_size?128k;??????#緩沖區(qū)代理緩沖用戶端請(qǐng)求的最大字節(jié)數(shù)
????????}
????}
}
負(fù)載均衡策略
負(fù)載均衡策略在各種分布式系統(tǒng)中基本上原理一致,對(duì)于原理有興趣,不妨參考:
https://dunwu.github.io/blog/design/theory/load-balance-theory/
輪詢:
upstream?bck_testing_01?{
??#?默認(rèn)所有服務(wù)器權(quán)重為?1
??server?192.168.250.220:8080
??server?192.168.250.221:8080
??server?192.168.250.222:8080
}
加權(quán)輪詢:
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
}
加權(quán)最少連接:
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
}
網(wǎng)站有多個(gè) webapp 的配置
舉個(gè)例子:假如 www.helloworld.com 站點(diǎn)有好幾個(gè) webapp,finance(金融)、product(產(chǎn)品)、admin(用戶中心)。
訪問(wèn)這些應(yīng)用的方式通過(guò)上下文(context)來(lái)進(jìn)行區(qū)分:
www.helloworld.com/finance/
www.helloworld.com/product/
www.helloworld.com/admin/
配置也不難,來(lái)看看怎么做吧:
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?{
????????#此處省略一些基本配置
????????#默認(rèn)指向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;
????????}
????}
}
靜態(tài)站點(diǎn)
配置如下:
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;
????????????#轉(zhuǎn)發(fā)任何請(qǐng)求到?index.html
????????}
????}
}
然后,添加 HOST:
127.0.0.1?static.zp.cn
搭建文件服務(wù)器
將 autoindex 開啟可以顯示目錄,默認(rèn)不開啟。
將 autoindex_exact_size 開啟可以顯示文件的大小。
將 autoindex_localtime 開啟可以顯示文件的修改時(shí)間。
root 用來(lái)設(shè)置開放為文件服務(wù)的根路徑。
charset 設(shè)置為 charset utf-8,gbk,可以避免中文亂碼問(wèn)題(Windows 服務(wù)器下設(shè)置后,依然亂碼,本人暫時(shí)沒(méi)有找到解決方法)。
一個(gè)最簡(jiǎn)化的配置如下:
autoindex?on;#?顯示目錄
autoindex_exact_size?on;#?顯示文件大小
autoindex_localtime?on;#?顯示文件時(shí)間
server?{
????charset??????utf-8,gbk;?#?windows?服務(wù)器下設(shè)置后,依然亂碼,暫時(shí)無(wú)解
????listen???????9050?default_server;
????listen???????[::]:9050?default_server;
????server_name??_;
????root?????????/share/fs;
}
解決跨域
CORS,在后端服務(wù)器設(shè)置 HTTP 響應(yīng)頭,把你需要允許訪問(wèn)的域名加入 Access-Control-Allow-Origin 中。
jsonp,把后端根據(jù)請(qǐng)求,構(gòu)造 json 數(shù)據(jù),并返回,前端用 jsonp 跨域。
首先,在 enable-cors.conf 文件中設(shè)置 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";
}
接下來(lái),在你的服務(wù)器中 include enable-cors.conf 來(lái)引入跨域配置:
#?----------------------------------------------------
#?此文件為項(xiàng)目?nginx?配置片段
#?可以直接在?nginx?config?中?include(推薦)
#?或者?copy?到現(xiàn)有?nginx?中,自行配置
#?www.helloworld.com?域名需配合?dns?hosts?進(jìn)行配置
#?其中,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;
??}
}
編輯:陶家龍
出處:github.com/dunwu/nginx-tutorial
文末分享
回復(fù)【00】:獲取DotNet、Java、C++、前端等技術(shù)資料 加微信群:添加號(hào)主微信號(hào)【dotnet9】,備注【入群】 加QQ群:群號(hào)【771992300】,備注【Dotnet9】
?時(shí)間如流水,只能流去不流回。
公眾號(hào):Dotnet9 號(hào)主微信號(hào):dotnet9 微信公眾號(hào):Dotnet9
