要理解負載均衡,必須先搞清楚正向代理和反向代理
一、正向代理
正向代理相似一個跳板機,代理訪問外部資源,正向代理 是一個位於客戶端和原始服務器(origin server)之間的服務器,爲了從原始服務器取得內容,客戶端向代理髮送一個請求並指定目標(原始服務器),而後代理向原始服務器轉交請求並將得到的內容返回給客戶端。客戶端必需要進行一些特別的設置才能使用正向代理。
正向代理的用途:
(1)訪問原來沒法訪問的資源,如google
(2) 能夠作緩存,加速訪問資源
(3)對客戶端訪問受權,上網進行認證
(4)代理能夠記錄用戶訪問記錄(上網行爲管理),對外隱藏用戶信息
二、反向代理
客戶端是無感知代理的存在的,反向代理對外都是透明的,訪問者者並不知道本身訪問的是一個代理。由於客戶端不須要任何配置就能夠訪問。
反向代理(Reverse Proxy)實際運行方式是指以代理服務器來接受internet上的鏈接請求,而後將請求轉發給內部網絡上的服務器,並將從服務器上獲得的結果返回給internet上請求鏈接的客戶端,此時代理服務器對外就表現爲一個服務器。
反向代理的做用:
(1)保證內網的安全,可使用反向代理提供WAF功能,阻止web×××
大型網站,一般將反向代理做爲公網訪問地址,Web服務器是內網。
(2)負載均衡,經過反向代理服務器來優化網站的負載
三、nginx的負載均衡
nginx是經過反向代理實現網站的負載均衡。代理一臺機器爲代理,多臺機器,就叫負載均衡
Nginx負載均衡算法
(1)、輪詢(默認)
每一個請求按時間順序逐一分配到不一樣的後端服務,若是後端某臺服務器死機,自動剔除故障系統,使用戶訪問不受影響。
(2)、weight(輪詢權值)
weight的值越大分配到的訪問機率越高,主要用於後端每臺服務器性能不均衡的狀況下。或者僅僅爲在主從的狀況下設置不一樣的權值,達到合理有效的地利用主機資源。
(3)、ip_hash
每一個請求按訪問IP的哈希結果分配,使來自同一個IP的訪客固定訪問一臺後端服務器,而且能夠有效解決動態網頁存在的session共享問題。
(4)、fair 第三方
比 weight、ip_hash更加智能的負載均衡算法,fair算法能夠根據頁面大小和加載時間長短智能地進行負載均衡,也就是根據後端服務器的響應時間 來分配請求,響應時間短的優先分配。Nginx自己不支持fair,若是須要這種調度算法,則必須安裝upstream_fair模塊。
(5)、url_hash 第三方
按訪問的URL的哈希結果來分配請求,使每一個URL定向到一臺後端服務器,能夠進一步提升後端緩存服務器的效率。Nginx自己不支持url_hash,若是須要這種調度算法,則必須安裝Nginx的hash軟件包。
四、配置nginx負載均衡
經過dig能夠查看到域名的解析IP地址,若是沒有這個命令能夠安裝包 php
yum -y install bind-utils
咱們用dig解析www.qq.com獲得兩個IP,用來作實驗html
[root@lnmp-server ~]# dig www.qq.com ; <<>> DiG 9.9.4-RedHat-9.9.4-61.el7 <<>> www.qq.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12037 ;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;www.qq.com. IN A ;; ANSWER SECTION: www.qq.com. 95 IN A 59.37.96.63 www.qq.com. 95 IN A 58.60.9.21
上面獲得有兩個IP 59.37.96.63和58.60.9.21,用來模擬nginx負載均衡的後端機器
先新建一個虛擬主機配置文件linux
[root@lnmp-server ~]# vi /usr/local/nginx/conf/vhost/ld.conf #寫入如下內容 upstream qq { ip_hash; server 58.60.9.21:80; server 59.37.96.63:80; } server { listen 80; server_name www.qq.com; location / { proxy_pass http://qq; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
說明:nginx
upstream qq : upstream是一個模塊,qq是模塊名,這個名字能夠自定義,在代理的時候須要用到
ip_hash: nginx負載均衡算法之一,保持同一用戶始終在同一臺服務器上,能夠解決會話共享問題
server 兩臺機器:後端服務器,這裏用dig解析出來的兩臺來模擬
listen 80; #定義監聽端口
server_name www.qq.com; #定義域名
proxy_pass http://qq; ##upstream定義的名稱,這個名稱表明着upstream裏定義的ipweb
編輯完以後保存退出,先不要從新加載配置文件,先測試一下用本機ip去訪問www.qq.com這個域名看看結果會是什麼:算法
[root@lnmp-server vhost]# curl -x127.0.0.1:80 www.qq.com This is default server aaa
由於還沒加載配置,因此www.qq.com解析到默認虛擬主機去了
檢測配置是否有錯並重載配置vim
[root@lnmp-server ~]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@lnmp-server ~]# /usr/local/nginx/sbin/nginx -s reload
再用curl測試www.qq.com的結果windows
[root@lnmp-server ~]# curl -x127.0.0.1:80 www.qq.com
出現了qq網站的源代碼,說明配置成功
關於Nginx負載均衡方面要注意一點:
Nginx不支持直接代理https,只能代理http,也就是說443端口不支持只支持80端口。若是非要代理https,只能是用戶訪問Nginx代理服務器時使用https,而後Nginx去訪問後端的web服務器時使用http,屬於折中的一種方式,依然不能直接代理。後端
https就是使用ssl加密的http,是一種加密的超文本傳輸協議。若是http不加密的話,被人抓包或監聽了數據包,就能很輕易地看到數據包裏面的數據內容,那樣的話你的信息就泄露了。瀏覽器
若是使用的是https協議,那麼你的數據包就會被加密,即使被人抓包了,也沒有那麼輕易破解加密算法,由於數據包只能使用服務器上的私鑰解密,而服務器根本不會在任何狀況下發送私鑰,想要不經過私鑰來直接破解數據包幾乎是不可能的。
理解了ssl原理後,如今咱們能夠在虛擬機上去生成ssl密鑰對,也就是本身製做證書。咱們須要使用一個工具來生成密鑰對,把密鑰對放在nginx的conf目錄下
[root@lnmp-server ~]# cd /usr/local/nginx/conf/
生成ssl密鑰對須要使用到的工具是openssl,若是你虛擬機沒有此命令,須要本身安裝,安裝命令:
yum -y install openssl
生成私鑰
[root@lnmp-server conf]# openssl genrsa -des3 -out tmp.key 2048 Generating RSA private key, 2048 bit long modulus ........................................................................................................................................................+++ .....................+++ e is 65537 (0x10001) Enter pass phrase for tmp.key: Verifying - Enter pass phrase for tmp.key:
命令說明:生成rsa格式的私鑰,名字爲tmp.key 長度2048,生成的時候要求給tmp.key設置密碼
轉換key,取消密碼
因爲生成私鑰時設置了密碼,這樣每次訪問https的網頁時都須要輸入密碼,過於麻煩,所以能夠經過轉換key的方式將密碼取消
[root@lnmp-server conf]# openssl rsa -in tmp.key -out luo.key Enter pass phrase for tmp.key: writing RSA key
說明:把以前生成的須要密碼的tmp.key轉換成無需密碼的luo.key,這裏要求輸入以前給tmp.key設置的密碼
此時存在兩個key,tmp.key和luo.key,兩者的內容徹底相同,只是前者帶有密碼,後者沒有密碼,所以可將前者刪除
[root@lnmp-server conf]# rm -f tmp.key
生成證書請求文件
用轉換的私鑰luo.key生成證書請求文件luo.csr
[root@lnmp-server conf]# openssl req -new -key luo.key -out luo.csr You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]: State or Province Name (full name) []: Locality Name (eg, city) [Default City]: Organization Name (eg, company) [Default Company Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []: Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []:
說明 :這裏會要求你輸入一些信息,由於作實驗默認直接回車,若是是購買的正式證書要認真填寫,後期可能會用到
生成公鑰文件
用生成的證書請求文件luo.csr和私鑰文件luo.key一塊兒生成公鑰文件luo.crt
[root@lnmp-server conf]# openssl x509 -req -days 365 -in luo.csr -signkey luo.key -out luo.crt Signature ok subject=/C=XX/L=Default City/O=Default Company Ltd Getting Private key
生成完成後conf目錄有三個文件
[root@lnmp-server conf]# ll luo* -rw-r--r-- 1 root root 1103 7月 10 14:20 luo.crt -rw-r--r-- 1 root root 952 7月 10 14:15 luo.csr -rw-r--r-- 1 root root 1679 7月 10 14:11 luo.key
證書請求文件luo.csr,私鑰文件luo.key,公鑰文件luo.crt,至此,生成ssl密鑰對完成
生成完ssl密鑰對以後,須要在虛擬主機配置文件中配置ssl,這裏新建個ssl.conf配置文件
[root@lnmp-server conf]# vi /usr/local/nginx/conf/vhost/ssl.conf #加入如下內容 server { listen 443 ssl; server_name luo.com; index index.html index.php; root /data/wwwroot/luo.com; ssl on; ssl_certificate luolinux.crt; ssl_certificate_key luo.key; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; }
解析說明:
server { listen 443 ssl; #ssl監聽端口,格式不能寫錯 server_name luo.com; #網站域名 index index.html index.php; #支持的默認索引頁 root /data/wwwroot/luo.com; #網站根目錄 ssl on; #開啓ssl ssl_certificate luolinux.crt; #前面生成的公鑰文件 ssl_certificate_key luo.key; #前面生成的私鑰文件 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #支持的協議 }
檢測配置是否有錯
[root@lnmp-server conf]# /usr/local/nginx/sbin/nginx -t nginx: [emerg] unknown directive "ssl" in /usr/local/nginx/conf/vhost/lemssl.conf:7 nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
在檢測時出現了報錯,緣由是編譯Nginx時沒有添加ssl模塊,所以須要從新編譯Nginx,加上--with-http_ssl_modul,因此說源碼包不要刪除,後期增長一些配置的時候會用到:
cd /usr/local/src/nginx-1.12.1 ./configure --prefix=/usr/local/nginx --with-http_ssl_module make && make install
這裏省略從新編譯過程
從新檢測配置文件看到已經能夠識別ssl了,從新加載配置
[root@lnmp-server conf]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx//conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx//conf/nginx.conf test is successful [root@lnmp-server conf]# /usr/local/nginx/sbin/nginx -s reload
檢測端口是否有443
[root@lnmp-server conf]# netstat -lnp |grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 5661/nginx: master tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 5661/nginx: master
用https進行訪問測試
用curl測試不直觀,這裏咱們用windows機器綁定hosts進行測試,先編輯一下hosts文件,文件路徑爲:
C:\Windows\System32\drivers\etc/hosts,在後面寫入:
192.168.66.132 luo.com
在網站根目錄下新建個index.html測試文件
[root@lnmp-server conf]# cat /data/wwwroot/luo.com/index.html This is ssl test.
用瀏覽器進行https訪問
會提示一些不安全信息,這是由於瀏覽器不信任這個證書,點開高級-繼續前往
能夠看到,已經能正常https訪問了,想要沒有這些警告的話,能夠本身去買正規受信任的證書。咱們能夠訪問https://www.12306.cn看看,相信這個網站你們都不陌生,訪問它的https也是會有警告:
這不是由於政府沒錢買證書,而是不相信那些外部購買的證書,因此使用本身內部頒發的證書。
所以能夠知道,顯示這個警告的緣由僅僅是由於瀏覽器沒有承認這個證書,並不是是真的不安全
pool是PHP-fpm的資源池,若是多個站點共用一個pool,則可能形成資源池中的資源耗盡,最終訪問網站時出現502。
爲了解決上述問題,咱們能夠配置多個pool,不一樣的站點使用不一樣的pool,保證充足的資源
編輯php-fpm配置文件,增長一個新的pool
vim /usr/local/php-fpm/etc/php-fpm.conf [luo.com] //修改pool的名稱 listen = /tmp/luo.sock //修改sock文件名稱 listen.mode = 666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024 //其他選項按需更改
檢測文件&&重啓
/usr/local/php-fpm/sbin/php-fpm -t /etc/init.d/php-fpm reload
查看系統進程
php-fpm 5707 0.0 0.4 227488 4772 ? S 11:30 0:00 php-fpm: pool www php-fpm 5708 0.0 0.4 227488 4772 ? S 11:30 0:00 php-fpm: pool www php-fpm 5709 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool www php-fpm 5710 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool www php-fpm 5711 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool www php-fpm 5712 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool www php-fpm 5713 0.0 0.4 227488 4772 ? S 11:30 0:00 php-fpm: pool luo.com php-fpm 5714 0.0 0.4 227488 4772 ? S 11:30 0:00 php-fpm: pool luo.com php-fpm 5715 0.0 0.4 227488 4772 ? S 11:30 0:00 php-fpm: pool luo.com php-fpm 5716 0.0 0.4 227488 4772 ? S 11:30 0:00 php-fpm: pool luo.com php-fpm 5717 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool luo.com php-fpm 5718 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool luo.com php-fpm 5719 0.0 0.4 227488 4776 ? S 11:30 0:00 php-fpm: pool luo.com
發現新的pool已經添加成功
將站點添加至新的pool中
server { listen 80 default_server; server_name lem.com; index index.html index.htm index.php; root /data/wwwroot/luo.com; location ~ \.php$ { include fastcgi_params; fastcgi_pass unix:/tmp/luo.sock; //要使站點使用某個pool,須要修改這裏,sock文件與pool中保持一致 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /data/wwwroot/luo.com$fastcgi_script_name; //對應站點的文件名 } }
經過過include語法建立多個pool(相似於Nginx的vhost)
咱們能夠在php-fpm.conf配置中直接定義多個pool,也能夠把多個pool拆分紅不一樣的文件,編輯php-fpm配置文件,在[global]部分增長include = etc/php-fpm.d/*.conf這一行
[global] pid = /usr/local/php-fpm/var/run/php-fpm.pid error_log = /usr/local/php-fpm/var/log/php-fpm.log include = etc/php-fpm.d/*.conf
建立並進入include所對應的目錄
mkdir /usr/local/php-fpm/etc/php-fpm.d/ cd /usr/local/php-fpm/etc/php-fpm.d/
建立各個pool的.conf文件
[root@lnmp-server conf]# vim /usr/local/php-fpm/etc/php-fpm.d/luo.com.conf #寫入下面的內容 [luo.com] listen = /tmp/test.sock ;listen = 127.0.0.1:9000 listen.mode = 666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024
[root@lnmp-server conf]# vim /usr/local/php-fpm/etc/php-fpm.d/www.conf #寫入下面的內容 [www] listen = /tmp/php-fcgi.sock listen.mode = 666 user = php-fpm group = php-fpm pm = dynamic pm.max_children = 50 pm.start_servers = 20 pm.min_spare_servers = 5 pm.max_spare_servers = 35 pm.max_requests = 500 rlimit_files = 1024
能夠看到兩個pool的sock文件是不同,不一樣的站點想使用不一樣的pool,只要修改對應的sock文件便可,定義完成後主配置文件php-fpm.conf定義的pool能夠刪除歌者註釋掉
檢測並重載配置使其生效
/usr/local/php-fpm/sbin/php-fpm -t /etc/init.d/php-fpm reload
經過慢執行日誌,咱們能夠查看哪些PHP腳本執行的速度慢,很是實用,咱們能夠在站點使用的pool池中定義慢執行日誌
編輯pool的www.conf文件
vim /usr/local/php-fpm/etc/php-fpm.d/www.conf #在最後面增長下面兩行 request_slowlog_timeout = 2 //請求執行時間超出2秒鐘的日誌 slowlog = /usr/local/php-fpm/var/log/www-slow.log //定義慢執行日誌的位置
定義完後檢測並重載配置使其生效
/usr/local/php-fpm/sbin/php-fpm -t /etc/init.d/php-fpm reload
在pool對應的站點中編寫PHP測試腳本,故意使其執行慢
vim /data/wwwroot/test.com/sleep.php <?php echo "test slow log"; sleep(2); echo "done"; ?>
效果測試
[root@lnmp-server conf]# curl -x127.0.0.1:80 test.com/sleep.php test slow logdone[root@lnmp-server conf]# cat /usr/local/php-fpm/var/log/www-slow.log [10-Jul-2018 15:25:39] [pool www] pid 1107 script_filename = /data/wwwroot/test.com/sleep.php //執行時間超過設置時間(2秒)的「慢腳本」的名稱 [0x00007f0f364cb280] sleep() /data/wwwroot/test.com/sleep.php:3 //該腳本具體哪一行執行的慢
正常PHP腳本的執行時間在1~2秒之間,所以設置超過兩秒的腳本記錄慢執行日誌便可
open_basedir 的做用是限制php在指定的目錄裏活動。
在php.ini中修改會針對全部站點生效,具備必定侷限性,所以可在不一樣的pool中進行配置,相似於在Apache中的虛擬主機配置文件中進行配置。
配置open_basedir
vim /usr/local/php-fpm/etc/php-fpm.d/www.conf//在最後面加入下面一行 php_admin_value[open_basedir]=/data/wwwroot/test.com:/tmp/ #不一樣的站點定義不一樣的網站根目錄和活動目錄
能夠故意改錯open_basedir的路徑,並打開錯誤日誌,查看效果
修改php.ini配置文件
vim /usr/local/php-fpm/etc/php.ini
關閉瀏覽器報錯顯示
在生產環境中,直接將網站服務器報錯信息顯示在服務器上是不安全的,每每是將錯誤日誌記錄在指定的日誌文件中。在php.ini搜索關鍵字「display_errors"將其修改爲Off
; Production Value: Off ; http://php.net/display-errors display_errors = Off
打開錯誤日誌(在php.ini搜索關鍵字「log_errors"將其修改爲On)
; Production Value: On ; http://php.net/log-errors log_errors = On
定義錯誤日誌存放的路徑(搜索關鍵字log_errors,並在下面定義一行)
;error_log = php_errors.log ; Log errors to syslog (Event Log on Windows). ;error_log = syslog error_log =/usr/local/php-fpm/var/log/php_errors.log
定義日誌級別(搜索關鍵字error_reporting)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED ; Development Value: E_ALL ; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT ; http://php.net/error-reporting error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
建立錯誤日誌對應路徑文件,並賦予777權限
[root@lnmp-server conf]# touch /usr/local/php-fpm/var/log/php_errors.log [root@lnmp-server conf]# chmod 777 /usr/local/php-fpm/var/log/php_errors.log
配置完後檢測並重載
[root@lnmp-server conf]# /usr/local/php-fpm/sbin/php-fpm -t [10-Jul-2018 15:47:15] NOTICE: configuration file /usr/local/php-fpm/etc/php-fpm.conf test is successful [root@lnmp-server conf]# /etc/init.d/php-fpm reload Reload service php-fpm done
pm = dynamic //表示進程以動態的形式啓動,動態就是一開始爲一個數值,根據需求再自動生成,服務器比較閒的時候還會去銷燬,銷燬到必定程度還有自動生成;根據下面的設置去進行設定「start_servers 」、「min_spare_servers 」、「max_spare_servers 」、「max_requests 」
pm 也能夠設置成是 static ,也就是靜態,一旦選擇這個設置,下面的pm的各類設置只會有一個max_children生效