#net #email #iis
Есть задача разработать сервис для рассылки почты, которым будут пользоваться остальные сервисы/приложения/сайты внутри компании. Планирую сделать WEB-сервис. Схема примерно такая: есть паблик метод который принимает на вход что рассылать и кому. метод получает пачку задач. Метод порождает поток, который берет задачи и рассылает потихонечку. Сам метод продолжает ожидать новых задач. Есть минимум 2 проблемы: До этого я всегда размещал сервисы в IIS. Однако, при наших объемах расылки, мы теоретически можем получить задачу которая будет длится часы. Насколько я понимаю IIS может сам прерывать задачи, которые длятся долгое время. Как мне этого избежать? Сервис работает в контексте IIS. Думаю (но не уверен), что реально мой метод будет не порождать потоки, а резервировать существующие внутри пула потоков IIS. Итого мы можем в результате залочить все потоки и полностью заблокировать сервис. Какой наиболее простой выход из этой ситуации? Возможно, мне стоит использовать SelfHosting WCF?
Ответы
Ответ 1
Нет, проблем с прерыванием задач не будет. Просто потому что у вас задача в отдельном потоке - IIS прерывает только те задачи, которые он запускал сам. Кстати, без отдельного потока он бы тоже не стал прибивать задачу - WCF служба неподвластна IIS, даже если использует его для активации. Если вы создаете поток через new Thread - то это будет именно отдельный поток, не имеющий никакого отношения к пулу IIS. В других случаях - да, такая проблема присутствует (кстати, у WCF и IIS тоже общие пулы). Способы "украсть" поток из общего пула: delegate.BeginInvoke ThreadPool.QueueUserWorkItem new Task BackgroundWorker Просто синхронная работа в операции WCF и еще куча более редких способов. Способы щадящей работы с общим пулом потоков: new Thread Использование асинхронных методов (они будут выполняться в общем пуле - но не будут занимать его надолго). На самом деле, проблемы вы ищите немного не там. Дело в том, что долгие операции рано или поздно захочется сделать еще и возобновляемыми, чтобы можно было, к примеру, выключить сервер для установки обновлений или для переезда на другой сервер - а потом продолжить все то, что не успело выполниться. Отдельную службу можно настроить, чтобы она запускалась автоматически. А сайт IIS - нет. Когда перед вами встанет такая задача - переход на SelfHosting WCF будет хорошим решением.Ответ 2
Итого мы можем в результате залочить все потоки и полностью заблокировать сервис. Хотел бы немного осветить этот пункт. Вам совсем не нужно каждый раз создавать по потоку на каждый вызов. Я совсем не знаком с разработкой в контексте IIS, но уверен, что внутри можно реализовать некий сервис - главный управляющий поток (если он требуется) и N потоков-рабочих. Сервис представляет собой просто обертку над одной большой очередью заданий, которые потоки-рабочие берут по одной и выполняют, и когда появляется необходимость отправить пачку писем, принявший эти письма поток должен просто скормить их сервису, который просто положит их в конец очереди. После этого проблемы с перегрузкой сервера пропадают сами собой: количество потоков всегда фиксированное, в случае пустующей очереди они спят, сожрать весь процессор они тоже не могут, потому что большую часть времени ждут ответов по сети. Здесь начинаются проблемы с уже немного другим характером: следить надо не за загруженностью сервера, а за тем, чтобы очередь не имела возможности бесконечно расти. Поэтому метод приемки сообщений должен возвращать 200, если размер очереди + переданные сообщения не превышают лимит и 503, если существует опасность вылезти за разумные пределы очереди.Ответ 3
IIS будет убивать ваш поток-обработчик при ресайкле пула приложений (app pool). Просто потому, что ресайкл аппула реализован перезапуска рабочего процесса IIS. Это может происходить, в зависимости от настроек, - по расписанию, по превышению памяти, вообще когда угодно. Например, при настройках по умолчанию appool будет убит через 20 минут неактивности. Вместе с вашим фоновым потоком. Хуже того, в некоторых случаях IIS будет запускать два рабочих процесса одновременно. Например, если включён overlapping recycling. Или если остановка старого аппула заняла больше времени, чем ожидалось (а это точно произойдёт, если вы запустить там долгий не-background поток). Даже при таких простых действиях, как редактирование конфига, поведение вашего "сервиса" будет полностью непредсказуемым. Хостить долгоживущие потоки в IIS - это плохая идея. Для долгоживущих потоков есть Windows Service (с self-hosted WCF в нём). Или, в случае стороннего хостинга - его замена в виде всяких webjobs.
Комментариев нет:
Отправить комментарий