Nginx之反向代理配置(二)
- 2020 年 3 月 6 日
- 筆記
前文我們聊了Nginx的防盜鏈、反向代理以及開啟nginx代理緩存,回顧請參考https://www.cnblogs.com/qiuhom-1874/p/12417130.html;今天我們繼續說nginx的反向代理,上一篇主要就說了下nginx反向代理http協議的使用,被代理RUL包含和不包含RUI的處理邏輯;我們可以把這種前後端都用同樣的協議理解為同構代理,就是說前端用戶訪問nginx是http或https協議,代理服務器訪問後端的真正提供服務的服務器也是基於http協議,這種前後端都是使用同一種協議,我們就說這是同構;同理有同構就有異構,異構就是前後端使用的協議不同,比如前端用戶使用http或https協議,代理和後端服務器使用fastcgi協議,這種就叫異構;互聯網上絕大部分網站都不是純html靜態網頁,很多網站都是有自己的應用服務器,比如,我們用戶訪問的數據是需要一段腳本,或者某一程序執行後的數據,那麼我們就把後面需要執行腳本的服務器叫應用服務器;nginx作為web服務器它雖然有很多功能,但是它自己沒有執行某些腳本的能力比如php腳本,通俗的講,nginx只可以處理靜態文本,不能自己執行php腳本(需藉助其他應用服務器),它和httpd類似,httpd還可以動態的加載php模塊,讓其擁有執行php腳本的能力,nginx沒有,為了實現這樣的功能,nginx就支持通過fastcgi協議向後端代理客戶端請求一個自己不能處理的資源;當然類似的協議還有很多比如,scgi、uwsgi等等;像這種異構的架構上,它的原理是這樣的,客戶端請求某一腳本資源,比如,index.php這個文件,如果我們不把用戶的請求代理到後端應用服務器上,客戶端看到的數據是index.php里的腳本內容,這顯然是不合情理的;那怎麼辦呢?通常情況我們需要在nginx服務器上配置,用戶訪問某某.php結尾的URL時,我們就讓它幹嘛幹嘛,通過這種匹配用戶的URL去做代理,把用戶的請求代理到後端服務器,讓後端應用服務器把腳本執行完,然後把執行後的數據返回給代理,再由代理響應給客戶端;如果是後端應用服務器需要某些數據,需要到數據庫里去拿數據,很可能應用服務器此時還會扮演客戶端角色,通過某種協議去數據庫拿數據;我們可以看到最終我們用戶看到的網頁里的內容,它來自很多服務器,所以說一個動態網站上由很多台服務器共同完成一個處理請求的結果,我們可以理解成,每個服務器處理自己擅長的事務,分工合作,最後把處理好的數據由代理響應給客戶端;
ngx_http_fastcgi_module:此模塊實現了nginx允許將用戶請求代理至fastcgi 服務器
1、fastcgi_pass address:設置fastcgi服務器的地址,此地址可以是IP加端口的形式,也可以是域名或者UNIX域套接字路徑;此選項可用於location 和if in location 配置段中
示例
fastcgi_pass localhost:9000
提示:以上配置意思是,通過fastcgi協議反代本機的9000端口上的服務響應;
fastcgi_pass Unix:/tmp/fastcgi.socket;
提示:以上表示設置fastcgi地址是本機/tmp/fastcgi.socket文件;
2、fastcgi_index name;設置fastcgi的默認主頁資源名稱;此指令可用於http、server、location配置段中
3、fastcgi_param parameter value [if_not_empty]:設置一個參數,用於傳遞給後端fastcgi服務器,參數的值可以是文本,變量,或者二者的組合。
示例
fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
提示:以上配置表示把SCRIPT_FILENAME等於/home/www/scripts/php$fastcgi_script_name傳遞給fastcgi服務器,$fastcgi_script_name表示用戶請求的腳本名稱;意思是告訴fastcgi服務器該把那個腳本執行了返回給客戶端(這裡的客戶端通常指代理服務器)
fastcgi_param QUERY_STRING $query_string;
提示:我們知道一個腳本傳遞不同的參數,執行的結果就會不同;以上配置表示把請求的腳本的參數通過QUERY_STRING變量保存,並傳遞給後端fastcgi服務器,讓其運行某腳本時,把QUERY_STRING保存的值作為參數傳遞給腳本;當然我們向後端傳遞的東西很多,不便一一寫出來,也不太可能一一寫到配置文件中,在nginx的配置目錄里有一個文件,專門存放nginx上的變量對應後端fastcgi服務器上的變量的一個配置文件fastcgi.conf 通常我們把這個配置文件用include指令來導入到我們需要定義nginx變量通過fastcgi變量傳遞給fastcgi服務器;
示例
location ~* .php$ { root /usr/share/nginx/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name; include fastcgi_params; }
提示:以上配置表示匹配用戶URI,如果用戶URI是以.php結尾的,就通過fastcgi協議代理至本機的127.0.0.1:9000端口進行處理(執行),fastcgi服務器默認主頁資源名叫index.php,並告訴fastcgi服務器到/usr/share/nginx/html/下去找用戶請求的資源腳本,如果還有其他參數和指令要傳遞,就使用/etc/nginx/fastcgi_params中的定義來把nginx的變量保存的值傳遞給後端fastcgi服務器,以上是反代動態php網頁的配置示例,有了以上配置 nginx就可以作為代理服務器響應客戶端請求動態腳本php的能力了;
[root@www nginx]# vim /etc/nginx/conf.d/proxy.conf server { server_name www.test.com; proxy_cache proxy_cache; # proxy_cache_key $request_uri; # proxy_cache_methods GET HEAD; proxy_cache_valid 200 302 15m; proxy_cache_valid 404 1m; # proxy_cache_use_stale http_500 http_502; location /en/docs/ { proxy_pass http://nginx.org; } location ~* /(.*).php$ { root /app/php_scripts; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /app/php_scripts$fastcgi_script_name; include /etc/nginx/fastcgi_params; } } ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ "conf.d/proxy.conf" 23L, 500C written [root@www nginx]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@www nginx]# mkdir /app/php_scripts -p [root@www nginx]# cat >> /app/php_scripts/test.php <?php phpinfo(); ?> ^C [root@www nginx]# cat /app/php_scripts/test.php <?php phpinfo(); ?> [root@www nginx]# nginx -s reload [root@www nginx]#
提示:在上面配置前需要先安裝好php-fpm,安裝好後需要更改/etc/php-fpm.d/www.conf里的user 和group,通常情況要看前端代理是用那個用戶啟動的,我們後端就用那個用戶啟動即可,我們前端代理商nginx,這裡需要更改成nginx即可,這樣修改後,保存配置,然後啟動php-fpm,然後在本機就可以看到127.0.0.1:9000就處於監聽狀態了;以上配置表示用戶請求.php結尾的資源都反代至127.0.01:9000進行處理;並且明確說明了後端fastcgi主頁資源名稱為index.php,後端應用服務器的根路徑為/app/php_scripts;fastcgi_param SCRIPT_FILENAME /app/php_scripts$fastcgi_script_name同nginx里的root alias指令的作用相同,指定用戶訪問的URI對應磁盤上的路徑,相當於指定後端fastcgi服務器的工作目錄吧;
提示:可以看到我們訪問test.php是能夠被php-fpm服務器執行並返回執行後的結果;
4、fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];此指令同proxy_cache_path一樣,作用定義fastcgi的代理緩存;其中levels表示定義緩存目錄的級別,最多3級,每級最多2個字符;keys_zone=name:size表示k/v映射的內存空間的名稱及大小;inactive=time表示非活動時長;max_size=size表示指定磁盤上用於緩存路徑的存放緩存的空間上限;
5、fastcgi_cache zone |off;調用指定的緩存空間來緩存數據;可用於http,server,location配置段中
6、fastcgi_cache_key string;定義用作緩存項的key的字符串;
7、fastcgi_cache_methods GET|HEAD|POST ……;定義那些請求方法使用緩存;默認是GET和HEAD
8、fastcgi_cache_min_uses number;定義緩存空間中的緩存項在inactive定義的非活動時間內至少要被訪問到此處所指定的次數方可被認為活動的緩存項,不被清理;
9、fastcgi_cache_valid[code] tiem;設定不同的響應碼各自緩存的時長;
10、fastcgi_keep_conn on | off;:設置是否保持連接,默認情況下,FastCGI服務器將在發送響應後立即關閉連接。但是,當這個指令被設置為值on時,nginx將指示FastCGI服務器保持連接打開。
示例
提示:在定義緩存空間時,必須要在http配置段定義,以上表示定義一個fastcgi的緩存空間,其名稱為php_cache,在內存中使用10m的空間,在物理磁盤上的路徑為/cache/proxy/php-fpm/目錄下,最大空間為2g;
提示:以上配置表示使用fastcgi的緩存空間php_cache,緩存key為$request_uri,就是把用戶請求的uri hash作為緩存路由,什麼意思呢,就是nginx查找緩存是通過hash什麼來查找緩存的,上面的配置就是定義nginx把用戶請求的URI作為hash對象;對用戶請求用的方法是GET 或HEAD方法時,使用緩存;緩存最小命中次數為3次,也就說在非活動時長內,該緩存項命中次數小於3次就會被認為該緩存是無效的,在下次檢查緩存的有效性,就會被清理;對響應碼是200 或302的資源緩存15分鐘,對404響應碼的資源緩存1分鐘;開啟和後端的fastcgi服務器的長連接;
提示:可以看到我們訪問test.php頁面時,在我們定義的緩存空間里生成了緩存,但是我們訪問了test.php這一個頁面,為什麼會緩存三項呢?其實我們可以打開瀏覽器的web開發者模式,查看它請求和響應的情況
提示:可以看到我們訪問test.php這個頁面,其背後是3次請求,所以我們在緩存空間里看到有三條緩存項,其實緩存空間里的緩存項每一個緩存項就代表一個緩存資源,我們是可以通過cat命令查看緩存項里的內容的;如下
提示:我們可以看到裏面的緩存項紀錄的信息,其中有一項KEY 就是我們指定的fastcgi_cache_key 說指定變量的值;我們查看緩存項里的內容很可能出現亂碼,原因是緩存的內容有二進制,或者其他字符編碼的內容;
以上就是nginx作為反向代理服務器代理動態資源的介紹,總結一點,nginx代理動態資源和代理http資源的思想是類似的,只是使用的指令不一樣;尤其對於緩存,兩者的思想幾乎完全一致,只是使用的模塊和指令不同而已;對於動態資源我們除了要指定被代理的地址外,還需要指定被代理端資源路徑,導入nginx變量與fastcgi變量對應的配置指令文件;對於緩存,兩者沒有什麼區別;