У меня есть два интернет-провайдера, которые предоставляют мне хостинг через apache / php / mysql. Я запускаю на них drupal. Иногда сервер mysql уходит (сбой), поэтому я надеялся найти разумный способ отработки отказа, если сервер A SQL не работает, весь трафик отправляется на сервер B.
Я знаю, что традиционно это обрабатывается в DNS, где второй альтернативный IP-адрес предоставляется, если есть проблема - или что-то подобное. Но у меня нет контроля над isp, кроме того, что я могу запускать php, perl и обычные вещи apache. Кроме того, у меня есть статические IP-адреса для каждого провайдера, и я могу создавать записи DNS (A / CNAME / TXT).
Итак, я надеялся, что у меня может быть способ создать сценарий, который проверяет, есть ли проблема с drupal, и если да, то каким-то образом изменить dns или?
Или какие-нибудь другие идеи? (кроме того, что вы тратите намного больше долларов на лучшего провайдера)
Циклический перебор 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
}
Однако вам все еще нужен способ тестирования, работает ли база данных без использования блокирующего вызова.
HTH
С.
Мне кажется, вы просите об отказе, а не о балансировке нагрузки.
Отработать отказоустойчивость крайне сложно, особенно с оборудованием, не входящим в ту же инфраструктуру. Лучшим случаем было бы получить у вашего интернет-провайдера резервный балансировщик географической нагрузки, который проверяет ваши сайты и без проблем справляется с аварийным переключением. Поскольку я предполагаю, что это выходит за рамки вашего бюджета, давайте выберем палочки и метод жевательной резинки.
Поскольку ваша проблема, по-видимому, связана с MySQL, а не с веб-сервером, давайте решим проблему вручную.
Дано:
Я бы использовал следующий метод:
Храните учетные данные для подключения к базе данных где-нибудь на диске (очевидно, не в корневом веб-каталоге) и загружайте их при каждом подключении к странице. Вы можете редактировать sites / default / settings.php так:
$ db_url = file_get_contents ('/ некоторые / частные / каталог / drupal-db.url');
Напишите фоновый демон, который подключается к базе данных каждые 5 секунд (или около того) и регистрирует сбои в машиночитаемом виде на диске. После сбоя подключения через 30 секунд (или около того) затем «поменяйте местами» учетные данные, хранящиеся на диске, с учетными данными резервного сервера. Это заставит ваш веб-сервер обслуживать контент с альтернативного сервера базы данных. Если он вернется, повторите процесс в обратном порядке. Ведение журнала в этом случае необходимо для отладки и т. Д.
Если вы хотите пофантазировать, вы можете попытаться записать все операции INSERT и UPDATE на диск на веб-сервере, чтобы потенциально можно было повторно синхронизировать базы данных после аварийного переключения. Если это в основном «только для чтения», то в этом нет необходимости.
Основным моментом здесь является отделение отработки отказа от работы веб-приложения. Он более модульный и упрощает внесение изменений в веб-приложение.
Наконец, убедитесь, что вы можете подключиться к базе данных резервного копирования с первичного сервера. Вы можете сделать это в командной строке и с помощью команд предоставления:
На хосте B:
mysql> GRANT ALL PRIVILEGES ON drupaldb.* TO username@'12.34.56.78' IDENTIFIED BY 'mypassword';
Если IP-адрес хоста A.
И не забывайте смывать!
mysql> FLUSH PRIVILEGES:
Затем проверьте:
bash> mysql -u username -pmypassword -h hostb drupaldb
Нет, для этого нет достойных технологий - учитывая вашу инфраструктуру.
DNS не будет работать, если вы не сохраните время ожидания домена DNS МАЛЕНЬКОЕ (диапазон в секундах), которое наступает. ЕСЛИ вы можете это сделать, вы можете правильно написать сценарий (сценарий на сервере 2 не может связаться с сервером 1, что изменяет записи DNS). По сути, это единственный способ сделать это.
В зависимости от того, как настроен ваш DNS, это будет либо там, либо - регистрация записи хоста с помощью чего-то вроде dyndns.org и замена вашей записи IN A на CNAME. DynDNS.org имеет хороший API, который вы можете вызвать через HTTP, чтобы изменить запись, и CNAME никогда не изменится. Они также держат свои домены на коротких TTL.
Это почти все варианты. Для этого есть и другие, но они требуют большого количества инфраструктуры, которой у вас нет.