ภาพรวม
บทความนี้จะแสดงวิธีการกำหนดค่า HAProxy ให้ทำหน้าที่เป็น Load Balancer สำหรับเว็บเซิร์ฟเวอร์ Nginx สองเครื่อง (สามารถเปลี่ยนเป็น Apache ได้) โดยใช้ CentOS เป็นระบบปฏิบัติการโฮสต์ในทุกกรณี
HAProxy เป็นซอฟต์แวร์เซิร์ฟเวอร์ที่ให้ความพร้อมใช้งานสูง (High Availability) และการกระจายโหลด (Load Balancing) สำหรับแอปพลิเคชัน TCP และ HTTP โดยการกระจายคำขอเข้าไปยังเซิร์ฟเวอร์แบ็กเอนด์หลายเครื่อง HAProxy ถูกใช้งานในเว็บไซต์ยอดนิยมอย่าง Twitter, Instagram, GitHub, Amazon และอื่นๆ
HAProxy จะถูกติดตั้งบนเซิร์ฟเวอร์แยกต่างหากที่รับคำขอจากไคลเอนต์และส่งต่อไปยังเว็บเซิร์ฟเวอร์ Nginx สถาปัตยกรรมระบบทั่วไปแสดงในภาพด้านล่าง:

การกำหนดค่า Nginx บนเซิร์ฟเวอร์แบ็กเอนด์
เริ่มต้นด้วยการติดตั้งและกำหนดค่า Nginx บนเว็บเซิร์ฟเวอร์ที่จะมีการกระจายโหลด ติดตั้งที่เก็บ EPEL และ nginx โดยใช้ yum (หรือ dnf บน RHEL/CentOS 8):
# yum install epel-release -y
# yum install nginx -y
จากนั้น ในไฟล์ nginx.conf ให้ระบุว่าเซิร์ฟเวอร์ต้องประมวลผลคำขอจากเซิร์ฟเวอร์ HAProxy และเซิร์ฟเวอร์แบ็กเอนด์เท่านั้น:
เซิร์ฟเวอร์แบ็กเอนด์ที่ 1:
server {
listen current_server_IP_address:80 default_server;
allow second_backend_server_IP_address;
allow IP_haproxy;
deny all;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
}
เซิร์ฟเวอร์แบ็กเอนด์ที่ 2:
server {
listen current_server_IP_address:80 default_server;
allow first_backend_server_IP_address;
allow IP_haproxy;
deny all;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
}
}
ไฟล์กำหนดค่า Nginx เป็นค่าเริ่มต้น เราเพียงแค่เพิ่มการ listen IP และปฏิเสธการเข้าถึงจากทุกคนยกเว้นเซิร์ฟเวอร์ของเราโดยใช้คำสั่ง allow และ deny
เพื่อให้เว็บเซิร์ฟเวอร์ทำงานได้ ให้เปิดพอร์ต HTTP ในไฟร์วอลล์โดยใช้ firewalld หรือ iptables:
# firewall-cmd --permanent --add-service=http
# firewall-cmd --reload
ทดสอบการทำงานบนเซิร์ฟเวอร์แบ็กเอนด์ใดๆ:
# curl IP_of_the_second_server
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "https://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> here you will get an html file
เซิร์ฟเวอร์ส่งกลับไฟล์ดัชนีมาตรฐานของ Nginx เพื่อให้ตรวจสอบได้ง่ายขึ้น ผมได้เปลี่ยนเนื้อหาไฟล์ดัชนีบนเซิร์ฟเวอร์แบ็กเอนด์แต่ละเครื่องเพื่อดูในเบราว์เซอร์ว่าคำขอถูกประมวลผลโดยเซิร์ฟเวอร์ใด
ไฟล์ดัชนี Nginx ตั้งอยู่ที่ /usr/share/nginx/html/
การกำหนดค่า HAProxy Load Balancer
ติดตั้งและกำหนดค่า HAProxy บนเซิร์ฟเวอร์ที่จะใช้เป็น Load Balancer
ติดตั้ง HAProxy:
# yum install epel-release -y
# yum install haproxy -y
Running transaction Installing : haproxy-1.5.18-9.el7.x86_64 1/1 Verifying : haproxy-1.5.18-9.el7.x86_64 1/1 Installed: haproxy.x86_64 0:1.5.18-9.el7 Complete!
เพื่อเปิดใช้งาน HAProxy ให้เพิ่ม Enabled=1 ในไฟล์ /etc/default/haproxy:
# nano /etc/default/haproxy

