正向代理舉例:翻越萬里長城去遊覽牆外的景色
反向代理舉例:負載均衡php
正向代理和反向代理涉及三個主體:css
正向代理中,代理跟請求方是一家子,請求方說要啥,代理就給他啥。
反向代理中,代理跟被請求方是一家子,代理統籌規劃讓哪個被請求方來處理請求,對於請求方來講,代理就是處理請求的人。大多數狀況下,反向代理和被請求方在同一個服務器上。Nginx就是最經常使用的反向代理服務器。html
這裏也提一下:動態代理和靜態代理
正向代理和反向代理是代理服務器的兩種類型
動態代理和靜態代理是Java中的設計模式:代理模式。
Spring的兩大核心:java
面向切面編程中大量使用動態代理,在每個方法調用前、調用後、拋異常時進行處理,跟裝飾器模式很像。linux
nginx主要配置位於/etc/nginx目錄下,nginx不只僅能夠用於負載均衡HTTP請求,也能夠用於基於TCP的其它協議的負載均衡。/etc/nginx/nginx.conf是nginx的跟配置,一切配置都是這個配置的子孫。nginx
/etc/nginx/nginx.confweb
users www-data;定義當前用戶 worker_prosesses 4;定義worker數 pid /run/nginx.pid;定義pid文件 events{......} http{... http協議的相關配置 include xxx路徑下的conf.d/*.conf; 可使用文件通配符來描述文件,可是必定是文件而非文件夾 } mail{ ....mail相關的一些配置 server{ listen localhost:xx; protocol pop3; proxy on; } server{ listen localhost:xxxx; protocol imap; proxy on; } }
能夠發現,最外層是協議,協議內部有若干個server組成,每一個server監聽一個端口,根據路徑能夠轉發到本地的其它端口進行處理。include是簡單的複製粘貼。正則表達式
需求說明:Tomcat和Gunicorn分別運行在8080端口和8000端口,如今要讓它們共用80端口。
當使用:localhost/tomcat/myapp
時,至關於localhost:8080/myapp
當使用:localhost/gunicorn/myapp
時,至關於localhost:8000/myapp
sql
server { listen 80; server_name www.haha.com; access_log /var/log/nginx/reverse.log; location /tomcat { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /gunicorn { proxy_pass http://127.0.0.1:8000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
server_name描述了服務器地址部分,既能夠是域名,也能夠是IP地址。這一項不可省略。
設置proxy_set_header部分是將請求者的真實信息告知後臺服務器shell
須要注意的是:
proxy_pass http://127.0.0.1:8000/myweb/
這樣是錯誤的;/
,不然路徑拼接時會由於少一個反斜槓而沒法解析,致使404錯誤。負載均衡必然要用到反向代理,讓Nginx做爲大管家凌駕於處理請求的服務器之上,Nginx能夠動態決定讓哪一個服務器來處理請求。負載均衡問題源遠流長:兩臺相同的處理機處理若干任務,怎麼處理可以使得任務儘早完成?這是「雙塔」問題;兩臺不一樣的處理機處理若干任務,不一樣處理機處理不一樣任務花費時間不一樣,怎樣分配任務才能使得任務儘早完成?
負載均衡的核心問題就是:創建用戶請求和服務器之間的映射。有以下幾種方式:
輪盤賭的方式進行以下配置,首先定義一個upstream,它是多個server的集合。而後在location中就能夠直接使用這個upstream。
upstream your_host_or_ip { server 127.0.0.3:8000 weight=5; server 127.0.0.3:8001 weight=5; server 192.168.0.1:8000; server 192.168.0.1:8001; } server { listen 80; server_name your_host_or_ip; access_log /var/log/nginx/my_access.log main; location / { proxy_pass http://your_host_or_ip; } }
須要注意的是,一臺服務器有兩種訪問方式:ip地址和域名方式。ip地址方式確定只能有一種方式進行訪問,由於ip地址是全網惟一的。而一臺服務器能夠綁定多個域名,這樣就能夠經過多個域名訪問同一個服務器了。
當配置了upstream以後,upstream的名稱確定跟服務器的名稱(IP或者域名)相同,因此一個域名只能進行一個負載均衡,一個IP也只能進行一個負載均衡,而一臺服務器能夠進行多個負載均衡。
location配置:
直接寫一個字符串,常規字符串匹配
~
表示執行一個正則匹配,區分大小寫
~*
表示執行一個正則匹配,不區分大小寫
^~
表示普通字符匹配。使用前綴匹配。若是匹配成功,則再也不匹配其餘location。
=
進行普通字符精確匹配。也就是徹底匹配。
location配置的優先級:
在Nginx的location和配置中location的順序沒有太大關係。正location表達式的類型有關。相同類型的表達式,字符串長的會優先匹配。
如下是按優先級排列說明:
第一優先級:等號類型(=)的優先級最高。一旦匹配成功,則再也不查找其餘匹配項。
第二優先級:^~
類型表達式。一旦匹配成功,則再也不查找其餘匹配項。
第三優先級:正則表達式類型(~
~*
)的優先級次之。若是有多個location的正則能匹配的話,則使用正則表達式最長的那個。
第四優先級:常規字符串匹配類型。按前綴匹配。
下面示例一下四種地址類型:
location = / { # 僅僅匹配請求 / [ configuration A ] } location / { # 匹配全部以 / 開頭的請求。可是若是有更長的同類型的表達式,則選擇更長的表達式。若是有正則表達式能夠匹配,則優先匹配正則表達式。 [ configuration B ] } location /documents/ { # 匹配全部以 /documents/ 開頭的請求。可是若是有更長的同類型的表達式,則選擇更長的表達式。 #若是有正則表達式能夠匹配,則優先匹配正則表達式。 [ configuration C ] } location ^~ /images/ { # 匹配全部以 /images/ 開頭的表達式,若是匹配成功,則中止匹配查找。因此,即使有符合的正則表達式location,也 # 不會被使用 [ configuration D ] } location ~* \.(gif|jpg|jpeg)$ { # 匹配全部以 gif jpg jpeg結尾的請求。可是 以 /images/開頭的請求,將使用 Configuration D [ configuration E ] }
請求匹配實例:
/ -> configuration A /index.html -> configuration B /documents/document.html -> configuration C /images/1.gif -> configuration D /documents/1.jpg -> configuration E
應用舉例:隱藏內在的地址
server { # 用 xxoo_admin 來掩飾 admin location / { # 使用break拿一旦匹配成功則忽略後續location rewrite /xxoo_admin /admin break; } # 訪問真實地址直接報沒權限 location /admin { return 403; } }
Nginx的反向代理像一個URL函數,輸入是一個URL,輸出也是一個URL。運行過程多是這樣的:
用戶發起請求url0 url1=f(url0) url2=f(url1) ...直到url再也不被重寫,被路由到合適的請求處理結點
在配置文件的server塊中寫,如:
server { rewrite 規則 定向路徑 重寫類型; }
$index
來表示正則裏的捕獲分組須要注意:
下面舉例說明4種重寫類型
server { # 訪問 /last.html 的時候,頁面內容重寫到 /index.html 中 rewrite /last.html /index.html last; # 訪問 /break.html 的時候,頁面內容重寫到 /index.html 中,並中止後續的匹配 rewrite /break.html /index.html break; # 訪問 /redirect.html 的時候,頁面直接302定向到 /index.html中 rewrite /redirect.html /index.html redirect; # 訪問 /permanent.html 的時候,頁面直接301定向到 /index.html中 rewrite /permanent.html /index.html permanent; # 把 /html/*.html => /post/*.html ,301定向 rewrite ^/html/(.+?).html$ /post/$1.html permanent; # 把 /search/key => /search.html?keyword=key rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent; }
在/etc/nginx/fastcgi.conf中能夠看到所有定義。
$args :這個變量等於請求行中的參數,同$query_string $content_length : 請求頭中的Content-length字段。 $content_type : 請求頭中的Content-Type字段。 $document_root : 當前請求在root指令中指定的值。 $host : 請求主機頭字段,不然爲服務器名稱。 $http_user_agent : 客戶端agent信息 $http_cookie : 客戶端cookie信息 $limit_rate : 這個變量能夠限制鏈接速率。 $request_method : 客戶端請求的動做,一般爲GET或POST。 $remote_addr : 客戶端的IP地址。 $remote_port : 客戶端的端口。 $remote_user : 已經通過Auth Basic Module驗證的用戶名。 $request_filename : 當前請求的文件路徑,由root或alias指令與URI請求生成。 $scheme : HTTP方法(如http,https)。 $server_protocol : 請求使用的協議,一般是HTTP/1.0或HTTP/1.1。 $server_addr : 服務器地址,在完成一次系統調用後能夠肯定這個值。 $server_name : 服務器名稱。 $server_port : 請求到達服務器的端口號。 $request_uri : 包含請求參數的原始URI,不包含主機名,如:」/foo/bar.php?arg=baz」。 $uri : 不帶請求參數的當前URI,$uri不包含主機名,如」/foo/bar.html」。 $document_uri : 與$uri相同。
如:
訪問連接是:http://localhost:88/test1/test2/test.php
網站路徑是:/var/www/html
$host:localhost $server_port:88 $request_uri:http://localhost:88/test1/test2/test.php $document_uri:/test1/test2/test.php $document_root:/var/www/html $request_filename:/var/www/html/test1/test2/test.php
if (表達式) { }
表達式的寫法有不少:
~*
不區分大小寫的匹配,!~區分大小寫的不匹配表達式中可使用shell經常使用運算符:
下面看幾個if語句的例子:
例子一:簡單的if語句
# 若是文件不存在則返回400 if (!-f $request_filename) { return 400; } # 若是host不是xuexb.com,則301到xuexb.com中 if ( $host != 'xuexb.com' ){ rewrite ^/(.*)$ https://xuexb.com/$1 permanent; } # 若是請求類型不是POST則返回405 if ($request_method = POST) { return 405; } # 若是參數中有 a=1 則301到指定域名 if ($args ~ a=1) { rewrite ^ http://example.com/ permanent; }
例子二:在重寫中使用if語句
# 訪問 /test.html 時 location = /test.html { # 默認值爲xiaowu set $name xiaowu; # 若是參數中有 name=xx 則使用該值 if ($args ~* name=(\w+?)(&|$)) { set $name $1; } # 301 rewrite ^ /$name.html permanent; }
舉例說明運行結果:
/test.html => /xiaowu.html /test.html?name=ok => /ok.html?name=ok
service nginx configtest 用來檢測配置是否正確
service nginx reload 從新加載配置
使用sudo service nginx
命令能夠查看可用參數.
location /request_path/image/ { root /local_path/image/; }
這樣配置的結果就是當客戶端請求 /request_path/image/cat.png 的時候,
Nginx把請求映射爲/local_path/image/request_path/image/cat.png
location /request_path/image/ { alias /local_path/image/; }
這時候,當客戶端請求 /request_path/image/cat.png 的時候,
Nginx把請求映射爲/local_path/image/cat.png
下面舉一個例子,當訪問myip/poem/authorImage/libai.jpg的時候會自動去文件夾/home/USER_NAME/authorImage/下去尋找libai.jpg。
location /poem/authorImage/ { alias /home/USER_NAME/authorImage/; autoindex on; }
須要注意的是,必須保證authorImage這個文件夾權限足夠,不然Nginx沒有權力訪問這個文件夾。最簡單可是不夠安全的方式就是把/etc/nginx.conf文件開頭的user www-data改成user root,這樣把管理員權限賦予Nginx,Nginx就可以訪問任意文件了。這樣作的缺點就是,一旦Nginx被攻破,整個系統的文件資源可能都會受到威脅。
實際訪問/var/ftp/in_ftp/ftp/space_1/111.jpg
location /myf_test/ { root /; rewrite ^/myf_test/(.*)$ /var/ftp/$1 break; }
www.ikscher.com/index.PHP?route=product/product&product_id=123
重定向到www.ikscher.com/product/product&product_id=123
if ($request_uri ~* "(.*)index\.php\?route=(.*)"){ set $host_ $1; set $last_ $2; rewrite (.*) $host_$last_? permanent; #這裏的.*表明的是url的原先地址,即要轉向的url地址。 }
注意:
www.ikscher.com/?route=product/product&product_id=123
,nginx在進行rewrite的正則表達式中只會將url中?前面的部分拿出來匹配,匹配完成後,?後面的內容將自動追加到url中(包含?),若是不讓後面的內容追加上去,請在最後加上?便可。若是想要?後面的內容時請使用$query_string
在這裏提醒一點,調試的時候在rewrite的最後一個配置項中不要使用break last這些,使用redirect能夠看到轉換後的地址。綜合以上幾點,使用的配置項爲
rewrite (.)index.php(.) $1$query_string? permanent;
要求:abc.domian.com/sort/2 => abc.domian.com/index.PHP?act=sort&name=abc&id=2
規則配置:
if ($host ~* (.*)\.domain\.com) { set $sub_name $1; rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last; }
要求:/123456/xxxx -> /xxxx?id=123456
規則配置:rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
設定nginx在用戶使用ie的使用重定向到/nginx-ie目錄
規則以下:
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; }
/
目錄自動加「/」 ,這個功能通常瀏覽器自動完成
if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; }
禁止多個目錄 location ~ ^/(cron|templates)/ { deny all; break; } 禁止以/data開頭的文件,能夠禁止/data/下多級目錄下.log.txt等請求 location ~ ^/data { deny all; } 禁止單個文件 location ~ /data/sql/data.sql { deny all; }
給favicon.ico和robots.txt設置過時時間; 這裏爲favicon.ico爲99天,robots.txt爲7天並不記錄404錯誤日誌
location ~(favicon.ico) { log_not_found off; expires 99d; break; } location ~(robots.txt) { log_not_found off; expires 7d; break; }
設定某個文件的瀏覽器緩存過時時間;這裏爲600秒,並不記錄訪問日誌
location ^~ /html/scripts/loadhead_1.js { access_log off; expires 600; break; }
Nginx還能夠自定義某一類型的文件的保質期時間,具體寫法看下文的代碼:
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ { if (-f $request_filename) { expires 1h; break; } } //上段代碼就將js|css|jpg|jpeg|gif|png|swf這類文件的保質期設置爲一小時。
防盜鏈:若是你的網站是個下載網站,下載步驟應該是先通過你的主頁找到下載地址,才能下載,爲了防止某些網友直接訪問下載地址徹底不經過主頁下載,咱們就可使用防盜鏈的方式,具體代碼以下:
location ~* \.(gif|jpg|swf)$ { valid_referers none blocked start.igrow.cn sta.igrow.cn; if ($invalid_referer) { rewrite ^/ http://$host/logo.png; } }
文件反盜鏈並設置過時時間
--<盜鏈屢次請求也會打開你的站點的圖片啊,因此設置下緩存時間,不會每次盜鏈都請求並下載這張圖片> location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ { valid_referers none blocked *.jjonline.cn *.jjonline.com.cn *.lanwei.org *.jjonline.org localhost 42.121.107.189; if ($invalid_referer) { rewrite ^/ http://img.jjonline.cn/forbid.gif; return 417; break; } access_log off; break; }
說明:
這裏的return 417爲自定義的http狀態碼,默認爲403,方便經過nginx的log文件找出正確的盜鏈的請求地址
rewrite ^/ http://img.jjonline.cn/forbid.gif;
顯示一張防盜鏈圖片
「access_log off;」不記錄訪問日誌,減輕壓力
「expires 3d」全部文件3天的瀏覽器緩存
location \ { allow 22.27.164.25; #容許的ipd deny all; auth_basic 「KEY」; #認證的一些設置 auth_basic_user_file htpasswd; }
if (!-e $request_filename) { #proxy_pass http://127.0.0.1; #這裏是跳轉到代理ip,這個代理ip上有一個監聽的web服務器 rewrite ^/ http://www.jjonline.cn/none.html; #跳轉到這個網頁去 #return 404; #直接返回404碼,而後會尋找root指定的404.html文件 }
域名跳轉
server { listen 80; server_name jump.jjonline.cn ;#須要跳轉的多級域名 index index.html index.htm index.php; #入口索引文件的名字 root /var/www/public_html/; #這個站點的根目錄 rewrite ^/ http://www.jjonline.cn/; #rewrite到這個地址,功能表現:在瀏覽器上輸入jump.jjonline.cn並回車,不會有任何提示直接變成www.jjonline.cn access_log off; }
多域名轉向
server { listen 80; server_name www.jjonline.cn www.jjonline.org; index index.html index.htm index.php; root /var/www/public_html/; if ($host ~ 「jjonline\.org」) { rewrite ^(.*) http://www.jjonline.cn$1 permanent; } }
三級域名跳轉
if ($http_host ~* 「^(.*)\.i\.jjonline\.cn$」) { rewrite ^(.*) http://demo.jjonline.cn$1; break; }
server { listen 80; server_name mirror.jjonline.cn; index index.html index.htm index.php; root /var/www/public_html; rewrite ^/(.*) http://www.jjonline.cn/$1 last; access_log off; }
java靜態代理和動態代理
Nginx location在配置中的優先級
nginx配置url重寫
nginx 重寫 rewrite 基礎及實例