Почему перебор всех папок пользователя java почты очень медленный?
Properties props = System.getProperties();
props.put("mail.imap.connectiontimeout",5000);
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
for(50K users){
//login,password changed in loop
String[] folders = {"inbox", "f1", "f2", "f3", "spam"};
store.connect(serverAddress, login + emailSuffix, password);
for (int i = 0; i < folders.length; i++) {
Folder x = store.getFolder(folders[i]);
x.open(Folder.READ_ONLY);
System.out.println("folder " + folders[i] + " of " + login);
x.getUnreadMessageCount();
x.close(false);
}
store.close();
}
Я использую один и тот же магазин для всех подключений, изменил service_count
в dovecot согласно этому ответу, чтобы улучшить производительность imap-dovecot, но я вижу только первую итерацию, и после этого код зависает или делает следующий system.out после долгого времени.
На самом деле мне нужно захватить все старые сообщения всех пользователей + подсчитать все непрочитанные сообщения, так как я хочу перейти с чистого Java Mail в какой-то другой пользовательский формат. Мне не удалось даже просто перебрать всех пользователей и папки для каждого пользователя, потому что даже простой store.connect зависает после 1-й итерации!
Лично я считаю, что узким местом является моя конфигурация dovecot, но она использует ограничения по умолчанию (1000 соединений), что выглядит неплохо.
Я как-то улучшаю свой dovecot, или подключаю свой магазин только один раз для всех пользователей, или как-то извлекаю все сообщения всех пользователей и unreadMessagesCount всех пользователей другим способом?
PS. Единственная альтернатива программируемому способу - это некоторый bash-скрипт в maildir, который будет читать каждое сообщение из файловой системы и передавать его в некоторый отдых, который конвертируется в мой пользовательский формат), но это намного сложнее, чем Java, слишком сложно разобрать smptp, parse seen
Флаги из имени файла и так далее.
ОБНОВИТЬ
Я нашел apache commons net imapclient, который работает очень быстро.
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
Мой код следующий
IMAPClient client = new IMAPClient();
client.connect("localhost");
for(50K users){
client.login(login + emailSuffix, password);
for (int i = 0; i < folders.length; i++) {
System.out.println(client.select("INBOX"); //prints true, it's ok
}
}
- Похоже, он подключается быстрее, чем java mailapi, потому что он можетподключиться один раз к хосту и после этого входа для каждого пользователя. Могу ли я как-нибудь повторить такое поведение в JavaMail API?
- Как я могу получить сообщения с помощью клиента Apache Commons? Все методы возвращают логическое значение или значение void, так что похоже, что это просто библиотека проверки сервера, я прав? Можно ли как-нибудь получить полезную информацию от imapclient?
1 ответ
Наконец, решил мою проблему, просто перебрав файловую систему (у меня есть формат maildir).
Я предполагаю, что Java Mail API делает новую аутентификацию dovecot для каждого пользователя в store.connect
в то время как он должен просто подключиться один раз (использовать dovecot auth) и после этого войти в систему для каждого пользователя (использовать dovecot imap-login). Вот почему я ждал 1 минуту для каждой итерации - это стандартный процесс авторизации в конфигурации dovecot. Я не уверен, но выглядит так.
Apache lib работает быстро, но это всего лишь тестовая библиотека для проверки связи с сервером, проверки соединения и других операций imap. Возвращает логический результат об операциях, но не полезную информацию (