Thứ năm, 26/09/2013 | 00:00 GMT+7

Cách sử dụng HAProxy để thiết lập cân bằng tải HTTP trên VPS Ubuntu


Giới thiệu về HAProxy


HAProxy (Proxy khả dụng cao) là một trình cân bằng tải open-souce có thể cân bằng tải bất kỳ dịch vụ TCP nào. Nó đặc biệt thích hợp cho cân bằng tải HTTP vì nó hỗ trợ tính bền bỉ của phiên và xử lý lớp 7.

Với Mạng riêng DigitalOcean, HAProxy có thể được cấu hình như một giao diện user để cân bằng tải hai VPS thông qua kết nối mạng riêng.

Khúc dạo đầu


Ta sẽ sử dụng ba VPS ( server ) ở đây:

Server 1 - Cân bằng tải
Tên server : haproxy
Hệ điều hành: Ubuntu
IP công cộng: 1.1.1.1
IP riêng: 10.0.0.100

Server 2 - Nút 1
Tên server : lamp1
OS: LAMP trên Ubuntu
IP riêng: 10.0.0.1

Server 2 - Nút 2
Tên server : lamp2
OS: LAMP trên Ubuntu
IP riêng: 10.0.0.2

Cài đặt HAProxy


Sử dụng apt-get để cài đặt HAProxy.

apt-get install haproxy

Ta cần kích hoạt HAProxy được khởi động bởi init script.

nano /etc/default/haproxy

Đặt tùy chọn ENABLED thành 1

ENABLED=1

Để kiểm tra xem thay đổi này có được thực hiện đúng hay không, hãy thực hiện đúng tập lệnh init của HAProxy mà không có bất kỳ tham số nào. Bạn sẽ thấy những điều sau đây.

root@haproxy:~# service haproxy
Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}

Cấu hình HAProxy


Ta sẽ di chuyển file cấu hình mặc định và tạo file của riêng ta .

mv /etc/haproxy/haproxy.cfg{,.original}

Tạo và chỉnh sửa file cấu hình mới:

nano /etc/haproxy/haproxy.cfg

Hãy để ta bắt đầu bằng cách thêm từng đoạn cấu hình vào file này:

global
    log 127.0.0.1 local0 notice
    maxconn 2000
    user haproxy
    group haproxy

Chỉ thị log đề cập đến một server log hệ thống mà thông báo log sẽ được gửi đến. Trên Ubuntu rsyslog đã được cài đặt và chạy nhưng nó không nghe trên bất kỳ địa chỉ IP nào. Ta sẽ sửa đổi các file cấu hình của rsyslog sau.

Chỉ thị maxconn chỉ định số lượng kết nối đồng thời trên giao diện user . Giá trị mặc định là 2000 và phải được điều chỉnh theo cấu hình VPS của bạn.

Chỉ thị usergroup thay đổi quy trình HAProxy thành user / group được chỉ định. Những thứ này không nên thay đổi.

defaults
    log     global
    mode    http
    option  httplog
    option  dontlognull
    retries 3
    option redispatch
    timeout connect  5000
    timeout client  10000
    timeout server  10000

Ta đang chỉ định các giá trị mặc định trong phần này. Các giá trị được sửa đổi là các chỉ thị timeout khác nhau. Tùy chọn connect chỉ định thời gian tối đa để đợi nỗ lực kết nối đến VPS thành công.

Thời gian chờ của server clientserver áp dụng khi client hoặc server được mong đợi xác nhận hoặc gửi dữ liệu trong quá trình TCP. HAProxy khuyên bạn nên đặt thời gian chờ của server clientserver thành cùng một giá trị.

Lệnh retries đặt số lần thử lại sẽ thực hiện trên VPS sau khi kết nối không thành công.

option redispatch cho phép phân phối lại phiên trong trường hợp kết nối bị lỗi. Vì vậy, độ bám của phiên sẽ bị overrides nếu VPS gặp sự cố.

listen appname 0.0.0.0:80
    mode http
    stats enable
    stats uri /haproxy?stats
    stats realm Strictly\ Private
    stats auth A_Username:YourPassword
    stats auth Another_User:passwd
    balance roundrobin
    option httpclose
    option forwardfor
    server lamp1 10.0.0.1:80 check
    server lamp2 10.0.0.2:80 check

