Балансировка нагрузки двух веб-серверов каждый на двух разных провайдерах?

У меня есть два интернет-провайдера, которые предоставляют мне хостинг через apache / php / mysql. Я запускаю друпал на них. Иногда mysql-сервер отключается (сбой), поэтому я надеялся найти разумный способ отработки отказа, если сервер A SQL не работает, весь трафик отправляется на сервер B.

Я знаю, что традиционно это обрабатывается в DNS, где дается второй альтернативный IP, если есть проблема - или подобное. Но я не могу контролировать ISP, кроме как я могу запустить PHP, Perl и обычные вещи Apache. Кроме того, у меня есть статические IP-адреса на каждом ISP, и я могу создавать записи DNS (A/CNAME/TXT).

Итак, я надеялся, что у меня мог бы быть способ иметь скрипт, который проверял бы, есть ли у drupal проблемы, и если да, каким-то образом изменить dns, или?

Или есть другие идеи? (кроме того, чтобы потратить намного больше $ на лучшего провайдера)

3 ответа

Решение

Использование циклического DNS не решит вашу проблему - это отличный способ обеспечить балансировку нагрузки веб-серверов - но восстановление после сбоя происходит, когда клиент пытается подключиться к порту и не получает ответа (затем он пытается выполнить следующую запись DNS для хозяина). Очевидно, что в случае сбоя базы данных MySQL это не окажет прямого влияния на веб-сервер (т. Е. Веб-сервер будет отвечать на запросы TCP).

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

Единственный практический способ справиться с этим сценарием - это перенаправить на определенное имя хоста в случае обнаружения сбоя, поэтому, если в настоящее время оба хоста настроены как www.example.com, добавьте записи для www1..example.com и www2.example.com, затем добавьте включаемый файл с автоматическим добавлением, чтобы сделать что-то вроде:

(on www1.example.com)
check_db();
// if check_db returns, then continue with normal processing...

function check_db() {
  if (request is for www.example.com) { // avoid loops when both sites fail
     if (last check more than 10 secs ago) {
         if (database status bad) {
            raise a database failed flag on the filesystem
            redirect to www2.example.com
            end
         }
     } else {
         if (database failed flag set) {
             redirect to www2.example.com
             end
         }
         return OK
     }
   } else { // request is for www1.example.com i.e. we are already in failover mode
     if (database failed flag set) && (last check more than 5 secs ago) {
         if (database status good) {
            remove database failed flag
            return OK
         } else { // oh no! both hosts down!
            print sorry message and exit
         }
     } else if (last check more than 5 secs ago) {
         if (database status bad) {
            raise a database failed flag on the filesystem
            print sorry message and exit
         }
     }
   }
   return OK
}

Однако вам все еще нужен какой-то способ тестирования, если база данных работает без использования блокирующего вызова.

НТН

C.

Вы просите о сбое, а не о балансировке нагрузки.

Аварийное переключение чрезвычайно трудно сделать хорошо, особенно с оборудованием, которое не находится в той же инфраструктуре. Лучшим вариантом было бы получить избыточный балансировщик географической нагрузки у вашего интернет-провайдера, который без проблем тестирует ваши сайты и обрабатывает отработки отказа. Так как я думаю, что это вне вашего бюджета, давайте перейдем к методу жевательной резинки.

Поскольку ваша проблема, по-видимому, связана с MySQL, а не с веб-сервером, давайте решим эту проблему.

Дано:

  • Хост A: веб-сервер и база данных MySQL
  • Хост B: веб-сервер и избыточная база данных MySQL

Метод, который я бы использовал, был бы:

  1. Храните свои учетные данные подключения к базе данных где-то на диске (очевидно, не в корневом веб-каталоге) и загружайте их при каждом подключении к странице. Вы можете редактировать сайты /default/settings.php следующим образом:

    $ db_url = file_get_contents ('/ some / private / dir / drupal-db.url');

  2. Напишите фоновый демон, который подключается к базе данных каждые 5 секунд (или около того) и регистрирует сбои машиночитаемым способом на диске. После сбоя соединения через 30 секунд (или около того), затем "поменяйте" учетные данные, хранящиеся на диске, с учетными данными сервера резервного копирования. Это заставит ваш веб-сервер обслуживать контент с альтернативного сервера базы данных. Если он вернется, полностью измените процесс. В этом случае ведение журнала необходимо для отладки и т. Д.

  3. Если вы хотите стать модным, вы можете попробовать записать все INSERT и UPDATE на диск на веб-сервере, чтобы вы могли повторно синхронизировать базы данных после отработки отказа. Если это в основном "только для чтения", то это может быть необязательно.

Основной момент здесь состоит в том, чтобы отделить отказов при работе веб-приложения. Он более модульный и упрощает изменения в веб-приложении.

Наконец, убедитесь, что вы можете подключиться к своей резервной базе данных с основного сервера. Вы можете сделать это в командной строке, используя команды grant:

На хосте B:

mysql> GRANT ALL PRIVILEGES ON drupaldb.* TO username@'12.34.56.78' IDENTIFIED BY 'mypassword';

Где IP-адрес хоста А.

И не забудьте промыть!

mysql> FLUSH PRIVILEGES:

Затем протестируйте:

bash> mysql -u username -pmypassword -h hostb drupaldb

Нет, достойных технологий для этого нет - учитывая вашу инфраструктуру.

  • DNS не будет работать, если вы не сохраните время ожидания домена DNS SMALL (диапазон секунд). Если вы можете сделать это, вы можете написать его правильно (сценарий на сервере 2 не может достичь сервера 1, таким образом, изменяет записи DNS). Это в значительной степени единственный способ сделать это.

  • В зависимости от того, как настроена ваша DNS, это может быть либо ИЛИ - зарегистрировать запись хоста, используя что-то вроде dyndns.org, и заменить вашу запись IN A на CNAME. DynDNS.org имеет хороший API, который вы можете вызвать через HTTP, чтобы изменить запись, и CNAME никогда не изменится. Они также держат свои домены на коротких TTL.

Это в значительной степени все варианты. Для этого есть и другие, но они требуют много инфраструктуры, которой у вас нет.

Другие вопросы по тегам