Продукты Р7
Корпоративный сервер 2024
Корпоративный сервер 2024
Сервер документов
Сервер документов
Редакторы
Редакторы
Корпоративный сервер 2019
Корпоративный сервер 2019
Графика
Графика
Команда
Команда
Мобильные редакторы
Мобильные редакторы
Облачный офис
Облачный офис
Почта
Почта
Органайзер
Органайзер
Дополнительно
Часто задаваемые вопросы
Разработчикам
Интеграции
Новые возможности

Пример реализации балансировщика HAproxy для архитектуры High Available

Обновлено: 25.12.25
Уточнение

HAProxy — это программное обеспечение балансировки нагрузки и прокси-сервер, который часто используется в кластерах для распределения запросов по различным серверам баз данных. HAProxy принимает запросы от клиентов и направляет их к соответствующим серверам в кластере, чтобы достичь балансировки нагрузки и повысить производительность кластера. Адресация на кластера будет производится согласно портам сервисов.

1. Установка и запуск сервиса

dnf install haproxy
systemctl enable haproxy --now

2. Настройка

В файле /etc/haproxy/haproxy.cfg укажите адреса нод кластеров PostgreSQL, RabbitMQ, Redis:

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    #
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    #
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    log /dev/log local0
    log /dev/log local1 notice
    #chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
    maxconn     4000
    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
    log                     global
    retries                 3
    timeout queue           5s
    timeout connect         10s
    timeout client          30m
    timeout server          30m
    timeout check           10s

listen stats
    mode http
    bind :7000
    stats enable
    stats uri /

### PostgreSQL ###
listen postgres_master
    bind :5000
    option tcplog
    option tcpka
    option httpchk OPTIONS /master
    http-check expect status 200
    default-server inter 3s fastinter 1s fall 3 rise 4 on-marked-down shutdown-sessions
    server psql1 192.168.27.239:5432 check port 8008 #адрес первой ноды БД
    server psql2 192.168.27.219:5432 check port 8008 #адрес второй ноды БД
    server psql3 192.168.27.108:5432 check port 8008 #адрес третьей ноды БД

listen postgres_replicas
    bind :5001
    option tcplog
    option httpchk OPTIONS /replica
    balance roundrobin
    http-check expect status 200
    default-server inter 3s fastinter 1s fall 3 rise 2 on-marked-down shutdown-sessions
    server psql1 192.168.27.239:5432 check port 8008 #адрес первой ноды БД
    server psql2 192.168.27.219:5432 check port 8008 #адрес второй ноды БД
    server psql3 192.168.27.108:5432 check port 8008 #адрес третьей ноды БД
### PostgreSQL ###

### RabbitMQ ###
listen rabbitmq
    bind :5672
    mode tcp
    balance roundrobin
    server rabmq1 rabmq1.localdomain:5672 check inter 2s rise 2 fall 3 #адрес первой ноды брокера сообщений
    server rabmq2 rabmq2.localdomain:5672 check inter 2s rise 2 fall 3 #адрес второй ноды брокера сообщений
    server rabmq3 rabmq3.localdomain:5672 check inter 2s rise 2 fall 3 #адрес третьей ноды брокера сообщений

listen rabbitmq_management
    bind :15672
    balance source
    server rabmq1 rabmq1.localdomain:15672 check inter 2s #адрес первой ноды брокера сообщений
    server rabmq2 rabmq2.localdomain:15672 check inter 2s #адрес второй ноды брокера сообщений
    server rabmq3 rabmq3.localdomain:15672 check inter 2s #адрес третьей ноды брокера сообщений
### RabbitMQ ###

### Redis ###
frontend redis_master
  bind :6379
  mode tcp
  option tcplog
  option clitcpka
  timeout client 24h
  default_backend redis_master

