企業級反向代理 HAProxy
社群版網站:http://www.haproxy.org/ github:https://github.com/haproxy #選偶數版本,長期支援版本,不要選dev開發版 點版本下載的是原始碼,需要編譯安裝
haproxy ubuntu自帶了,如果要裝最新的包,就在社群版網站左側點debian包,選擇對應版本,會出現命令
根據命令執行,第一步不用,第二部實際上是新增倉庫
#紅帽系列沒有提供包安裝,那就採用原始碼編譯安裝吧 #注意需要lua支援,centos7的lua版本太低,需要先編譯lua,在編譯安裝haproxy
#範例:Ubuntu #安裝依賴包(這裡以為依賴順便把lua裝上了) [root@ubuntu2204 ~]#apt update && apt -y install gcc make libssl-dev libpcre3 libpcre3-dev zlib1g-dev libreadline-dev libsystemd-dev liblua5.4-dev #下載 [root@ubuntu2204 ~]#wget http://www.haproxy.org/download/2.8/src/haproxy-2.8.0.tar.gz [root@ubuntu2204 ~]#tar xf haproxy-2.8.0.tar.gz;cd haproxy-2.8.0/ #編譯安裝 (-j表示多程序並行編譯) [root@ubuntu2204 haproxy-2.8.0]#make -j 2 ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_PROMEX=1 USE_LUA=1 [root@ubuntu2204 haproxy-2.8.0]#make install PREFIX=/apps/haproxy
#準備配置檔案 [root@centos7 ~]# mkdir /etc/haproxy #方式1:複製原始碼中的範例配置檔案做為初始配置檔案 (必須cfg結尾) [root@haproxy haproxy-2.8.3]#cp examples/quick-test.cfg /etc/haproxy/haproxy.cfg
#設定使用者和目錄許可權 [root@centos7 ~]# useradd -m -r -s /sbin/nologin -d /var/lib/haproxy haproxy
#建立service檔案 [root@centos7 ~]#vim /usr/lib/systemd/system/haproxy.service [Unit] Description=HAProxy Load Balancer After=syslog.target network.target [Service] #啟動前檢查語法,有問題就別啟動了 ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid ExecReload=/bin/kill -USR2 $MAINPID LimitNOFILE=100000 #HAProxy能開啟的檔案個數 [Install] WantedBy=multi-user.target [root@centos7 ~]#systemctl daemon-reload [root@centos7 ~]#systemctl status haproxy.service #開機啟動 [root@centos7 ~]#systemctl enable --now haproxy.service
啟用狀態頁
#修改配置檔案(下面追加) [root@centos7 ~]#vim /etc/haproxy/haproxy.cfg #啟用狀態頁功能 listen stats mode http bind 0.0.0.0:9999 #狀態頁埠 stats enable log global stats uri /haproxy-status #狀態頁地址 stats auth admin:123456 #狀態頁使用者密碼 [root@centos7 ~]#systemctl reload haproxy.service #瀏覽器上檢視狀態頁 10.0.0.200:9999/haproxy-status
Haproxy 官方映象 https://hub.docker.com/_/haproxy/ 範例: 基於 Docker 安裝 Haproxy #cat haproxy.cfg global maxconn 100000 stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin uid 99 gid 99 daemon pidfile /var/lib/haproxy/haproxy.pid log 127.0.0.1 local3 info defaults option http-keep-alive option forwardfor maxconn 100000 mode http timeout connect 300000ms timeout client 300000ms timeout server 300000ms listen stats mode http bind 0.0.0.0:9999 stats enable log global stats uri /haproxy-status stats auth admin:123456 #新版 docker run -d --name my-running-haproxy -v /root/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro -p 9999:9999 --sysctl net.ipv4.ip_unprivileged_port_start=0 haproxy:2.8.2-alpine3.18 #舊版 docker run -d --name my-running-haproxy -v /root/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro -p 9999:9999 --sysctl net.ipv4.ip_unprivileged_port_start=0 haproxy:2.6.0-alpine3.16 #ip_unprivileged_port_start是最佳化,正常特權埠是1024以內埠,這裡設0表示所有埠都非特權埠,都能使用
HAProxy 的配置檔案haproxy.cfg由兩大部分組成,分別是global和proxies部分 global:全域性配置段 proxies:代理配置段
chroot /apps/haproxy #鎖定執行目錄(安全,只能訪問這個目錄下,被駭客控制也只能在這個目錄下) deamon #以守護程序執行 stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #socket檔案,並可以透過此檔案管理,新版不再支援多程序 stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin process 1 #socket檔案,並可以透過此檔案管理,舊版指定程序 user, group, uid, gid #執行haproxy對應worker程序的使用者身份 #nbproc n #開啟的haproxy worker 程序數,預設程序數是一個, nbproc從HAProxy 2.5開始不再支援 nbthread 1 #預設值auto,和多程序 nbproc配置互斥(版本有關,CentOS8的haproxy1.8無此問題),指定每個haproxy程序開啟的執行緒數,預設為每個程序一個執行緒 #如果同時啟用nbproc和nbthread 會出現以下日誌的錯誤,無法啟動服務,此項不指定,預設為auto,即也可以實現自動生成和CPU核數相同的執行緒數 Apr 7 14:46:23 haproxy haproxy: [ALERT] 097/144623 (1454) : config : cannot enable multiple processes if multiple threads are configured. Please use either nbproc or nbthread but not both. #注意:下面方式不支援執行緒繫結 #cpu-map 1 0 #繫結haproxy worker 程序至指定CPU,將第1個worker程序繫結至0號CPU #cpu-map 2 1 #繫結haproxy worker 程序至指定CPU,將第2個worker程序繫結至1號CPU cpu-map auto:1/1-8 0-7 #haproxy2.4中啟用nbthreads,在global配置中新增此選項,可以進行自動的執行緒和CPU的繫結,nbproc選項2.5版本中將會刪除,每個程序中1-8個執行緒分別繫結0-7號CPU,注意:新版用此項進行執行緒繫結 maxconn n #每個haproxy程序的最大併發連線數 maxsslconn n #每個haproxy程序ssl最大連線數,用於haproxy 配置了證書的場景下 maxconnrate n #每個程序每秒建立的最大連線數量 #haproxy可以主動檢查,nginx只能被動檢查(訪問了再檢查)。下面引數可以讓檢查請求前後時間錯開 spread-checks n #後端server狀態check隨機提前或延遲百分比時間,建議2-5(20%-50%)之間,預設值0 pidfile #指定pid檔案路徑 log 127.0.0.1 local2 info #定義全域性的syslog伺服器;日誌伺服器需要開啟UDP協議,最多可以定義兩個
#語法檢查 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q #修改haproxy對應worker程序的使用者身份(縮排沒關係) [root@ubuntu ~]#vim /etc/haproxy/haproxy.cfg global user haproxy group haproxy [root@ubuntu ~]#systemctl reload haproxy.service #檢視是否生效 [root@ubuntu ~]#ps auxf|grep haproxy
HAProxy 支援利用rsyslog服務記錄日誌到指定日誌檔案中
HAProxy配置
#在global配置項定義: log 127.0.0.1:514 local{0-7} info #基於syslog記錄日誌到指定裝置,級別包括:err、warning、info、debug 透過514埠接受日誌 local自定義日誌,用0-7中的某一個 #例: log 127.0.0.1:514 local6 info listen web_port bind 127.0.0.1:80 mode http log global #開啟當前web_port的日誌功能,預設不記錄日誌 server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5 # systemctl reload haproxy.service
Rsyslog配置
vim /etc/rsyslog.conf $ModLoad imudp $UDPServerRun 514 #監聽514 ...... local6.info /var/log/haproxy.log #日誌寫入位置(這個配置也可以寫在只配置檔案中) ...... # systemctl restart rsyslog
defaults [<name>] #預設配置項,針對以下的frontend、backend和listen生效,可以多個name也可以沒有name listen <name> #將frontend和backend合併在一起配置,相對於frontend和backend配置更簡潔,生產常用 frontend <name> #前端servername,類似於Nginx的一個虛擬主機 server和LVS服務叢集。 backend <name> #後端伺服器組,等於nginx的upstream和LVS中的RS伺服器
[root@ubuntu ~]#vim /etc/rsyslog.conf global ... listen webservers #起個名字 bind 192.168.10.200:80 #本機監聽地址 server web1 10.0.0.201:80 server web2 10.0.0.202:80 [root@ubuntu ~]#systemctl reload haproxy.service #注意這時候,如果一個後端掛了,haproxy不會去監測,依然會把請求打上去 #追加健康檢查 [root@ubuntu ~]#vim /etc/rsyslog.conf listen webservers bind 192.168.10.200:80 #本機監聽地址 server web1 10.0.0.201:80 check #自動定期檢查後端,預設2s(L4只查埠開沒開,不嚴謹) #每1s檢查後端,5次失敗就異常,3次成功才算恢復正常,權重3,最大連線數10000 server web2 10.0.0.202:80 check inter 1000 fall 1 rise 3 weight 3 maxconn 10000 server localhost 127.0.0.1:80 redir http://www.baidu.com #重定向到百度 [root@ubuntu ~]#systemctl reload haproxy.service
server配置
#針對一個server配置 check #對指定real進行健康狀態檢查,如果不加此設定,預設不開啟檢查,只有check後面沒有其它配置也可以啟用檢查功能 #預設對相應的後端伺服器IP和埠,利用TCP連線進行週期性健康性檢查,注意必須指定埠才能實現健康性檢查 addr <IP> #可指定的健康狀態監測IP,可以是專門的資料網段,減少業務網路的流量 port <num> #指定的健康狀態監測埠 inter <num> #健康狀態檢查間隔時間,預設2000 ms fall <num> #後端伺服器從線上轉為線下的檢查的連續失效次數,預設為3 rise <num> #後端伺服器從下線恢復上線的檢查的連續有效次數,預設為2 weight <weight> #預設為1,最大值為256,0(狀態為藍色)表示不參與負載均衡,但仍接受持久連線 backup #將後端伺服器標記為備份狀態,只在所有非備份主機down機時提供服務,類似Sorry Server disabled #將後端伺服器標記為不可用狀態,即維護狀態,除了持久模式,將不再接受連線,狀態為深黃色,支援優雅平滑下線,繼續處理舊請求,不接受新請求 maxconn <maxconn> #指定每個後端server的最大併發連線數,放在,放在server 指令後面 redir http://www.baidu.com #將請求臨時(302)重定向至其它URL,只適用於http模式,放在server 指令後面
redirect 配置
#注意:此指令和redir功能相似,但不屬於server指令後面,是獨立存放在listen,frontend,backend語句塊 redirect prefix http://www.baidu.com/ #將請求臨時(302)重定向至其它URL,只適用於http模式
#把listen拆成前端frontend,後端backen [root@ubuntu ~]#vim /etc/rsyslog.conf frontend web-http-80 bind 192.168.10.200:80 #本機監聽地址 use_backend httpservers1 #排程到指定後端 backend httpservers1 #後端有兩臺 server web1 10.0.0.201:80 check server web2 10.0.0.202:80 check backend httpservers2 #可以寫多組後端 server web2 10.0.0.202:80 check [root@ubuntu ~]#systemctl reload haproxy.service
#存放業務配置 [root@ubuntu ~]#mkdir /etc/haproxy/conf.d [root@ubuntu ~]#vim /etc/haproxy/conf.d/www.magedu.org.cfg #修改service檔案 [root@centos7 ~]#vim /usr/lib/systemd/system/haproxy.service [Unit] Description=HAProxy Load Balancer After=syslog.target network.target [Service] #追加語法檢查 ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d -c -q #追加配置檔案目錄 ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d -p /var/lib/haproxy/haproxy.pid ExecReload=/bin/kill -USR2 $MAINPID LimitNOFILE=100000 [Install] WantedBy=multi-user.target [root@centos7 ~]#systemctl daemon-reload [root@centos7 ~]#systemctl restart haproxy.service
HAProxy動態: 可以動態修改後端伺服器的權重,平滑修改
動態修改用Socat工具控制 (透過socket連線)
#提前配置socket檔案路徑 [root@ubuntu2204 ~]#vim /etc/haproxy/haproxy.cfg global stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin [root@ubuntu2204 ~]#systemctl reload haproxy.service #安裝socat [root@ubuntu1804 ~]#apt update && apt -y install socat [root@centos ~]#yum -y install socat #檢視當前socket支援的指令 [root@centos7 ~]#echo "help" | socat stdio /var/lib/haproxy/haproxy.sock [root@centos7 ~]#echo "show version" | socat stdio /var/lib/haproxy/haproxy.sock #顯示當前執行的任務 [root@centos7 ~]#echo "show tasks" | socat stdio /var/lib/haproxy/haproxy.sock #檢視後端 [root@centos7 ~]#echo "show backend" | socat stdio /var/lib/haproxy/haproxy.sock #顯示資訊 [root@centos7 ~]#echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock #檢視server狀態 ..."show servers state" #獲取權重(伺服器分組名/服務名) ..."get weight webservers/web1" #修改權重 ..."set weight webservers/web1 6" #禁用服務 ..."disable server webservers/web1" #恢復服務 ..."enable server webservers/web1"
6.1 基於 Cookie 的會話保持
6.2 HAProxy 狀態頁
6.3 IP透傳
四層透傳沒意義,後面nginx無法解析
6.4 報文修改
6.5 自定義日誌格式
6.6 壓縮功能
6.7 後端伺服器健康性監測
6.8 ACL (比nginx和lvs強大的地方)
frontend httpserver bind 192.168.10.100:80 acl acl_static path_beg -i /static http-request deny if HTTP_1.0 #拒絕http1.0 use_backend pc_hosts if acl_static default_backend mobile_hosts backend pc_hosts server web01 10.0.0.201:80 backend mobile_hosts server web02 10.0.0.202:80
defaults #option forwardfor #no option http-use-htx 支援html檔案,此設定和版本有關,2.1不支援 #...... #加下面行 errorfile 500 /usr/local/haproxy/html/500.http errorfile 502 /usr/local/haproxy/html/502.http errorfile 503 /usr/local/haproxy/html/503.http #範例: [root@centos7 ~]#vim /etc/haproxy/haproxy.cfg defaults ... errorfile 503 /apps/haproxy/html/503.http listen ....... [root@centos7 ~]#vim /apps/haproxy/html/503.http HTTP/1.1 503 Service Unavailable Content-Type:text/html;charset=utf-8 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>報錯頁面</title> </head> <body> <center><h1>網站維護中......請稍候再試</h1></center> <center><h2>聯絡電話:400-123-4567</h2></center> <center><h3>503 Service Unavailable</h3></center> </body> [root@centos7 ~]#systemctl restart haproxy #將後端伺服器down,可以觀察到以下頁面
listen redis-port bind 10.0.0.7:6379 mode tcp balance leastconn server server1 10.0.0.17:6379 check server server2 10.0.0.27:6379 check backup
範例:對 MySQL 服務實現四層負載
[root@centos7 ~]#vim /etc/haproxy/haproxy.cfg listen wang_mysql bind 10.0.0.7:3306 mode tcp balance leastconn server mysql1 10.0.0.17:3306 check server mysql2 10.0.0.27:3306 check #如果不寫埠號,可以轉發,但無法check狀態 #或者使用frontend和backend實現 frontend mysql bind :3306 mode tcp #必須指定tcp模式 default_backend mysqlsrvs backend mysqlsrvs mode tcp #必須指定tcp模式 balance leastconn server mysql1 10.0.0.17:3306 server mysql2 10.0.0.27:3306 [root@centos7 ~]#systemctl restart haproxy #在後端伺服器安裝和配置mariadb服務 [root@centos7 ~]#yum -y install mariadb-server [root@centos7 ~]#mysql -e "grant all on *.* to test@'10.0.0.%' identified by '123456'" [root@centos7 ~]#vim /etc/my.cnf [mysqld] server-id=17 #在另一臺主機為27 [root@centos7 ~]#systemctl start mariadb
[root@centos7 ~]#cat /etc/haproxy/conf.d/test.cfg frontend wang_http_port bind 10.0.0.7:80 ###################### https setting ############################## bind 10.0.0.7:443 ssl crt /etc/haproxy/certs/haproxy.pem redirect scheme https if !{ ssl_fc } # 注意{ }內的空格 default_backend pc_hosts backend mobile_hosts server web1 10.0.0.17:80 backend pc_hosts server web2 10.0.0.27:80