Điều này chứa cấu hình cho cả giao diện user và backend . Ta đang cấu hình HAProxy để lắng nghe trên cổng 80 cho appname mà chỉ là một tên để xác định một ứng dụng. Các stats thị stats cho phép trang thống kê kết nối và bảo vệ nó bằng xác thực HTTP Cơ bản sử dụng thông tin đăng nhập được chỉ định bởi chỉ thị stats auth .

Trang này có thể được xem bằng URL được đề cập trong stats uri vì vậy trong trường hợp này, nó là http://1.1.1.1/haproxy?stats ; một bản demo của trang này có thể được xem ở đây .

Chỉ thị balance chỉ định thuật toán cân bằng tải để sử dụng. Tùy chọn có sẵn là Round Robin ( roundrobin ), tĩnh Round Robin ( static-rr ), Connections Least ( leastconn ), Source ( source ), URI ( uri ) và URL tham số ( url_param ).

Thông tin về mỗi thuật toán có thể được lấy từ tài liệu chính thức .

Chỉ thị server khai báo một server backend , cú pháp là:

server <name> <address>[:port] [param*]

Tên ta đề cập ở đây sẽ xuất hiện trong log và cảnh báo. Có nhiều tham số được hỗ trợ bởi chỉ thị này và ta sẽ sử dụng tham số checkcookie trong bài viết này. Tùy chọn check cho phép kiểm tra tình trạng trên VPS, nếu không, VPS là
luôn được coi là có sẵn.

Khi bạn đã hoàn tất việc cấu hình , hãy bắt đầu dịch vụ HAProxy:

service haproxy start

Kiểm tra cân bằng tải và chuyển đổi dự phòng


Để kiểm tra cài đặt này, hãy tạo một tập lệnh PHP trên tất cả các web server của bạn ( server backend - LAMP1 và LAMP2 tại đây).

/var/www/file.php

<?php
header('Content-Type: text/plain');
echo "Server IP: ".$_SERVER['SERVER_ADDR'];
echo "\nClient IP: ".$_SERVER['REMOTE_ADDR'];
echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR'];
?>

Bây giờ ta sẽ sử dụng curl và yêu cầu file này nhiều lần.

> curl http://1.1.1.1/file.php

Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X

> curl http://1.1.1.1/file.php

Server IP: 10.0.0.2
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X

> curl http://1.1.1.1/file.php

Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X

Lưu ý ở đây cách HAProxy bật tắt kết nối giữa LAMP1 và LAMP2, đây là cách Round Robin hoạt động. IP client mà ta thấy ở đây là địa chỉ IP Riêng của bộ cân bằng tải và tiêu đề X-Forwarded-For là IP của bạn.

Để xem chuyển đổi dự phòng hoạt động như thế nào, hãy truy cập web server và dừng dịch vụ:

lamp1@haproxy:~#service apache2 stop

Gửi lại các yêu cầu bằng curl để xem mọi thứ hoạt động như thế nào.

Mức độ dính của phiên


Nếu ứng dụng web của bạn cung cấp nội dung động dựa trên các phiên đăng nhập của user (ứng dụng nào thì không), khách truy cập sẽ gặp phải những điều kỳ lạ do chuyển đổi liên tục giữa các VPS. Độ bám của phiên đảm bảo khách truy cập sẽ sử dụng VPS đã phục vụ yêu cầu đầu tiên của họ. Điều này có thể thực hiện được bằng cách gắn thẻ từng server backend với một cookie.

Ta sẽ sử dụng đoạn mã PHP sau để chứng minh cách hoạt động của độ dính phiên.

/var/www/session.php

<?php
header('Content-Type: text/plain');
session_start();
if(!isset($_SESSION['visit']))
{
        echo "This is the first time you're visiting this server";
        $_SESSION['visit'] = 0;
}
else
        echo "Your number of visits: ".$_SESSION['visit'];

$_SESSION['visit']++;

echo "\nServer IP: ".$_SERVER['SERVER_ADDR'];
echo "\nClient IP: ".$_SERVER['REMOTE_ADDR'];
echo "\nX-Forwarded-for: ".$_SERVER['HTTP_X_FORWARDED_FOR']."\n";
print_r($_COOKIE);
?>

Mã này tạo một phiên PHP và hiển thị số lần xem trang trong một phiên duy nhất.

Trong phương pháp này, tất cả các phản hồi từ HAProxy tới client sẽ chứa tiêu đề Set-Cookie: với tên của server backend làm giá trị cookie của nó. Vì vậy, về sau client (trình duyệt web) sẽ bao gồm cookie này với tất cả các yêu cầu của nó và HAProxy sẽ chuyển tiếp yêu cầu đến server backend phù hợp dựa trên giá trị cookie.

Đối với phương pháp này, bạn cần thêm chỉ thị cookie và sửa đổi chỉ thị server trong phần listen

   cookie SRVNAME insert
   server lamp1 10.0.0.1:80 cookie S1 check
   server lamp2 10.0.0.2:80 cookie S2 check

Điều này khiến HAProxy thêm tiêu đề Set-Cookie: với cookie có tên SRVNAME có giá trị là S1 hoặc S2 dựa vào đó chương trình backend trả lời yêu cầu. Sau khi điều này được thêm vào, hãy khởi động lại dịch vụ:

service haproxy restart

và sử dụng curl để kiểm tra cách thức hoạt động.

> curl -i http://1.1.1.1/session.php
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:11:22 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Set-Cookie: PHPSESSID=l9haakejnvnat7jtju64hmuab5; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 143
Connection: close
Content-Type: text/plain
Set-Cookie: SRVNAME=S1; path=/

This is the first time you're visiting this server
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
)

Đây là yêu cầu đầu tiên ta đưa ra và nó đã được LAMP1 trả lời như ta có thể thấy từ Set-Cookie: SRVNAME=S1; path=/ . Bây giờ, để mô phỏng những gì một trình duyệt web sẽ làm cho yêu cầu tiếp theo, ta thêm các cookie này vào yêu cầu bằng cách sử dụng tham số --cookie của curl.

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=l9haakejnvnat7jtju64hmuab5;SRVNAME=S1;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:11:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 183
Connection: close
Content-Type: text/plain

Your number of visits: 1
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.87.127
Array
(
    [PHPSESSID] => l9haakejnvnat7jtju64hmuab5
    [SRVNAME] => S1
)

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=l9haakejnvnat7jtju64hmuab5;SRVNAME=S1;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:11:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 183
Connection: close
Content-Type: text/plain

Your number of visits: 2
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.87.127
Array
(
    [PHPSESSID] => l9haakejnvnat7jtju64hmuab5
    [SRVNAME] => S1
)

Cả hai yêu cầu này đều được LAMP1 phục vụ và phiên được duy trì đúng cách. Phương pháp này rất hữu ích nếu bạn muốn có tất cả các file trên web server .


Mặt khác, nếu bạn chỉ muốn có độ dính cho các cookie cụ thể hoặc không muốn có một cookie riêng cho độ dính phiên, tùy chọn prefix là dành cho bạn.

Để sử dụng phương pháp này, hãy sử dụng lệnh cookie sau:

cookie PHPSESSID prefix

PHPSESSID có thể được thay thế bằng tên cookie của bạn . Chỉ thị server vẫn giống như cấu hình trước đó.

Bây giờ ta hãy xem cách này hoạt động.

> curl -i http://1.1.1.1/session.php
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:36:27 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Set-Cookie: PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 143
Content-Type: text/plain

This is the first time you're visiting this server
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
)

Lưu ý cách cookie server S1 được đặt trước cookie phiên. Bây giờ, hãy gửi thêm hai yêu cầu với cookie này.

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:36:45 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 163
Content-Type: text/plain

Your number of visits: 1
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
    [PHPSESSID] => 6l2pou1iqea4mnhenhkm787o56
)

> curl -i http://1.1.1.1/session.php --cookie "PHPSESSID=S1~6l2pou1iqea4mnhenhkm787o56;"
HTTP/1.1 200 OK
Date: Tue, 24 Sep 2013 13:36:54 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 163
Content-Type: text/plain

Your number of visits: 2
Server IP: 10.0.0.1
Client IP: 10.0.0.100
X-Forwarded-for: 117.213.X.X
Array
(
    [PHPSESSID] => 6l2pou1iqea4mnhenhkm787o56
)

Ta có thể thấy rõ rằng cả hai yêu cầu đều được LAMP1 phục vụ và phiên đang hoạt động hoàn hảo.

Cấu hình ghi log cho HAProxy


Khi ta bắt đầu cấu hình HAProxy, ta đã thêm một dòng: log 127.0.0.1 local0 notice log hệ thống đến địa chỉ IP localhost. Nhưng theo mặc định, rsyslog trên Ubuntu không lắng nghe trên bất kỳ địa chỉ nào. Vì vậy, ta phải làm cho nó làm như vậy.

Chỉnh sửa file cấu hình của rsyslog.

nano /etc/rsyslog.conf

Thêm / Chỉnh sửa / Bỏ ghi chú các dòng sau:

$ModLoad imudp
$UDPServerAddress 127.0.0.1
$UDPServerRun 514

Bây giờ rsyslog sẽ hoạt động trên cổng UDP 514 trên địa chỉ 127.0.0.1 nhưng tất cả các thông báo HAProxy sẽ chuyển đến /var/log/syslog nên ta phải tách chúng ra.

Tạo luật cho log HAProxy.

nano /etc/rsyslog.d/haproxy.conf

Thêm dòng sau vào nó.

if ($programname == 'haproxy') then -/var/log/haproxy.log

Bây giờ khởi động lại dịch vụ rsyslog:

service rsyslog restart

Điều này ghi tất cả các thông báo HAProxy và truy cập log vào /var/log/haproxy.log .

Keepalives trong HAProxy


Theo chỉ thị listen , ta đã sử dụng option httpclose để thêm tiêu đề Connection: close . Thao tác này cho client (trình duyệt web) đóng kết nối sau khi nhận được phản hồi.

Nếu bạn muốn bật keep-alives trên HAProxy, hãy thay thế dòng option httpclose bằng:

option http-server-close
timeout http-keep-alive 3000

Đặt thời gian chờ duy trì một cách khôn ngoan để một vài kết nối không tiêu hao hết tài nguyên của bộ cân bằng tải.

Thử nghiệm Keepalives

Keepalives có thể được kiểm tra bằng cách sử dụng curl bằng cách gửi nhiều yêu cầu cùng một lúc. Đầu ra không cần thiết sẽ được bỏ qua trong ví dụ sau:

> curl -v http://1.1.1.1/index.html http://1.1.1.1/index.html
* About to connect() to 1.1.1.1 port 80 (#0)
*   Trying 1.1.1.1... connected
> GET /index.html HTTP/1.1
> User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
> Host: 1.1.1.1
> Accept: */*
>
......[Output omitted].........
* Connection #0 to host 1.1.1.1 left intact
* Re-using existing connection! (#0) with host 1.1.1.1
* Connected to 1.1.1.1 (1.1.1.1) port 80 (#0)
> GET /index.html HTTP/1.1
> User-Agent: curl/7.23.1 (x86_64-pc-win32) libcurl/7.23.1 OpenSSL/0.9.8r zlib/1.2.5
> Host: 1.1.1.1
> Accept: */*
>
.......[Output Omitted].........
* Connection #0 to host 1.1.1.1 left intact
* Closing connection #0

Trong kết quả này, ta phải tìm dòng: Re-using existing connection! (#0) with host 1.1.1.1 , cho biết rằng curl đã sử dụng cùng một kết nối để thực hiện các yêu cầu tiếp theo.


Tags:

Các tin liên quan

Cách tạo Omega 4 Drupal Subtheme trên Ubuntu VPS
2013-09-26
Cách sử dụng tính năng trùng lặp với GPG để tự động hóa an toàn các bản backup trên Ubuntu
2013-09-19
Cách cấu hình một cụm đa node với Cassandra trên VPS Ubuntu
2013-09-11
Cách theo dõi log xác thực hệ thống trên Ubuntu
2013-09-05
Cách bắt đầu với Jekyll trên VPS Ubuntu
2013-08-28
Cách sử dụng Dig, Whois và Ping trên Ubuntu VPS để truy vấn dữ liệu DNS
2013-08-23
Cách thiết lập Sass trên VPS của bạn đang chạy trên Ubuntu
2013-08-14
Cách cài đặt Cassandra và chạy một cụm node đơn trên VPS Ubuntu
2013-08-08
Cách cài đặt CouchDB từ nguồn trên VPS Ubuntu 13.04 x64
2013-08-06
Cách quản lý gói trong Ubuntu và Debian với Apt-Get & Apt-Cache
2013-08-06