+4

HAProxy and keepalive

1. Reverse proxy là gì

Reverse proxy là một loại proxy server trung gian giữa một máy chủ và các clients gởi tới các yêu cầu. Nó kiểm soát yêu cầu của các clients, nếu hợp lệ, sẽ luân chuyển đến các servers thích ứng.

2. Load balancing

Cân bằng tải là một giải pháp chung cho việc phân phối các ứng dụng web theo chiều ngang trên nhiều host trong khi cung cấp cho người sử dụng một điểm truy cập duy nhất cho dịch vụ (chỉ duy nhất 1 domain truy cập). Nó nhằm mục đích tối ưu hóa việc sử dụng tài nguyên, giảm thiểu thời gian phản ứng, và tránh quá tải cho hệ thống trong mạng nhằm tăng khả năng sử dụng ứng dụng đồng thời và độ tin cậy của ứng dụng. Load balancing được thực hiện chủ yếu qua 2 cách:

  • Layer 4: TCP (layer transport - mô hình OSI)
  • Layer 7: HTTP (layer application - mô hình OSI)

Load balancing trên layer 4: sẽ chuyển tiếp những lưu lượng, dữ liệu đi qua nó dựa trên IP và port tương ứng (ví dụ có 1 request tới www.viblo.asia thì tất cả traffic sẽ được truyền tới 1 trong các server backend để xử lý tất cả request cho www.viblo.asia trên port 80). Tất cả các server trong web-backend sẽ phải có nội dung giống hệt nhau nếu không người dùng sẽ có thể nhận ra sự khác nhau đó khi truy cập tới domain tương ứng. Lưu ý là các web-backend phải connect tới cùng 1 database.

Load balancing trên layer 7: cho phép cân bằng tải để chuyển tiếp các request tới những server backend tương ứng dựa trên nội dung của request từ người dùng. Chế độ cân bằng tải này cho phép bạn chạy nhiều máy chủ web dưới cùng một tên miền và cổng.

Ví dụ: khi truy cập tới http://yourdomain.com/blog thì các request sẽ được gửi về 1 trong những máy chủ thuộc blog-backend mà chỉ chạy /blog. Những request khác thì trả về 1 trong các máy chủ web-backend để xử lý.

3. HAProxy

Có rất nhiều tool để xử lý vấn đề load balancing . Về mặt server thì có 2 tool nổi trội đó là: HAProxy và nginx. Để so sánh thì tác giả @Lê Tuấn Minh đã có bài tổng quan ở đây https://viblo.asia/le.tuan.minh/posts/XWkKAvyNzjy. Vì vậy mình muốn đi sâu hơn về phần cấu hình.

HAProxy (high availability proxy) là một phần mềm open source cân bằng tải giữa cả 2 giao thức TCP và HTTP. HAProxy đã được viết bởi Willy Tarreau trong C, nó hỗ trợ SSL, compressions, keep-alive, custom log và header rewriting. HAProxy là một máy chủ proxy và cân bằng tải nhanh và nhẹ với một bộ nhớ nhỏ và sử dụng ít tài nguyên CPU. Nó được sử dụng bởi các trang web lớn như Github, StackOverflow, Reddit, Tumblr, Twitter và những người khác. Nó đã trở thành cân bằng tải phần mềm phổ biến nhất và máy chủ proxy trong những năm qua.

