Форум: "Прочее";
Текущий архив: 2017.03.05;
Скачать: [xml.tar.bz2];
ВнизНужен совет по поводу обработки большого количества почты Найти похожие ветки
← →
Игорь Шевченко © (2016-03-22 11:12) [0]Задача стоит следующая: Приходит большое число писем (две-три сотни тысяч в сутки), эти письма надо обработать следующим образом: Для каждого письма проверить его валидность (неким внешним процессом по данным из заголовка письма),
если письмо невалидное, то удалить с почтового сервера, если письмо валидное, то передать его на обработку еще одному внешнему процессу, дождаться оповещения об успешном начале обработки и удалить с почтового сервера.
Письмо должны быть гарантировано обработаны и не должны теряться в случае ошибок, сбоев питания, и прочих обстоятельств на обрабатывающей стороне.
Как сделано сейчас: Используется протокол POP3, программа подключается к почтовому серверу, забирает порцию писем (скажем, 100) не удаляя их с сервера, для каждого письма из порции получает UIDL, отключается от сервера. Дальше письма этой порции обрабатываются, когда наступает момент удаления письма, программа подключается к почтовому серверу, перебирает письма, сравнивая UIDL-ы, найдя нужный, удаляет письмо с сервера).
После обработки порции писем, программа пытается получить следующую порцию, если ее нет, то засыпает на какое-то время, и дальше все сначала.
Надежность этого решения устраивает, не устраивает скорость при большом количестве писем в ящике.
Собственно вопрос в чем - есть ли какие-то готовые проверенные решения по обработке приличных объемов почты, возможно, использование другого протокола, и т.д.
Мне необходимо обеспечить а) скорость б) надежность.
Ну все это в режиме 24/7
Буду рад пинкам в нужном направлении.
← →
virex(home) © (2016-03-22 11:28) [1]>Игорь Шевченко © (22.03.16 11:12) [0]
на самом почтовом сервере есть какие инструменты по валидации?
есть возможность работать с базой данных почтового сервера?
← →
DayGaykin © (2016-03-22 11:32) [2]Почему нельзя сделать так, чтобы программа, которая забирает порцию писем с сервера надежно сохраняла их у себя до обработки и сразу удаляла с сервера?
← →
Игорь Шевченко © (2016-03-22 11:33) [3]virex(home) © (22.03.16 11:28) [1]
Нет. Интересует решение для клиентской части. Работа с базой данных почтового сервера - это IMAP имеется в виду или что ?
← →
Игорь Шевченко © (2016-03-22 11:36) [4]DayGaykin © (22.03.16 11:32) [2]
Это одно из решений, которые делать не хочется, но возможно, придется, если не найдется менее затратных. Сохраняло где ? В базе данных ? Сложно и затратно. Файловой системы нету.
← →
Empleado © (2016-03-22 11:53) [5]>Для каждого письма проверить его валидность
Идет ли речь про отсеивание/частичное отсеивание спама?
← →
virex(home) © (2016-03-22 11:57) [6]>Игорь Шевченко © (22.03.16 11:33) [3]
вдруг бд хранится в sql-подобной бд
клиент бы запускал запросы/процедуры к бд по валидации и удалению ненужных писем, почти мгновенно
тут конечно нужна серверная часть доступа к бд, можно нацепить шифрование
← →
Игорь Шевченко © (2016-03-22 12:02) [7]Empleado © (22.03.16 11:53) [5]
> Идет ли речь про отсеивание/частичное отсеивание спама?
Не совсем. Спам отсеивает почтовый сервер. Здесь именно валидность писем с прикладной точки зрения. В среднем валидных писем 95%
← →
Труп Васи Доброго © (2016-03-22 12:04) [8]
> Надежность этого решения устраивает, не устраивает скорость
Если процент "спама" весьма высок, то не лучше ли на первом этапе (валидации) загружать не всё письмо, а только его заголовок (в MS OUTLOOK есть такая возможность). Обработать заголовки, отметить плохие для удаления, а хорошие для загрузки. На втором этапе уже удалять "спам", загружать "проверенные" письма полностью и передавать их в обработку.
В итоге, если спама много, загружать придётся намного меньше писем, что повысит скорость. Заголовки загружаются практически мгновенно.
← →
Игорь Шевченко © (2016-03-22 12:24) [9]Труп Васи Доброго © (22.03.16 12:04) [8]
> В среднем валидных писем 95%
← →
Sha © (2016-03-22 13:05) [10]Игорь,
а не проще/быстрее сразу просить у сервера все UIDL,
а потом в один проход удалять все старое и брать все новое?
← →
Игорь Шевченко © (2016-03-22 13:32) [11]Sha © (22.03.16 13:05) [10]
Привет, Саша!
Не понял, можно подробнее :) Письма, они же поступают регулярно, а не так, что они лежат в ящике, ждут, пока их обработают, а потом до следующего дня. Я обозначил общий объем, а темпы поступления я, увы, обозначить не могу.
← →
Sha © (2016-03-22 13:49) [12]Первое, что приходит в голову.
Клиент ведет 4 списка UIDL:
- успешно обработанные - их надо удалить в ближайшем сеансе,
- переданные на обработку - надо дождаться результата,
- не прошедшие валидацию - их надо удалить в ближайшем сеансе,
- новые, еще не считанные с сервера - их надо считать ближайшем сеансе.
Клиент в непрерывном цикле делает следующее:
- соединяется с сервером, начиная новый сеанс,
- одним запросом получает все имеющиеся у него UIDL,
- сравнивает их со своим списком и считывает, если надо, очередную порцию новых сообщений,
- сравнивает их со своим списком и удаляет невалидное и обработанное,
- закрывает соединение.
← →
KSergey © (2016-03-22 13:51) [13]Я так понимаю надёжность имеющегося подхода устраивает. Не устраивает скорость.
Проводился ли анализ на каком именно этапе происходит задержка в описанном сценарии? если проблема с POP3 - то может какой-то мэйл-сервер поддерживает какие-то плагины, для которых есть более шустрые протоколы.
← →
Sha © (2016-03-22 13:51) [14]Выше имелось в виду, что
"сравнивает их" = "сравнивает полученные UIDL"
← →
Sha © (2016-03-22 13:57) [15]> KSergey
ну, скорость у POP3 совершенно нормальная,
если прочитанные сообщения удалять сразу после прочтения,
и не использовать сервер POP3 в качестве сервера БД
← →
Rouse_ © (2016-03-22 14:11) [16]У нас Женька (jack128) писал небольшой сервис на шарпе по обработки такого кол-ва заявок (багрепорты от клиентов отсылаемых нам - объем примерно такой-же).
Его вариант работает именно так как ты и говоришь 24/7 без сбоев и задержек + сортировка писем по каталогам багтрекера и отсев спама.
Вроде бы у него даже все конфигурируется.
Щас его позову, может что подскажет
← →
Kerk © (2016-03-22 14:24) [17]Надо на ассемблере все переписать. Быстрее будет :)
← →
Игорь Шевченко © (2016-03-22 14:32) [18]KSergey © (22.03.16 13:51) [13]
Да, проводился анализ. Узкое место при удалении писем с сервера при наличии в ящике большего количества писем. В pop3 можно удалять письма по их номеру в сессии, а не по UIDL, поэтому при удалении приходится перебирать все письма и сравнивать UIDL
← →
Игорь Шевченко © (2016-03-22 14:36) [19]Sha © (22.03.16 13:49) [12]
Я примерно понял, что ты хочешь сказать, но хотелось бы для начала услышать, может, какие-то механизмы есть уже готовые. Я попробовал IMAP, но у меня сразу возникли проблемы со скоростью даже на этапе выборки писем. Читаю порцию, запоминаю UID-ы писем, потом удаляю по UID-у.
Почему мне не хочется хранить все в памяти и обрабатывать помногу - если произойдет сбой, мне кажется, я могу потерять всю хранящуюся у меня информацию. И да, забыл добавить, повторно отправлять на обработку валидные письма нежелательно.
← →
Sha © (2016-03-22 14:40) [20]> при удалении приходится перебирать все письма и сравнивать UIDL
зачем перебирать, если можно сразу можно получить список всех пар
No:UIDL
← →
jack128 © (2016-03-22 14:45) [21]На счет объема Rouse загнул, на пару порядков поменьше объем будет. И надежности никакой не надо, потерялась сотня сообщений об ошибках, ну и бог с ними, не жалко. Поэтому я просто раз 15 минут подключаюсь считываю все письма на диск, удаляю с сервера и оправляю дальше на обработку, никаких заморочек нет.
← →
KSergey © (2016-03-22 14:54) [22]> Игорь Шевченко © (22.03.16 14:36) [19]
> Sha © (22.03.16 13:49) [12]
>
> Я примерно понял, что ты хочешь сказать, но хотелось бы
> для начала услышать, может, какие-то механизмы есть уже
> готовые.
Видимо речь про готовую команду UIDL протокола POP3
А нельзя опереться на тот факт, что номера (не UIDL, а порядковые) неудалённых писем от сессии к сессии не меняются?
Впрочем, можно же вообще не закрывать POP3 сессию. Подключился - загрузил письма - обработал - если успешно - удалил. Вот тут можно переподключиться и увидеть новые письма.
Правда, вероятон медленное удаление писем - фича почтового сервера. ВОзможно - конкретного почтового сервера. Например, для корректной работы разных POP3 сессий (которые теоретически могут быть), плюс приём новых писем.
← →
Sha © (2016-03-22 14:55) [23]> мне не хочется хранить все в памяти и обрабатывать помногу
размер порции может быть любой
> если произойдет сбой, мне кажется, я могу потерять всю хранящуюся у меня информацию.
во время обработки все данные лежат также на почтовом сервере
> повторно отправлять на обработку валидные письма нежелательно
если не потеряешь список UIDL, то все будет OK
← →
Игорь Шевченко © (2016-03-22 15:05) [24]jack128 © (22.03.16 14:45) [21]
Увы, не мой вариант
Sha © (22.03.16 14:40) [20]
> зачем перебирать, если можно сразу можно получить список
> всех пар
> No:UIDL
Не понял, можно подробнее ?
KSergey © (22.03.16 14:54) [22]
> А нельзя опереться на тот факт, что номера (не UIDL, а порядковые)
> неудалённых писем от сессии к сессии не меняются?
Я ОЧЕНЬ не уверен, что они не меняются.
> Впрочем, можно же вообще не закрывать POP3 сессию. Подключился
> - загрузил письма - обработал - если успешно - удалил. Вот
> тут можно переподключиться и увидеть новые письма.
Тут есть один нюанс - все процессы (валидации и оповещения об успешной постановке на обработку) асинхронные. То есть, я отправляю запрос на валидацию и занимаюсь дальше своим делом. Точно также я отправляю запрос на обработку письма и тоже занимаюсь своим делом. В нужный момент мне приходят оповещения об удачной/неудачной валидации и удачной/неудачной постановке на обработку. В обработчиках этих оповещений я и занимаюсь взаимодействием с почтовым сервером на предмет удалить письмо.
← →
Sha © (2016-03-22 15:38) [25]> Не понял, можно подробнее ?
если опустить порядковый номер, то результат (список) вернется для всех порядковых номеров, известных в текущей сессии
см https://tools.ietf.org/html/rfc1939
← →
Игорь Шевченко © (2016-03-22 15:46) [26]Sha © (22.03.16 15:38) [25]
Спасибо, этого я не знал.
К сожалению, используемые мной компоненты список не поддерживают. Indy, как я вижу, умеет.
Но зтот список будет действительным для номеров в текущей транзакции сервера. После закрытия соединения, мне кажется, я могу список выбросить, нет ?
← →
NoUser © (2016-03-22 15:52) [27]А если на постоянной основе подключится несколькими такими клиентами ( UIDL and UIDL_MASK )
и внешние процессы валидации и обработки подстроить под "многоклиентность" ?
( я так понимаю на такой режим работы и заточены почтовики,
а производительность обмена с внешними процессами увеличится )
← →
Nouser © (2016-03-22 15:55) [28]о, коли они асинхронные, то ( как минимум для теста) так и нужно сделать
← →
Игорь Шевченко © (2016-03-22 15:56) [29]NoUser © (22.03.16 15:52) [27]
Не понимаю, можно подробнее ?
← →
Nouser © (2016-03-22 15:59) [30]
> В обработчиках этих оповещений я и занимаюсь взаимодействием
> с почтовым сервером на предмет удалить письмо.
то есть новая сесия POP3 для каждого удаления?
← →
Nouser © (2016-03-22 16:03) [31]> подробнее
каждый клиент работает только со своим "окончанием" UIDL или порядкового номера
( чёт/нечёт, если их два; b00/b01/b02/b03 если четыре )
← →
Sha © (2016-03-22 16:47) [32]> Но зтот список будет действительным для номеров в текущей транзакции сервера.
> После закрытия соединения, мне кажется, я могу список выбросить, нет ?
Да, правильно его получать каждый раз в начале сессии.
> то есть новая сесcия POP3 для каждого удаления?
Удаление происходит по окончании сессии.
До этого помеченные на удаление можно вернуть к жизни.
← →
Игорь Шевченко © (2016-03-22 17:46) [33]Sha © (22.03.16 16:47) [32]
> Да, правильно его получать каждый раз в начале сессии.
Я и так получаю этот список в начале сессии, при получении порции писем. Все письма складываются в некий внутренний список, с которым собственно выполняется работа. Когда мне надо письмо удалить (одно), я зная его UIDL, получаю от сервера письма, спрашиваю UIDL каждого, если совпадает, прошу удалить его и закрываю соединение. Ты предлагаешь при удалении получать полный список UIDL с сервера, найти там номер нужного и удалить, я верно понимаю ?
← →
Sha © (2016-03-22 18:37) [34]Нет.
Удаление вообще не наша цель. Оно - прибамбас к получению.
Наша цель - получение.
Когда нам приходит мысль, что надо получить порцию данных
(таймер или сигнал или просто бесконечный цикл),
делаем следующее.
1. Открываем соединение и прочитываем список всех UIDL, имеющихся на сервере.
2. Определяем, что там появилось нового.
3. Считываем порцию данных нужного нам размера.
4. Отдаем на валидацию.
5. Глядя в ведущийся нами список подлежащих удалению, помечаем на удаление невалидное и обработанное.
6. Закрываем соединение, при этом произойдет физическое удаление.
По событию завершения валидации
- либо помещаем UIDL в список невалидных,
- либо передаем сообщение на обработку, UIDL помещаем в список обрабатываемых.
По событию завершения обработки
1. помещаем UIDL в список обработанных
2. если список обрабатываемых пуст, сигналим, что пора принимать.
← →
Игорь Шевченко © (2016-03-22 23:07) [35]Sha © (22.03.16 18:37) [34]
Саша, спасибо тебе за помощь, но есть нюансы:
И валидация и обработка - это асинхронные процессы. Результат валидации может поступить неизвестно когда. Но по результату надо запустить на обработку. Постановка на обработку - это тоже асинхронный процесс, ее результат тоже может придти неизвестно когда. Ты предлагаешь постоянно держать открытый сеанс с почтовым сервером ?
← →
Sha © (2016-03-23 00:14) [36]> Игорь Шевченко © (22.03.16 23:07) [35]
> Ты предлагаешь постоянно держать открытый сеанс с почтовым сервером ?
Нет, конечно.
Основная идея в том, чтобы все время поддерживать непустую очередь на обработку. При этом мы отслеживаем текущее состояние всех скачанных писем (готово к валидации/готово к обработке/готово к удалению).
По таймеру или сигналу об опустошении очереди на обработку выполняем такую единицу работы:
1 Открываем соединение.
2. Считываем оглавление, определяем в нем количество и ID ранее нами не прочитанных писем, скачиваем их (ставя на валидацию и запоминая ID) сколько надо (напр, 10 или 1000 штук)
3. Метим на сервере на удаление те, которые надо было удалить к началу сеанса (т.е. как бы выполняем отложенное удаление).
4. И быстренько закрываем сеанс.
Остальные обработчики событий очевидны.
Важно не терять время на индивидуальные удаление писем в отдельных сеансах и на лишние чтения оглавление.
← →
Сергей Суровцев © (2016-03-23 02:46) [37]Я правильно понял из Игорь Шевченко © (22.03.16 15:05) [24] что письма удаляются по одному за раз?
← →
Игорь Шевченко © (2016-03-23 10:36) [38]Сергей Суровцев © (23.03.16 02:46) [37]
Да
Sha © (23.03.16 00:14) [36]
Я понял примерно. Ты предлагаешь организовать зеркало писем и заниматься его синхронизацией. Это все хорошо, но если будет ошибка, что станет с этими внутренними структурами ?
> Считываем оглавление, определяем в нем количество и ID ранее
> нами не прочитанных писем
Я не до конца понимаю, как определить "ранее не прочитанные письма". Как только я открыл соединение, я считываю содержимое почтового ящика.
← →
Sha © (2016-03-23 11:03) [39]> Ты предлагаешь организовать зеркало писем
Не совсем.
Предлагается вести и надежно хранить только список троек (No,Id,State),
полностью описывающих текущее состояние.
> если будет ошибка, что станет с этими внутренними структурами ?
Ничего страшного не произойдет.
Максимум, если все рухнет совсем - повторная обработка.
А если дублировать тройки хотя бы в INI файле, то вообще никаких последствий.
> как определить "ранее не прочитанные письма"
Ну, мы же в начале каждого сеанса имеем список пар (No,Id) на сервере
и такой же список пар для писем, которые скачали в прошлых сеансах.
Более того, для всех скачанных писем мы знаем их состояние в техпроцессе (готово к валидации/готово к обработке/готово к удалению).
← →
Игорь Шевченко © (2016-03-23 11:17) [40]Sha © (23.03.16 11:03) [39]
Я бы все-таки предпочел более простое решение. Почему: Хранить что-то в файловой системе я не могу, потому что проблемы с репликацией. Хранить в базе данных такую информацию как-то пока непонятно, за какую глубину.
Чем мне мое решение кажется проще - подключился к серверу, забрал письма, проверил, обработал, нужное удалил. Все просто и ясно. Если сломается, то рискуем одним письмом максимум (сломались на удалении, письмо будет прочитано и обработано еще раз).
Я почему в начале обратился к сообществу пнуть в плане протокола или еще чего - мне не очень нравится переделывать архитектуру, она учитывает много нюансов, которые не всегда возможно описать. Поэтому архитектуру я бы по максимуму хотел сохранить, а это значит, никаких дополнительных хранилищ и т.п.
Страницы: 1 2 вся ветка
Форум: "Прочее";
Текущий архив: 2017.03.05;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.003 c