ต่อไป มากำหนดค่า HAProxy ในการกำหนดค่าพื้นฐาน เซิร์ฟเวอร์ Load Balancer จะประมวลผลคำขอ HTTP ทั้งหมดและส่งต่อไปยังเซิร์ฟเวอร์แบ็กเอนด์สลับกัน:
# nano /etc/haproxy/haproxy.cfg
log /dev/log local0
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
frontend www
bind balancer_IP_address:80
default_backend nginx_pool
backend nginx_pool
balance roundrobin
mode http
server web1 IP_of_the_first_backend_server:80 check
server web2 IP_of_the_second_backend_server:80 check
หลังจากบันทึกการกำหนดค่า ให้ตรวจสอบไวยากรณ์ของ haproxy.cfg:
# haproxy -f /etc/haproxy/haproxy.cfg -c
ถ้าถูกต้อง จะได้ข้อความ:
Configuration file is valid
จากนั้นรีสตาร์ท HAProxy และเพิ่มเข้าไปในการเริ่มต้นของ Linux และเปิดพอร์ต HTTP ในไฟร์วอลล์:
# systemctl restart haproxy
# systemctl enable haproxy
# firewall-cmd --permanent --add-service=http
# firewall-cmd --reload
Load Balancer ถูกกำหนดค่าแล้ว ลองทดสอบโดยเปิด IP ของเซิร์ฟเวอร์ HAProxy ในเบราว์เซอร์:

ตามที่เห็น ทั้งสองเซิร์ฟเวอร์ส่งคืนเนื้อหาสลับกัน แสดงว่า Load Balancer ทำงานปกติ
พารามิเตอร์ไฟล์การกำหนดค่า Haproxy.cfg
พิจารณาอัลกอริทึมหลักของ HAProxy:
roundrobin— อัลกอริทึมเริ่มต้น ส่งคำขอไปยังเซิร์ฟเวอร์ทีละเครื่อง ใช้วิธีนี้ในตัวอย่างของเราleastconn— เลือกเซิร์ฟเวอร์ที่มีการเชื่อมต่อใช้งานน้อยที่สุด แนะนำสำหรับโครงการที่ใช้เซสชันนานๆsource— เลือกเซิร์ฟเวอร์จากแฮชของ IP ผู้ใช้ ในโหมดนี้ ไคลเอนต์จะเชื่อมต่อเซิร์ฟเวอร์เว็บเดียวกันถ้า IP ไม่เปลี่ยน
บล็อก global:
log— เขียนล็อกใน /dev/log โดยเก็บ local0 เป็นค่าออบเจ็กต์chroot— การตั้งค่าความปลอดภัย ล็อก HAProxy ไว้ในไดเรกทอรีที่ระบุmaxconn— จำนวนการเชื่อมต่อพร้อมกันสูงสุดต่อโปรเซสdaemon— รันโปรเซสเป็น daemon
บล็อก defaults:
บล็อกนี้ตั้งค่าพารามิเตอร์เริ่มต้นสำหรับทุกส่วนที่ตามมา:
log— กำหนดว่าล็อกจะเขียนที่ไหน (global หมายถึงใช้พารามิเตอร์จากส่วน global)mode— กำหนดโปรโตคอลการสื่อสาร: tcp, http หรือ healthretries— จำนวนครั้งที่ลองเชื่อมต่อเซิร์ฟเวอร์หากล้มเหลวoption httplog— รูปแบบล็อกถ้า HAProxy ทำหน้าที่เป็นพร็อกซี HTTPoption redispatch— อนุญาตให้โปรแกรมยกเลิกและส่งต่อเซสชันใหม่หากเซิร์ฟเวอร์ล้มเหลวcontimeout— เวลารอสูงสุดจนกว่าการเชื่อมต่อกับเซิร์ฟเวอร์จะสำเร็จ
ยังมีพารามิเตอร์ที่เกี่ยวกับ timeout หลายอย่าง
การรวบรวมสถิติ HAProxy
เพิ่มบล็อก stats ในไฟล์กำหนดค่า:
listen stats
bind :10001
stats enable
stats uri /haproxy_stats
stats auth admin:admin
คำอธิบาย:
bind— พอร์ตสำหรับดูสถิติstats enable— เปิดใช้งานรายงานสถิติstats uri— กำหนดที่อยู่หน้าสถิติstats auth— ชื่อผู้ใช้และรหัสผ่านสำหรับเข้าถึง
สามารถระบุพอร์ต TCP ใดก็ได้ หากพอร์ตข้างต้นใช้งานอยู่หรือไม่เหมาะสม
อนุญาตการเชื่อมต่อเข้าในพอร์ตที่ระบุในไฟร์วอลล์:
firewall-cmd --permanent --add-port=10001/tcp
firewall-cmd --reload
เพื่อดูรายงาน HAProxy ให้เข้าไปที่:
https://hostname_haproxy:10001/haproxy_stats

เปิด IP ของ Load Balancer ในเบราว์เซอร์และกด F5 ซ้ำๆ สถิติ HAProxy จะเปลี่ยนไป
บทความนี้ครอบคลุมการกำหนดค่า HAProxy ขั้นพื้นฐาน มีกรณีการใช้งาน HAProxy อื่นๆ อีกมาก
ในสถาปัตยกรรมของเรา เซิร์ฟเวอร์ HAProxy ที่ทำหน้าที่ Load Balancing กลายเป็น Single Point of Failure เพื่อเพิ่มความทนทานของบริการเว็บ สามารถเพิ่มเซิร์ฟเวอร์ HAProxy อีกเครื่องและใช้ Keepalived สำหรับการกำหนดค่า Load Balancer แบบ High Availability จะได้สถาปัตยกรรมแบบนี้:
