Балансировка нагрузки двух веб-серверов каждый на двух разных провайдерах?
У меня есть два интернет-провайдера, которые предоставляют мне хостинг через 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
Метод, который я бы использовал, был бы:
Храните свои учетные данные подключения к базе данных где-то на диске (очевидно, не в корневом веб-каталоге) и загружайте их при каждом подключении к странице. Вы можете редактировать сайты /default/settings.php следующим образом:
$ db_url = file_get_contents ('/ some / private / dir / drupal-db.url');
Напишите фоновый демон, который подключается к базе данных каждые 5 секунд (или около того) и регистрирует сбои машиночитаемым способом на диске. После сбоя соединения через 30 секунд (или около того), затем "поменяйте" учетные данные, хранящиеся на диске, с учетными данными сервера резервного копирования. Это заставит ваш веб-сервер обслуживать контент с альтернативного сервера базы данных. Если он вернется, полностью измените процесс. В этом случае ведение журнала необходимо для отладки и т. Д.
Если вы хотите стать модным, вы можете попробовать записать все 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.
Это в значительной степени все варианты. Для этого есть и другие, но они требуют много инфраструктуры, которой у вас нет.