Название: [Закрыта] Защита сервисов от перегрузки Отправлено: sergek от Март 29, 2018, 14:31 Коллеги,
разработал я систему мониторинга оборудования. Она включает в себя сервер доступа к данным, который обеспечивает получение данных от различных периферийных устройств, и веб-сервер, предоставляющих UI для пользователей. Сделаны в виде сервисов и работает на разных платформах, основная - Raspberry Pi. Сейчас занимаюсь повышением нагрузочной устойчивости серверов. В принципе, нагрузка невысокая (5-10 клиентов), но не хотелось бы, чтобы какой-нибудь пытливый пользователь пощелкал раз двадцать на кнопку и какой-нибудь сервер завалился. В системе можно выделить 2 основных потока данных - информационный (получение данных об устройствах - для чего, собственно, система и предназначена) и административный (для настройки конфигурации оборудования). Все выполняется через веб-интерфейс. С информационным потоком все понятно - есть очередь, куда ставятся запросы клиентов на получение данных, это прекрасно работает под разной нагрузкой. На крайний случай есть таймауты, так что устойчивости серверов ничего не угрожает. А с административным сложнее - при изменении конфигурации требуется ее обновление на обоих серверах. При этом пересоздаются объекты, обеспечивающие работу с устройствами (через TCP сокеты, USB, брокер MQTT, GPIO и еще всякое разное), так что угроза падения сервера доступа весьма реальна. Поэтому приходится ставить заборы - запрещаю обработку информационных запросов, дожидаюсь очистки очереди и после этого пересоздаю объекты конфигурации. Можно было бы просто перезапускать сервис, но это долго и не хочется так делать. Спасибо, что дочитали до этого места)) Теперь сформулирую вопрос. Посоветуйте, пожалуста, как грамотнее защитить сервера от перегрузки при обработке запросов на изменение конфигурации. Постановка такая: - запрос передается на сервер доступа через веб-сервер; - последовательная обработка, т.е. если обрабатывается запрос на обновление конфигурации, другие запросы можно игнорировать; - максимально простое решение. Представляется, что нужно использовать какие-то механизмы, которые бы показывали текущее состояние обработки запроса и ограничивали исполнение других запросов. Какие - семафорры, мьютексы, простые переменные? Отбраковывать на веб-сервере, на сервере доступа? Как это вообще делается? Если есть ссылки, где можно почитать, буду признателен. Название: Re: Защита сервисов от перегрузки Отправлено: qate от Март 29, 2018, 16:07 врятли я чтото понял, но спрошу - а почему эти сервисы вообще падают ?
Название: Re: Защита сервисов от перегрузки Отправлено: sergek от Март 29, 2018, 16:28 Да хз. Веб работает стабильно. А сервер доступа - я не понимаю(( В логах нет ничего криминального. Изредка проскакивает
Код: ASSERT failure in QArrayData::deallocate: "Static data can not be deleted", file tools\qarraydata.cpp, line 166. Название: Re: Защита сервисов от перегрузки Отправлено: _Bers от Март 29, 2018, 22:25 там же вроде на чистом английскоим написанно:
не могу прибить статические данные. корявая логика время от времени пытается освободить память, которую освобождать нельзя. даже точка в коде указанно. откуда нужно баг раскапывать. а ну да. по теме: когда сервер падает из-за бага, То по хорошему нужно искать ошибку и исправлять её. а не изобретать костыли-подпорки, что бы это корыто хоть как то удержалось на плаву. Название: Re: Защита сервисов от перегрузки Отправлено: sergek от Март 29, 2018, 23:43 а ну да. по теме: В том-то и дело, что багов нет, а есть недостатки в логике работы, которые я и пытаюсь исправить. Хотелось узнать о принятых подходах в решении подобных проблем. Не надо постить подобные "умные" мысли, толку от них ноль. когда сервер падает из-за бага, То по хорошему нужно искать ошибку и исправлять её. Название: Re: Защита сервисов от перегрузки Отправлено: qate от Март 30, 2018, 08:16 если программа падает, то она перезапускается - вот мой подход
при этом есть и корка и логи для анализа Название: Re: Защита сервисов от перегрузки Отправлено: sergek от Март 30, 2018, 10:05 если программа падает, то она перезапускается - вот мой подход Анализировал. Знаю места, где генерируются исключения (они разные), знаю почему. при этом есть и корка и логи для анализа Я все же спрашивал не об этом, наверное плохо или длинно сформулировал. Спасибо, тему закрываю. Название: Re: Защита сервисов от перегрузки Отправлено: Igors от Март 31, 2018, 06:31 ..наверное плохо или длинно сформулировал. Спасибо, тему закрываю. Не переживайте, это нормально. Серьезная проблема обычно требует хорошего знания задачи. А то "административный", "веб-сервер" и "сервер доступа" - возможно есть люди которые прекрасно знают о чем речь, но я без понятия. С др стороны так ли уж необходимо знание всех потрохов? Не всегда, более того, обильные подробности обычно убивают всякое обсуждение, тема как бы становится "слишком узкой"Представляется, что нужно использовать какие-то механизмы, которые бы показывали текущее состояние обработки запроса и ограничивали исполнение других запросов. Какие - семафорры, мьютексы, простые переменные? Отбраковывать на веб-сервере, на сервере доступа? Семафоры, мутексы и др - это низкоуровневые средства/примитивы синхронизации. Показывали и ограничивали - ну выше Вы писали, что запрещаете, дожидаетесь. Так что же не устраивает? Не скажу что это мне "безумно интересно", но может возможно сформулировать задачу без глухого провала в специфику? Правда тогда найдутся деятели что будут активно совать пятак в специфику, мол, нужно больше подробностей, а то слишком абстрактно :) Ну это можно пережитьНазвание: Re: [Закрыта] Защита сервисов от перегрузки Отправлено: sergek от Март 31, 2018, 12:32 К сожалению, трудно сформулировать задачу без деталей. Но попробую, вдруг кто-нибудь вникнет))
Например, как работает у меня очередь запросов (см. картинку). На картинке адаптер - это объект, обеспечивающий межпотоковое взаимодействие клиента с контроллером, который передает запросы в устройства и получает ответы. Очередь и контроллер существуют в главном потоке сервера доступа. Обычно у каждого контроллера своя очередь (не всегда, но не суть). Клиентский поток работает с очередью, т.е. ставит в нее свой запрос и ждет ответа. Далее все автоматически происходит в очереди - как только запрос становится первым в очереди, выполняется подключение контроллера к устройству и передача данных. После того, как контроллер получит ответ, он удаляет обработанный запрос из очереди, а очередь выполняет отключение контроллера. Происходит продвижение очереди и все повторяется. Это, когда все нормально. В случае, если контроллер не получает ответа от устройства, срабатывает таймаут адаптера и он шлет сигнал в очередь на удаление запроса. Ну и далее по вышеописанному сценарию. К чему я привожу эти подробности - очередь должна иметь потокобезопасную реализацию. Тут появляются мьютексы. Ими защищены постановка запроса в очередь, удаление, проверка длины очереди и т.д. Но не все операции можно закрыть ими. Например, вызовы передачи запроса в контроллер (появляются дедлоки), отключение от контроллера (иногда эта операция длится существенное время). Я уже упоминал в предыдущих постах, что при перезагрузке конфигурации я дожидаюсь очистки очередей, проверяя их длину. В результате, как я себе представляю, можно попасть в момент, когда очередь обнулилась, а операция с контроллером еще не завершилась. Метод контроллера вызывается, а объекта уже нет. Этого мне удается добиться, например, если к серверу доступа подключен десяток клиентов, которые каждые несколько сек. шлют запросы, чтобы организовать очередь (1-2 запроса), и я одновременно шлю 10-15 запросов на пересоздание конфигурации путем быстрого нажатия на кнопку. Такую ситуацию можно создать только умышленно, поэтому я не стал придумывать что-то с очередью, хотел ограничиться простыми ограничительными мерами на уровне веб-сервер, например. Ну это кратко. Знаю, по каким местам меня можно здесь критиковать, но надеюсь на конструктивную критику (наивный))) |