backend redis_master
  balance first
  mode tcp
  timeout queue 2s
  timeout connect 2s
  timeout check 1s
  option srvtcpka
  timeout server 24h
  option tcp-check
  tcp-check connect
  tcp-check send AUTH\ SecretPassword\r\n #укажите пароль для мастера из пункта 3.2
  tcp-check send PING\r\n

  tcp-check expect string +PONG
  tcp-check send info\ replication\r\n 
  tcp-check expect string role:master
  tcp-check send QUIT\r\n

  tcp-check expect string +OK
  server redis1 192.168.27.208:6379 check inter 5s
  server redis2 192.168.27.133:6379 check inter 5s
  server redis3 192.168.27.185:6379 check inter 5s
### Redis ###

2.1. Команды для проверки работы

haproxy -f /etc/haproxy/haproxy.cfg -d — для проверки конфигурации

systemctl status haproxy — для проверки статуса сервиса

3. Дополнительные ноды для отказоустойчивости (опционально)

Для минимизации времени простоя сервера с внутренним балансером возможно реализовать отказоустойчивый кластер с использованием нескольких экземпляров HAProxy.

Для реализации потребуется дополнительный IP адрес в сети, рекомендуется использовать внутренний для обеспечения безопасности доступа к кластерами других нод. Ноды будут использовать один виртуальный IP адрес при обращении к сервисам PostgreSQL, RabbitMQ, Redis.

В статье используется внутренний IP адрес 192.168.26.27 как VRRP (Virtual Router Redundancy Protocol) — это сетевой протокол, предназначенный для обеспечения отказоустойчивости маршрутизаторов или шлюзов в локальной сети. При настройке использовался на сервере с одним портом с внутренним IP.

В дальнейшем к этому интерфейсу будет привязан виртуальный адрес 192.168.26.27 Это один общий IP-адрес, который является точкой входа для всех клиентов, обращающихся к балансировщику. Этот адрес не привязан постоянно к одному серверу. Вместо этого, служба Keepalived настраивается на обоих узлах кластера и определяет, какой из серверов в данный момент является «основным» (MASTER). Только на этом основном сервере в данный момент активен Виртуальный IP-адрес.

Если основной сервер или служба HAProxy на нем выходит из строя, Keepalived автоматически обнаружит это и переключит статус MASTER на второй сервер, который затем «поднимет» Виртуальный IP-адрес уже у себя. Клиенты при этом продолжают обращаться к тому же Виртуальному IP, не замечая переключения.

3.1. Установка

На основной ноде потребуется дополнительно установить сервис:

dnf install keepalived -y

На всех дополнительных нодах потребуется установка сервисов:

dnf install haproxy keepalived -y

Далее, добавьте в автозагрузку:

systemctl enable keepalived haproxy

3.2. Настройка

3.2.1. На основной ноде

3.2.1.1. Создайте каталог
mkdir -p /usr/libexec/keepalived

Далее, создайте файл /usr/libexec/keepalived/haproxy_check.sh с содержимым:

#!/bin/bash
/bin/kill -0 $(cat /var/run/haproxy.pid)

Скрипт проверяет, запущен ли процесс HAProxy, используя его PID для мониторинга состояния службы.

3.2.1.2. Измените конфигурацию /etc/keepalived/keepalived.conf
global_defs {
  router_id haproxy-server1
  enable_script_security
  script_user root
}

vrrp_script haproxy_check {
  script "/usr/libexec/keepalived/haproxy_check.sh"
  interval 1
  weight -20
  fall 2
  rise 2
}

vrrp_instance VI_1 {
  interface ens3
  virtual_router_id 101
  priority 100
  advert_int 1
  state MASTER
  virtual_ipaddress {
    192.168.26.27
  }
  track_script {
    haproxy_check weight 20
  }
  authentication {
    auth_type PASS
    auth_pass SecretPassword
  }
}

Где введённые параметры:

  • router_id — ID роутера, уникальное значение на каждом узле;
  • script_user — пользователь, от имени которого будут запускаться скрипты VRRP;
  • interface — наименование интерфейса, к которому будет привязан keepalived;
  • virtual_router_id — ID виртуального роутера, общее значение на всех узлах;
  • priority — приоритет нод внутри виртуального роутера;
  • state — тип роли ноды в виртуальном роутере;
  • virtual_ipaddress — виртуальный IP;
  • auth_type — тип аутентификации в виртуальном роутере;
  • auth_pass — указывается пароль.

3.2.2. На дополнительных нодах

3.2.2.1. Скопируйте ранее установленные значения из /etc/hosts и укажите значения на новых нодах
3.2.2.2. Скопируйте конфигурацию /etc/haproxy/haproxy.cfg и укажите конфигурацию на новых нодах
3.2.2.3. Создайте каталог
mkdir -p /usr/libexec/keepalived

Создайте файл /usr/libexec/keepalived/haproxy_check.sh с содержимым:

#!/bin/bash
/bin/kill -0 $(cat /var/run/haproxy.pid)
3.2.2.4. Измените конфигурацию /etc/keepalived/keepalived.conf
global_defs {
  router_id haproxy-server2
  enable_script_security
  script_user root
}

vrrp_script haproxy_check {
  script "/usr/libexec/keepalived/haproxy_check.sh"
  interval 1
  weight -20
  fall 2
  rise 2
}

vrrp_instance VI_1 {
  interface ens3
  virtual_router_id 101
  priority 90
  advert_int 1
  state BACKUP
  virtual_ipaddress {
    192.168.26.27
  }
  track_script {
    haproxy_check weight 20
  }
  authentication {
    auth_type PASS
    auth_pass SecretPassword
  }
}

За основу взята конфигурация с основной ноды и внесены правки в параметры:

  • router_id — укажите уникальные названия для каждой ноды;
  • priority — приоритет нод внутри виртуального роутера;
  • state — тип роли ноды в виртуальном роутере.
3.2.2.5. Перезапустите на всех нодах сервисы
systemctl restart keepalived haproxy

4. Настройка Корпоративного сервера

4.1. Внесите правки в конфигурации на всех нодах api

В файле /opt/r7-office/Api/appsettings.json:

"ConnectionStrings": {
    "R7StorageServerUserActions": "Database=cddisk;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "R7StorageServer": "Database=cddisk;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "CommunityRepository": "Server=localhost;UserID=root;Password=test;Database=r7-office",
    "Payments": "Database=Payments;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "GeoNames": "Database=GeoNames;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;"
  },
  "rabbitMq": {
    "host": "192.168.26.27",
    "username": "r7office",
    "password": "r7office",
    "timeout": 10
  },

В файле /opt/r7-office/Sso.Api/appsettings.json:

"ConnectionStrings": {
    "R7StorageServerUserActions": "Database=cddisk;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "R7StorageServer": "Database=cddisk;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "CommunityRepository": "Server=localhost;UserID=root;Password=p@ssw0rd;Database=r7-office",
    "Payments": "Database=Payments;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "GeoNames": "Database=GeoNames;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;"
  },
"rabbitMq": {
    "host": "192.168.26.27",
    "username": "r7office",
    "password": "r7office",
    "timeout": 10
  },

А ткже processing нодах /opt/r7-office/Processing/appsettings.json:

"ConnectionStrings": {
    "R7StorageServerUserActions": "Database=cddisk;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "R7StorageServer": "Database=cddisk;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "CommunityRepository": "Server=localhost;UserID=root;Password=test;Database=r7-office",
    "Payments": "Database=Payments;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;",
    "GeoNames": "Database=GeoNames;Username=cddisk;Password=cddisk;Host=192.168.26.27;Port=5000;"
  },
  "DbType": "postgre",
  "rabbitMq": {
    "host": "192.168.26.27",
    "username": "r7office",
    "password": "r7office",
    "timeout": 10
  }
Важно

Также необходимо указать параметры подключения к виртуальному IP адресу 192.168.26.27.

4.2. Перезапустите на нодах api и processing службы

supervisorctl restart all

5. Настройка Сервера документов

5.1. Выполните повторную конфигурацию

Выполните скрипт documentserver-configure.sh по пункту 3.3.1 документации ↗ и укажите параметры с виртуальным IP адресом 192.168.26.27.

5.2. Далее внесите правки

В следующих файлах укажите параметры с виртуальным IP адресом 192.168.26.27:

  • /etc/r7-office/documentserver/local.json
  • /etc/r7-office/documentserver/default.json

5.3. Выполните перезапуск служб сервера документов

systemctl restart ds-*