Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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
15-1458310315
ВладОшин
2016-03-18 17:11
2017.03.05
Архиватор 7z, извлечение в cmd, пустые папки


1-1346672822
Alexander_K
2012-09-03 15:47
2017.03.05
Печать формы на принтер


2-1435321941
TheEd
2015-06-26 15:32
2017.03.05
Не работает DataSet.Refresh, или можно ли обойтись без CloseOpen?


2-1435573097
Кузьмич
2015-06-29 13:18
2017.03.05
Кеш базы???


15-1458293246
DayGaykin
2016-03-18 12:27
2017.03.05
VCL для веб





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский