توازن بار (Load Balancing) به بهبود توزیع بار کاری بین چند منبع (نظیر شبکه، پردازنده، دیسک و …) گفته می شود. هدف از این کار چیه؟ بهبود استفاده از منابع، افزایش کارایی (Throughput)، کاهش زمان پاسخ گویی (Response Time) و جلوگیری از سرریز بار (Overload) بر روی یک منبع. HAProxy یک نرم افزار متن باز است که از آن به عنوان متوازن کننده بار و پراکسی عموما برای سرویس های تحت وب استفاده می شود. حتی از این ابزار برای توازن بار ترافیک TCP هم می توان استفاده کرد.

HAProxy برای این که نشان دهد چرا کارایی بالایی دارد یک سری ویژگی از معماری خود را لیست کرده که از آنها می توان به مواردی چون Event Driven، Zero-copy forwarding، O(1) event checker و … اشاره کرد.

در این پست می خواهیم با بهره گیری از یک HAProxy بار را بین سه سرویس تحت وب توزیع کنیم. یعنی چنین ساختاری:

توزیع بار با کمک HAProxy

من برای این که یه VM سبک داشته باشم Alpine رو انتخاب کردم. این توزیع از لینوکس معمولا به عنوان سیستم عامل پایه در سیستم های مبتنی بر Docker استفاده می شود. نسخه بهینه شده برای ماشین مجازی رو دانلود (حدودا ۴۹ مگابایت) و با دستور setup-alpine نصب کردم. با دستور زیر می توانید haproxy رو روی alpine نصب کنید.

apk update
apk add haproxy
rc-update add haproxy
rc-service haproxy start

پیکربندی HAProxy

وقتی haproxy رو نصب می کنید یک تنظیمات پیش فرض در مسیر

 /etc/haproxy/haproxy.cfg 

ایجاد می شود. پیش از هر اقدامی از این فایل کپی بگیرید و محتویات این فایل را به شکل زیر تغییر دهید.

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log         127.0.0.1 local2

    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4096
    user        haproxy
    group       haproxy
    daemon

#---------------------------------------------------------------------
# Common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block.
#---------------------------------------------------------------------
defaults
    #mode                   tcp|http
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option 		    http-server-close

    # Since HAProxy works in reverse-proxy mode, the servers see its IP address as
    # their client address. This is sometimes annoying when the client's IP address
    # is expected in server logs. To solve this problem, the well-known HTTP header
    # "X-Forwarded-For" may be added by HAProxy to all requests sent to the server.
    # This header contains a value representing the client's IP address.
    option forwardfor       except 127.0.0.0/8

    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                 2048

#---------------------------------------------------------------------
# Main frontend which proxys to the backends.
#---------------------------------------------------------------------
frontend lb-http
    bind 10.8.8.40:80
    http-request add-header X-Forwarded-Proto http
    default_backend http-nodes

#---------------------------------------------------------------------
# Round robin balancing between the various backends.
#---------------------------------------------------------------------
backend http-nodes
    balance roundrobin
    server  lvs-hap02 10.8.8.42:80 check
    server  lvs-hap03 10.8.8.43:80 check
    server  lvs-hap04 10.8.8.44:80 check

#---------------------------------------------------------------------
# Stats.
#---------------------------------------------------------------------
listen stats
    bind 10.8.8.41:8080
    mode http
    stats enable
    stats uri /
    stats hide-version
    stats realm HAProxy\ Statistics
    stats auth admin:passwd

این پیکربندی از ۵ بخش تشکیل شده است:

  • global، برخی تنظیمات عمومی مربوط به سرویس HAProxy
  • defaults، تنظیمات پیشفرضی که برای بقیه پیکربندی به طور مشترک اعمال می شود.
  • frontend، تنظیمات ورودی HAProxy
  • backend، تنظیمات سرور های پشتی (که قرار بار روشون توزیع بشه)
  • listen، تنظیمات ماژول آمارگیری از وضعیت HAProxy؛ در واقع با فعال کردن stats خود HAProxy بر روی آدرس مشخص شده در تنظیمات اطلاعات آماری ارائه می کنه. جزئیات بیشتر در مورد این ماژول را از اینجا مطالعه بفرمایید.

این هم نمونه خروجی آمار از HAProxy:

این آمار مربوط به حالتی است که سیستم زیر بار نیست!

در اینجا می تونید یک دمو از HAProxy را مشاهده کنید.

در بخش backend http-nodes سرویس های اصلی و الگوریتم توزیع بار بر روی آن ها مشخص می شود. الگوریتم هایی که haproxy از آن پشتیبانی می کند عبارتند از:

  • roundrobin، این الگوریتم پیش فرض است و درخواست دریافتی به نوبت به سرورهای پشتی فرستاده می شود.
  • leastconn، سروری انتخاب می شود که تعداد کانکشن کمتری به آن زده شده است. این الگوریتم زمانی که نیاز به جلسات طولانی تری داریم پیشنهاد می شود.
  • source، سرور بر اساس هش آدرس IP فرستنده درخواست انتخاب می شود. این متد تضمین می کند درخواست های یک کاربر به سرور یکسانی فرستاده می شود. (درخواست به درخواست، سرور تغییر نمیکنه!)

کلید check در این بخش بررسی میکنه سرورهای پشتی در حال سرویس دهی هستند و یا اینکه Down اند. این کار به صورت دوره ای انجام میشه تا درخواست به سرویسی که خاموش است ارسال نشود. در جدول آمار هم چون سرویس های پشتی ما Down بود با رنگ قرمز مشخص شده است.

در وب سایت HAProxy برای توازن بار ابزارهای دیگری به عنوان جایگزین HAProxy معرفی شده است. کلی منبع خوب مرتبط با HAProxy هم در اینجا فهرست شده است.

همه چیز به اینجا ختم نمی شود ان شاءالله در پست های آتی به نکات دیگری از توازن بار خواهم پرداخت.

مطلب مرتبط:
کامپایل و ساخت NGINX بر روی Ubuntu 18.04 LTS
ماژول وضعیت NginX و تولید خروجی JSON
مشکل PHP در هندل کردن چند درخواست موازی از یک کاربر