4. Các thuật toán xử dụng trong HAProxy

  • Round Robin: Đây là thuật toán cân bằng đơn giản nhất. Đối với mỗi kết nối mới, nó sẽ được xử lý bởi các máy chủ backend tiếp theo. Nếu máy chủ backend cuối cùng trong danh sách được đạt tới, nó sẽ bắt đầu lại từ đầu danh sách backend.
  • Least Connections: Các kết nối mới sẽ được xử lý bởi các máy chủ backend với số lượng kết nối ít nhất. Điều này rất hữu ích khi thời gian và các request rất lớn.
  • Source: Đây là phiên dính, các IP của client sẽ được băm để xác định máy chủ backend đã nhận được yêu cầu cuối cùng từ IP này. Vì vậy, một IP A sẽ luôn được xử lý bởi backend1, và IP B sẽ luôn luôn được xử lý bởi banckend2 để không làm gián đoạn phiên.
  • Static Round Robin: Tương tự như Round Robin, mỗi máy chủ được sử dụng trong vòng lặp dựa trên weight. Nhưng thay đổi weight của máy chủ trên cũng không ảnh hưởng gì. Bạn có thể tự xác định bao nhiêu server mà bạn muốn. Khi một máy chủ tăng lên, nó sẽ luôn luôn được ngay lập tức đưa lại vào 1 bảng sau khi được tính toán lại weight.
  • URI: Thuật toán này băm hoặc phần bên trái của URI, hoặc toàn bộ URI và chia giá trị băm bằng tổng weight của máy chủ đang chạy. Cùng URI luôn hướng đến cùng một server miễn là không có máy chủ up hoặc down. Nó cũng là một thuật toán tĩnh và hoạt động theo cách tương tự như các thuật toán Source.
  • URL Parameter: Thuật toán tĩnh này chỉ có thể được sử dụng trên một backend HTTP. Các tham số URL được chỉ định sẽ được nhìn trong chuỗi truy vấn của mỗi yêu cầu HTTP GET. Nếu tham số đó được tìm thấy bởi một dấu hiệu và giá trị như nhau, giá trị được băm và chia cho tổng trọng lượng của máy chủ đang chạy.

4. Cấu hình HAProxy

Chuẩn bị:

  • 1 server HAProxy (Load Balancing - Ubuntu 16.04 - IP: 192.168.13.214)
  • 2 server backend (Ubuntu 14.04 - IP: 192.168.13.212 & 192.168.13.216)
  1. Trên HAProxy:
  • Install HAProxy:
# apt-get install haproxy
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  liblua5.3-0
Suggested packages:
  vim-haproxy haproxy-doc
The following NEW packages will be installed:
  haproxy liblua5.3-0
0 upgraded, 2 newly installed, 0 to remove and 73 not upgraded.
Need to get 872 kB of archives.
After this operation, 1,997 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
  • Check HAProxy enable
vim /etc/default/haproxy
ENABLED=1
  • Config HAProxy:
vim /etc/haproxy/haproxy.cfg

frontend nginx_lb
       bind 192.168.13.214:80 #listen trên port 80
       default_backend app #trỏ backend mặc định về app

backend app
        mode http #sử dụng layer 7. nếu muốn chuyển sang layer 4 thì thay "http" bằng "tcp"
        stats enable #enable status của haproxy
        stats uri /haproxy #uri của status haproxy
        balance roundrobin #dùng round robin để chia tải
        server server1 192.168.13.212:80 check #các server backend
        server server2 192.168.13.216:80 check

#nếu muốn sử dụng các thuật toán khác liên quan tới weight của server thì các bạn có thể set tại đây. ví dụ
#        server server1 192.168.13.212:80 weight 1 maxconn 512 check
#        server server2 192.168.13.216:80 weight 1 maxconn 512 check

  • Restart HAProxy: systemctl restart haproxy.service
  1. Trên backend
  • Cài nginx # apt-get install nginx
  • Sửa nội dung file html tĩnh vim /usr/share/nginx/html/index.html
  • Start nginx /etc/init.d/nginx restart

OK. giờ test thử nào

và check status của HAProxy theo url vừa đặt: http://192.168.13.214/haproxy

Vậy là đã LB qua HAProxy thành công. Nhưng mọi người có nhận thấy rằng 1 LB qua mạng là chưa đủ? Hệ thống sẽ ra sao nếu lượng truy cập rất lớn qua HAProxy? Client vẫn chỉ request qua HAProxy nên dễ dẫn tới bottleneck.

5. Keepalive

Để giải quyết bài toán bottleneck cho HAProxy, ta sẽ dựng 2 HAProxy - 1 làm master 1 làm slave để khi có vấn đề gì thì có đường backup kịp thời.

Chuẩn bị:

  • 2 server haproxy (192.168.13.214 - master, 192.168.13.222 - slave)
  • 2 server backend (192.168.13.212, 192.168.13.216) - ta có thể sử dụng luôn 2 server cũ (không cần cấu hình gì thêm)

Bắt đầu:

  1. Server haproxy master (192.168.13.214)
  • add virtual IP # ip address add 192.168.13.213/24 dev ens32
# ip addr

2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:9e:25:23 brd ff:ff:ff:ff:ff:ff
    inet 192.168.13.214/24 brd 10.0.1.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet 192.168.13.213/32 scope global ens32
       valid_lft forever preferred_lft forever
    inet 192.168.13.213/24 scope global secondary ens32
       valid_lft forever preferred_lft forever
  • cài đặt keepalive
# apt-get install keepalived
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  ipvsadm libsensors4 libsnmp-base libsnmp30
Suggested packages:
  heartbeat ldirectord lm-sensors snmp-mibs-downloader
The following NEW packages will be installed:
  ipvsadm keepalived libsensors4 libsnmp-base libsnmp30
0 upgraded, 5 newly installed, 0 to remove and 73 not upgraded.
Need to get 1,251 kB of archives.
After this operation, 4,902 kB of additional disk space will be used.
Do you want to continue? [Y/n] 

Để float IP có thể share cho HAProxy khác, các bạn enable config lên

# vim /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind=1

Config keepalive # vim /etc/keepalived/keepalived.conf

# Script used to check if HAProxy is running
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
# Virtual interface
# The priority specifies the order in which the assigned interface to take over in a failover
vrrp_instance VI_01 {
state MASTER
interface ens32
virtual_router_id 1
priority 101 # 101 on master, 100 on backup
# The virtual ip address shared between the two loadbalancers
virtual_ipaddress {
192.168.13.213
}
track_script {
check_haproxy
}
}

restart keepalive # service keepalived start

Lưu ý các bạn 1 chút là lúc nãy mình cấu hình HAProxy là chỉ để Listen trên port 80 của IP 192.168.13.214. Giờ mình sẽ chuyển về listen trên all nhé. sửa file /etc/haproxy/haproxy.cfg dòng bind *:80 nhé các bạn (tương tự server slave cũng vậy nhé) 2. Server HAProxy slave

  • Cài HAProxy
  • Cài keepalive
  • Config kêpalive # vim /etc/keepalived/keepalived.conf
# Script used to check if HAProxy is running
vrrp_script check_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
# Virtual interface
# The priority specifies the order in which the assigned interface to take over in a failover
vrrp_instance VI_01 {
state MASTER
interface ens32
virtual_router_id 1
priority 100 # 101 on master, 100 on backup
# The virtual ip address shared between the two loadbalancers
virtual_ipaddress {
192.168.13.213
}
track_script {
check_haproxy
}
}

ok. giờ test nhé.

  • Master (192.168.13.214) vẫn sống:

  • giờ mình down master đi nhé

~# ping 192.168.13.214
PING 192.168.13.214 (192.168.13.214) 56(84) bytes of data.
^C
--- 192.168.13.214 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 2999ms

-> die rồi.

# ip a

2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:9e:73:87 brd ff:ff:ff:ff:ff:ff
    inet 192.168.13.222/24 brd 10.0.1.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet 192.168.13.213/32 scope global ens32

-> vậy là server slave đã nhận được IP 192.168.13.213 của master rồi. check LB xem sao nhé phù. vẫn ăn nhé.

  • Giờ onl lại Master nhé:
# ping 192.168.13.214
PING 192.168.13.214 (192.168.13.214) 56(84) bytes of data.
64 bytes from 192.168.13.214: icmp_seq=1 ttl=64 time=0.192 ms
64 bytes from 192.168.13.214: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 192.168.13.214: icmp_seq=3 ttl=64 time=0.179 ms
64 bytes from 192.168.13.214: icmp_seq=4 ttl=64 time=0.110 ms
^C
--- 192.168.13.214 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.090/0.142/0.192/0.045 ms

root@ubuntu16:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:9e:73:87 brd ff:ff:ff:ff:ff:ff
    inet 192.168.13.222/24 brd 10.0.1.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet6 fe80::250:56ff:fe9e:7387/64 scope link 
       valid_lft forever preferred_lft forever

vâng. ngay khi master onl lại thì sv slave đã trả lại IP cho chính chủ rồi

2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:50:56:9e:25:23 brd ff:ff:ff:ff:ff:ff
    inet 192.168.13.214/24 brd 10.0.1.255 scope global ens32
       valid_lft forever preferred_lft forever
    inet 192.168.13.213/32 scope global ens32
       valid_lft forever preferred_lft forever

và tất nhiên LB vẫn không có vấn đề gì rồi.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí