一:概念
nginx用來作爲網關暴露到外面,裏面負載均衡其他的應用服務器tomcat,當然,靜態資源,js,圖片,之類的可以直接放到nginx服務器,來加快訪問速度;
和haproxy對比
1.nginx可以支持幾萬的併發連接數,在性能方面應該和haproxy都差不多,
2.使用起來簡單一點,主要是通過配置文件來使用相應的模塊
3.沒有監控頁面(這裏說的nginx只說免費版本),haproxy有
4.haproxy完全免費,可以拿到4,7層數據來定製我們想要的任何功能,不過需要深入學習;nginx的話如果現有的模塊不支持某個功能,要不使用商業版本(如果支持),要不自己開發模塊來支持,比較困難
二:版本
1.http://nginx.org/ 免費版本 就是我們常說的nginx open source
2.https://www.nginx.com/ 商業版本,全稱nginx plus
三:安裝
兩種安裝方式
a.使用yum install直接安裝編譯好的版本,參考http://nginx.org/en/linux_packages.html#RHEL-CentOS
b.自己編譯源碼,好處就是可以指定編譯的模塊
考慮到以後有可能會增加模塊,我們使用第二種方法安裝
1.安裝編譯需要的工具包
[root@deappa17 soft]# yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel
2.安裝PCRE讓Nginx 支持 Rewrite 功能
[root@deappa17 soft]# wget https://nchc.dl.sourceforge.net/project/pcre/pcre/8.43/pcre-8.43.tar.gz
[root@deappa17 soft]# tar zxvf pcre-8.43.tar.gz
[root@deappa17 soft]# cd pcre-8.43
[root@deappa17 pcre-8.43]# ./configure
[root@deappa17 pcre-8.43]# make && make install
[root@deappa17 pcre-8.43]# pcre-config --version
8.43
3.安裝nginx
[root@deappa17 soft]# wget http://nginx.org/download/nginx-1.16.1.tar.gz
[root@deappa17 soft]# tar xzvf nginx-1.16.1.tar.gz
[root@deappa17 soft]# cd nginx-1.16.1
[root@deappa17 nginx-1.16.1]# ./configure --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module
[root@deappa17 nginx-1.16.1]# make
[root@deappa17 nginx-1.16.1]# make install
[root@deappa17 nginx-1.16.1]# /usr/local/webserver/nginx/sbin/nginx -v
nginx version: nginx/1.16.1
四:常用操作
1.啓動nginx
[root@deappa17 nginx-1.16.1]# /usr/local/webserver/nginx/sbin/nginx
2.檢查配置文件的正確性
用於已經啓動,調整了配置文件,重新加載之前使用
/usr/local/webserver/nginx/sbin/nginx -t
3.其他常用命令
/usr/local/webserver/nginx/sbin/nginx -s reload # 重新載入配置文件,如果配置文件中配置的目錄不存在,則不報錯,但不生效,需要看日誌來確認是否重新載入是否成功
/usr/local/webserver/nginx/sbin/nginx -s reopen # 重新打開日誌文件,並不是重啓nginx
/usr/local/webserver/nginx/sbin/nginx -s stop # 停止 Nginx
/usr/local/webserver/nginx/sbin/nginx -s quit # 平緩停止 Nginx
五:常用配置
這裏不羅列所有的配置,如果需要可以參考nginx官網http://nginx.org/en/docs/,模塊內部有詳細全面的指令說明,可用內部變量及例子
1.配置成web服務器
http {
server {
listen 127.0.0.1:8080;
}
server {
listen 80;
server_name example.org www.example.org;
}
server {
listen 80 default_server;
location /some/path/ {
#...
}
location ~ \.html? {
#...
}
location /images/ {
root /data;
}
location / {
proxy_pass http://www.example.com;
}
// 可以使用內置變量$remote_addr,
// 參考每個模塊最下面的變量說明,例如ngx_http_core_module模塊內部可以使用的內置變量
//https://nginx.org/en/docs/http/ngx_http_core_module.html?&_ga=2.205840795.900571110.1585708043-1368246722.1570772956#variables
// 返回特定的響應碼
location /wrong/url {
return 404;
}
location /permanently/moved/url {
return 301 http://www.example.com/moved/here;
}
// 重寫http相應的內容
location / {
sub_filter /blog/ /blog-staging/;
sub_filter_once off;
}
location / {
sub_filter 'href="http://127.0.0.1:8080/' 'href="https://$host/';
sub_filter 'img src="http://127.0.0.1:8080/' 'img src="https://$host/';
sub_filter_once on;
}
// 處理錯誤
location /old/path.html {
error_page 404 /404.html;
}
location /old/path2.html {
error_page 404 =301 http:/example.com/new/path.html;
}
// 出現404轉到後端
location /images/ {
root /data/www;
open_file_cache_errors off;
error_page 404 = /fetch$uri;
}
location /fetch/ {
proxy_pass http://backend/;
}
}
}
location匹配優先級
首先說明:匹配字符串有兩種,正則表達式和普通字符串(非正則表達式)
1)遇到=號,直接返回,優先級最高
2)找到最長匹配的普通字符串,如果前面有^~則直接返回
3)找到匹配的正則表達式,直接返回
4)沒有找到匹配的正則表達式,則使用步驟2匹配到的最長普通字符串匹配
2.提供靜態資源
server {
root /www/data; // 資源位置
location / {
index index.htm index.html;
}
location /images/ {
autoindex on; // 返回列表目錄頁面
}
location /images2/ {
try_files $uri /images/default.gif; // 如果請求資源不存在,則返回默認的
}
location /images3/ {
try_files $uri $uri/ $uri.html =404; // 如果請求資源不存在,則返回404
}
location /images4/ {
try_files $uri $uri/ @backend; // 如果請求資源不存在,則定向到下面backend
}
location ~ \.(mp3|mp4) {
root /www/media;
}
location @backend {
proxy_pass http://backend.example.com;
}
// 優化性能相關
location /mp3 {
//默認情況下,NGINX處理文件傳輸本身,並在發送之前將文件複製到緩衝區中。啓用
//sendfile指令消除了將數據複製到緩衝區的步驟,並允許將數據從一個文件描述符直接
//複製到另一個文件描述符。或者,爲了防止一個快速連接完全佔用工作進程,可以使用
//sendfile_max_chunk指令來限制單個sendfile()調用中傳輸的數據量(在本例中爲1 MB):
sendfile on;
sendfile_max_chunk 1m;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
}
}
3.反向代理
location /some/path/ {
proxy_pass http://www.example.com/link/;
}
location ~ \.php {
proxy_pass http://127.0.0.1:8000;
}
// 設置header
location /some/path/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8000;
}
// 阻止傳遞header
location /some/path/ {
proxy_set_header Accept-Encoding "";
proxy_pass http://localhost:8000;
}
// 配置緩存大小,默認已經啓動
location /some/path/ {
proxy_buffers 16 4k;
proxy_buffer_size 2k;
proxy_pass http://localhost:8000;
}
// 關閉緩存
location /some/path/ {
proxy_buffering off;
proxy_pass http://localhost:8000;
}
// 綁定sorceip,比如有多網卡,或者其他的需求
location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}
location /app2/ {
proxy_bind 127.0.0.2;
proxy_pass http://example.com/app2/;
}
location /app3/ {
proxy_bind $server_addr;
proxy_pass http://example.com/app3/;
}
4.http負載均衡
http {
upstream backend {
# no load balancing method is specified for Round Robin
#least_conn;
#ip_hash;
#Random 還可以加其他的參數,請參考官網
#https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/
server backend1.example.com;
server backend2.example.com;
server 192.0.0.1 backup;
# 如果一個服務器需要暫時從負載平衡循環中移除,可以使用down參數來標記它,
# 以保持當前客戶端IP地址的散列。本服務器處理的請求被自動發送到組中的下一個服務器
server backend3.example.com down;
# 30秒內3次失敗,則這臺服務器標識爲不可用30秒(30秒是否又可用了?)
server backend2.example.com max_fails=3 fail_timeout=30s;
#設置服務器將其權重從0恢復到一個標稱值的時間,當不健康的服務器變得健康時,
#或服務器在一段時間後變得可用時(服務器被認爲不可用)。默認值爲0,即禁用慢啓動。
server backend1.example.com slow_start=30s;
}
server {
location / {
proxy_pass http://backend;
}
}
}
5.TCP負載均衡
stream {
# ...
server {
listen 127.0.0.1:12345;
proxy_pass backend.example.com:12345;
proxy_bind 127.0.0.1:12345;
}
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12346;
# ...
}
}
6.限流
1)限制併發連接數
http {
limit_conn_zone $server_name zone=servers:10m;
server {
limit_conn servers 1000;
}
}
2)限制訪問速率
http {
#...
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
#...
location /search/ {
# 每秒處理一個請求,超出的直接返回503
limit_req zone=one;
}
location /search2/ {
# 每秒處理一個請求,超出的進入桶中延遲處理(以指定的速率處理,客戶端會卡着),如果桶滿了,則直接返回503
limit_req zone=one burst=5;
}
location /search3/ {
# 每秒處理一個請求,超出的進入桶中立即處理,好像桶中有個計時器,每進入一個請求加1,每過一秒
# 減1,如果計時器=5,則此時新來的請求直接返回503,此種配置可以應對突發的情況並且不延遲,突發的緩衝是5
# 個人認爲此種方式比較完美
limit_req zone=one burst=5 nodelay;
}
}
}
3)限制下載帶寬
http {
limit_conn_zone $binary_remote_address zone=addr:10m
server {
root /www/data;
// 正常可以打開5個連接,現代瀏覽器會直接打開3個連接
limit_conn addr 5;
location / {
}
location /download/ {
#限制打開1個連接
limit_conn addr 1;
#1M後開始限制,可以不要此參數,直接限制
limit_rate_after 1m;
limit_rate 50k;
}
}
}
7.緩存
http {
# 定義緩存的名稱,單個緩存內容的最大size,總緩存的最大size,和緩存的目錄(必須存在)
proxy_cache_path /data/nginx/cache keys_zone=mycache:10m max_size=10g;
# 定義一個變量$purge_method,他的值有$request_method決定
map $request_method $purge_method {
PURGE 1;
default 0;
}
# 創建變量,其值依賴於客戶端IP地址
geo $purge_allowed {
default 0; # 默認不允許
192.168.100.17 1; # 本地允許
192.168.0.0/24 1; # 同一個網段允許
}
map $request_method $purge_method2 {
PURGE $purge_allowed;
default 0;
}
server {
# 使用緩存
proxy_cache mycache;
# 定義緩存的key
proxy_cache_key "$host$request_uri$cookie_user";
# 被請求多少次才被緩存,默認是1
proxy_cache_min_uses 5;
# 定義各種響應碼的緩存時間(測試過程發現如果不定義此參數緩存不生效)
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
# 僅僅200, 301, and 302會被緩存
proxy_cache_valid 5m;
# 所有響應碼會被緩存
proxy_cache_valid any 1m;
# 指定忽略響應頭的內容,內容是否被緩存,還和響應頭中的內容有關,比如響應頭中有Set-Cookie字段
# 則響應的內容不會被緩存
proxy_ignore_headers Set-Cookie Cache-Control;
# 如果後面的幾個參數,任何一個參數值不爲空或者不等0,nginx就不會查找緩存,直接進行代理轉發
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
# 定義不需要緩存的情況,參數使用和proxy_cache_bypass一樣
proxy_no_cache $http_pragma $http_authorization;
# 清除緩存,如果收到請求method=PURGE ,則清除指定的緩存,如果路徑/*結尾,則清除匹配的所有緩存
# 並不會真正從磁盤清除,有三種條件可以真正從磁盤清除,如下
# proxy_cache_path使用purger=on或者inactive參數,或者下次訪問此緩存時
proxy_cache_purge $purge_method;
# 除了清除緩存功能,可以限制訪問此清除功能的客戶端ip
proxy_cache_purge $purge_method2;
# 如果緩存的文件比較大,比如視頻文件,可以切片緩存,具體可以參考
# https://docs.nginx.com/nginx/admin-guide/content-cache/content-caching/
location / {
proxy_pass http://localhost:8000;
}
}
}
六:常見問題
1.上傳大文件失敗,小文件可以
- client_body_buffer_size 配置請求體緩存區大小
- client_body_temp_path 設置臨時文件存放路徑,只有當上傳的請求體超出緩存區大小時,纔會寫到臨時文件中
- client_max_body_size 設置上傳文件的最大值
通過設置client_max_body_size 100m解決掉
2.防止惡意攻擊某個地址,比如發短信
location ~ /account(/.*)
{
if ($http_referer ~ "https://www.xxxxxxxx.net/account/sendPhoneCode") {
#如果匹配就直接返回200,返回404,也行啊,自己定。給可愛的攻擊者,不傳給後端web
return 200;
}
#不匹配,傳給後端web
proxy_pass http://web_group;
}
參考網站: