Алгоритм восстановления процесса

Jekich

Ситуация следующая.
Есть программная реализация сервера, который выполняет проксирование запросов пользователя, т.е. принимает запрос от пользователя, оборочаивает его каким-то образом, отправляет в другую систему, получает ответ, преобразовывает его и отдает пользователю.
user -> MyServ -> MegaServ 

Иногда MegaServ не отвечает, либо время ожидание ответа очень большое. На MyServ запущен мониторинг, который измеряет среднее время ожидания ответа за фиксированный интервал, если оно превышает заданное пороговое значение, то мониторинг убивает процесс сервера. Далее через фиксированный интервал времени, допустим 10 минут, сервер поднимается, но в случае первого неудачного запроса, или долгогр времени ожидания опять отрубается на 10 минут.
Так было сделано, потому что на самом деле MyServ несколько штук и, соответственно, также несколько MegaServ.
 user -> Контроллер -> MyServ1, MyServ2, MyServ3... -> MegaServ1, MegaServ2, MegaServ3 

Нужно отключать процессы MyServ, которые тормозят, контроллер ждет ответа от всех известных ему MyServ'ов.
Вопрос
Эта реализация была придумана мной за 5 минут, и она мне не нравится тем, что если один из MyServ будет отключен, то ему потом будет сложно подняться (одна ошибка или долгое время ожидания и жди снова 10 минут). Подскажите в какую сторону лучше посмотреть, чтобы разработать более оптимальный алгоритм восстановления одного из процессов?

zorin29

а зачем весь MyServ убивать? разве нет более гуманных способов отменить запрос?

Jekich

убивается один из MyServ'ов.
Контроллер ждет, пока каждый из MyServ обработает запрос пользователя, поэтому если один начал тупить, то его нужно убить, пока ситуация не изменится к лучшему.

marat7256

Также не понятно, зачем MyServ вообще ждет. Послал запрос - продолжает работать получая запросы userов, получил ответ - передал по назначению.

Jekich

Также не понятно, зачем MyServ вообще ждет. Послал запрос - продолжает работать получая запросы userов, получил ответ - передал по назначению.
Возможно, я плохо объяснила саму логику системы, щас распишу подробнее.
Имеем общую картину
 
 user -> Контроллер -> MyServ1, MyServ2, MyServ3,... -> MegaServ1, MegaServ2, MegaServ3,... 

Запрос от пользователя поступает Контроллеру, тот параллельно вызывает MyServ1, MyServ2, и т.д., которые вернут ему ответы. Контроллер соединит их ответы и вернет пользователю. Пользователю нельзя отдать часть ответа, а потом дослать остальное. Поэтому время ожидание ответа пользователем = max( ResponseTime(MyServ1 ResponseTime(MyServ2... ). Это жесткое требование и от него избавиться нельзя.
Если один из MyServ'ов тупит, то соответственно тупит и контроллер, который его ждет. Для меня критично время ответа пользователю. Поэтому целесообразно убить один тупящий процесс, а потом поднять его снова, когда ситуация улучшится. Это не означает, что контроллер не может принять несколько одновременных запросов от пользователя, еще раз повторюсь, я борюсь за время ожидания ответа.

marat7256

Так яснее.
Все же убивая процесс мы не достигаем цели - получение ответа пользователем.
Эффективнее помечать в контроллере, что процесс тупит, и дублировать запрос к другому процессу.
Таймаут же лучше в самом MyServ контролировать, чтобы по достижении его он сам переставал ожидать ответа и сообщал контроллеру, что освободился.

Jekich

Яснее, но все же не до конца.
Каждый MyServ - это интерфейс к API различных MegaServ. Контроллер - суть агрегатор запросов к MegaServ'ам.
Естественно, что в каждом MyServ реализован таймаут ожидания ответа от MegaServ, по истичению которого он вернет ответ с ошибкой (эта ситуация нормально отрабатывается контроллером).
Рассмотрим пример
MyServ1 среднее время ожидания ответа за последние 5 минут - 14 секунд
MyServ2 ср. время ожидания ответа за последние 5 минут - 1 секунда
MyServ3 ср. время ожидания ответа за последние 5 минут - 1 секунда
Сл-но среднее время ожидания пользователем ответа - 14 секунд (как максимум). Если убить MyServ1 на время, пока ситуация на MegaServ1 не станет лучше, то время ответа пользователю от контроллера станет 1 секунда.

stm7884696

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

Jekich

нет, они не равнозначны

stm7884696

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

marat7256

Если убить MyServ1 на время, пока ситуация на MegaServ1 не станет лучше, то время ответа пользователю от контроллера станет 1 секунда.
Ты же писала, что отдать надо ВСЕ ответы. А убив одного, ты часть просто теряешь.

Jekich

Если проблема только в том, чтобы быстро поднять, то надо на отключенные вешать демонов, которые будут проверять время ответа и возвращать в строй не через жестко заданные интервалы, а как только нагрузка спадет.
Да, проблема в том, чтобы быстро поднять. Но твое предложение нужно додумать... Ты говоришь, что нужно проверить, что нагрузка спала - вот тут главная засада. А что значит, что нагрузка спала? Я сейчас выполняю один запрос, если его выполнение превысило какой-то заданный интервал, то считаю, что нагрузка не спала, и нужно еще подождать немного. С другой стороны я отключаю сервер тогда, когда среднее за указанный интервал становится выше порогового значения. Мне не нравится, что эти условия (условие включения и выключения) описывают разное поведение мегасервов (согласен?).
Решение в лоб - демоны (которых ты предложил) должны также замерить среднее и на основании его, а не одного замера принять решение о том, поднять или нет. Может, есть что-то изящнее, или не заморачиваться и остановиться на этом?

Jekich

Ты же писала, что отдать надо ВСЕ ответы. А убив одного, ты часть просто теряешь.
Я писала, что
Пользователю нельзя отдать часть ответа, а потом дослать остальное.

stm7884696

Может, есть что-то изящнее, или не заморачиваться и остановиться на этом
Учитывая твое описание проблемы через пень колоду, пока самое изящное - это топор :)

stm7884696

Я писала, что
где это все применяется? какая реальная система?

Jekich

Учитывая твое описание проблемы через пень колоду, пока самое изящное - это топор
это последствие суток без сна =)
Реализовать буду, когда высплюсь, поэтому хочется, чтобы был не топор.

Jekich

где это все применяется? какая реальная система?
Система бронирования отелей. Только тссс :o

marat7256

Ты писала:
Запрос от пользователя поступает Контроллеру, тот параллельно вызывает MyServ1, MyServ2, и т.д., которые вернут ему ответы. Контроллер соединит их ответы и вернет пользователю. Пользователю нельзя отдать часть ответа, а потом дослать остальное. Поэтому время ожидание ответа пользователем = max( ResponseTime(MyServ1 ResponseTime(MyServ2... ). Это жесткое требование и от него избавиться нельзя.

Из чего вытекает, что просто убить процесс без его восстановления нельзя, ибо ответ будет неполным.
Кроме того не понятно, зачем убивать MyServ, если проблема в MegaServ.
Если выразиться точнее, то пока твое описание неполно и противоречиво.

stm7884696

отдавай результаты через ajax построчно.
Внеси изменения в дизайн и юзаюилити :)

Jekich

отдавай результаты через ajax построчно.
Снеси изменения в дизайн и юзаюилити
МегаСерверы - это сервера отельных поставщиков. Мне нужно, чтобы поиск отелей в определенном городе происходил быстро, а выдача должна быть уже отсортирована по цене (жесткое бизнес требование)/ Поэтому что-то досылать - нельзя.

Jekich

Если выразиться точнее, то пока твое описание неполно и противоречиво.
Спроси 'а, он понял мою боль и печаль ;)

marat7256

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

Jekich

Из чего вытекает, что просто убить процесс без его восстановления нельзя, ибо ответ будет неполным.
Кроме того не понятно, зачем убивать MyServ, если проблема в MegaServ.
1/ Я несказала, что мне запрещено вернуть неполный ответ, я сказала, что немогу что-то дослать в уже отправленный ответ.
2/ Потому что MyServ - это мои процессы, я ими распоряжаюсь сама, а MegaServ - это жизнь вне моей системы, поэтому я могу только скрестить пальцы и ждать, что у мегасерв все наладится.

stm7884696

а выдача должна быть уже отсортирована по цене (жесткое бизнес требование)/ Поэтому что-то досылать - нельзя.
Это потому, что ты не умеешь сортировать налету перестраивая таблицу цен?
Так и представляется прогрессбар с процентажем выполнения поиска и постепенно заполняющаяся табличка с предложениями и сортировкой по цене.
В отличие от остальных говносистем пользователь начинает видеть ответы сразу, а значит время реакции системы минимально. А то, что догружается долго - это уже не так критично.
Вобщем я бы так и сделал. Все остальные решения - это потеря или времени или части информации, что менее приемлимо.

Jekich

Определись, тебе важно собрать все-все ответы или максимально возможное число ответов за определенное время?
Я уже несколько раз написала, что для меня важно, чтобы ответ от контроллера формировался быстро (сейчас в реализации это означает, что среднее время ожидания ответа от мегасерва не превышает некоторого порогового значения). Поэтому да, мне важно "максимально возможное число ответов за определенное время", и я решаю задачу - когда (максимально быстро) я могу снова поднять убитый майсерв.

stm7884696

MyServ - это мои процессы, я ими распоряжаюсь сама, а MegaServ - это жизнь вне моей системы, поэтому я могу только скрестить пальцы и ждать, что у мегасерв все наладится.
Ах да, кеширование :) Для прогулки по страницам - самое то :)

marat7256

Все равно не ясно, зачем убивать MyServ. Нет от него ответа и ладно. Если сам MyServ умеет выходить из анабиоза ожидания, то в его убийстве нет смысла. Просто контроллер продолжит слать ему запросы, а получит ответ или нет будет зависть от MegaServa и грамотно написанного MyServa.

Jekich

Так и представляется прогрессбар с процентажем выполнения поиска и постепенно заполняющаяся табличка с предложениями и сортировкой по цене.
:crazy: Представлять интерфейсы - это, конечно же круто, но не правильно. Сервис должен строиться от своего API, а не от того, что увидит пользователь. Простой пример, который убьет твое предложение. Пользователем может быть не только физический человек, который просматривает предложения в браузере, а какая-то система, которая через меня получает агрегированный ответ от k отельных поставщиков.
Я сказала, что требование "ничего дослать нельзя" - жесткое, его нужно придерживаться в реализации. Потерять часть данных можно. Это нам дано, не нужно пытаться изменить эти входные условия.

Jekich

кеширование
на самом деле кеширование для данной задачи это непросто - поверь на слово. Очень много подводных камней из-за специфики.

stm7884696

Не вижу проблемы. Отдавай пользователю с догрузкой.
А в API сделай отсечку в контроллере по таймауту но не роняя сервис.
На чем проект пишется ?

Jekich

Все равно не ясно, зачем убивать MyServ.
Я для кого формулу писала вычисления величины времени ожидания? И несколько повторила, что для меня время ожидания мега критично, и решение об убийстве MyServ как принимается на основе его.

viktor954

дело говорит. Если я правильно понял, то делается параллельный запрос к нескольким МегаСервам и потом выдаётся отсортированный результат по полученным данным. Так? Тогда если очередной МегаСерв не ответил - это проблема его владельцев, его "хотэль" не попадёт в выборку. Остальные результаты от исправно отвечающих МегаСервов будут выведены и отсортированы "на лету" по мере получения ответов.

stm7884696

на самом деле кеширование для данной задачи это непросто - поверь на слово
Верю, что если подумать, то можно сделать все красиво :)

Jekich

дело говорит. Если я правильно понял, то делается параллельный запрос к нескольким МегаСервам и потом выдаётся отсортированный результат по полученным данным. Так? Тогда если очередной МегаСерв не ответил - это проблема его владельцев, его "хотэль" не попадёт в выборку. Остальные результаты от исправно отвечающих МегаСервов будут выведены и отсортированы "на лету" по мере получения ответов.
время ожидания ответа от контролера не должно быть слишком большим. Прями как аксиому, что больного нужно убить, а поднять лишь тогда, когда жизнь наладится.

marat7256

Я для кого формулу писала вычисления величины времени ожидания? И несколько повторила, что для меня время ожидания мега критично, и решение об убийстве MyServ как принимается на основе его.
Убивать зачем? Не жди его и все.

Jekich

Верю, что если подумать, то можно сделать все красиво
я тоже в этом уверена ;)

stm7884696

Убивать зачем? Не жди его и все.
Походу она не знает, как.
Поэтому по факту ответа думает отключать на время. А надо просто поставить таймауты ожидания ответа, а запросы отсылать всегда и всем :)

marat7256

Прями как аксиому, что больного нужно убить, а поднять лишь тогда, когда жизнь наладится.
Это не аксиома, а бездоказательное утверждение.

marat7256

Так я уже это писал!

Jekich

Поэтому по факту ответа думает отключать на время. А надо просто поставить таймауты ожидания ответа, а запросы отсылать всегда и всем
:D TimeOut'ы и так есть. Но если подумать, то мой вариант с отключением после превышения время ожидания в среднем на каком-то интервале все таки для чего-то нужен ;)

stm7884696

Смотря для чего. Если для того, чтобы увеличить сложность разработки без улучшения юзабилити - то да, отличный вариант.
А так - ложись спать, утром на свежую голову вникнешь в те другие 5 предложений, которые тебе озвучили в треде.

Jekich

хорошо :D утром объяснюсь

stm7884696

что в итоге выбрала ?
Оставить комментарий
Имя или ник:
Комментарий: