Сбой приложения высокой загрузки Java-mysql

У меня проблема с моим html-скребком. Html-scraper — многопоточное приложение, написанное на Java с использованием HtmlUnit, по умолчанию работает со 128 потоками. Вкратце, это работает следующим образом: берет URL-адрес сайта из большого текстового файла, пингует URL-адрес и, если он доступен, анализирует сайт, находит определенные html-блоки, сохраняет все URL-адреса и информацию о блоках, включая html-код, в соответствующие таблицы в базе данных и переходит к следующий сайт. База данных - mysql 5.1, есть 4 таблицы InnoDb и 4 представления. Таблицы имеют числовые индексы для полей, используемых при объединении таблиц. Также у меня есть веб-интерфейс для просмотра и поиска парсируемых данных (для поиска я использую Sphinx с дельта-индексами), написанный на CodeIgniter.

Конфигурация сервера:

CPU: Type Xeon Quad Core X3440 2.53GHz
RAM: 4 GB
HDD: 1TB SATA
OS: Ubuntu Server 10.04

Некоторая конфигурация mysql:

key_buffer = 256M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 128
max_connections = 400
table_cache = 64
query_cache_limit = 2M
query_cache_size = 128M

Java machine run with default parameters except next options:

-Xms1024m -Xmx1536m -XX:-UseGCOverheadLimit -XX:NewSize=500m -XX:MaxNewSize=500m -XX:SurvivorRatio=6 -XX:PermSize=128M -XX:MaxPermSize=128m -XX:ErrorFile=/var/log/java/hs_err_pid_%p.log 

Когда база данных была пустой, скрейпер обрабатывал 18 URL-адресов в секунду и работал достаточно стабильно. Но после 2-х слабых мест, когда таблица urls содержит 384929 записей (~25% всех обработанных url-ов) и занимает 8.2Gb, java-приложение стало работать очень медленно и вылетать каждые 1-2 минуты. Думаю, причина в mysql, который не справляется с растущей нагрузкой (парсер, выполняющий 2+4*BLOCK_NUMBER запроса на каждый обработанный url; sphinx, обновляющий дельта-индексы каждые 10 минут; веб-интерфейс не рассматриваю, т.к. им пользуется только один человек ), может быть, он очень медленно перестраивает индексы? Но журналы mysql и скребка (которые также содержат все неперехваченные исключения) пусты. Что вы думаете об этом?


person c1tru55    schedule 17.01.2012    source источник
comment
Можно подробнее об аварии? Это сбой JVM или вы получаете ошибку типа OutOfMemoryError. Пробовали ли вы профилировать память вашего приложения или увеличивать максимальный объем памяти?   -  person Peter Lawrey    schedule 17.01.2012
comment
это не исключение OutOfMemoryError, приложение просто молча закрывается через несколько минут (возможно, из-за mysql). В это время веб-интерфейс не отвечает, sql-запросы выполняются очень медленно (300 с и более). Я пытаюсь увеличить максимальную память, но это не помогает   -  person c1tru55    schedule 18.01.2012


Ответы (3)


Я бы порекомендовал запустить следующее, просто чтобы проверить несколько вещей о состоянии. Помещение этого вывода здесь также поможет:

  1. dmesg
  2. top Проверьте резидентную и виртуальную память для каждого процесса.
person technocrat    schedule 17.01.2012
comment
сверху VIRT RES SHR %CPU %MEM COMMAND 823m 53m 2960 460 1.3 mysqld 3094m 1.9g 10m 329 49.1 java - person c1tru55; 18.01.2012
comment
вау, да, java определенно там. Вы нашли что-нибудь убедительное в dmesg? - Он должен показать, какой поток умер. Кроме того, вы уже заметили тенденцию использования памяти для любой из этих программ? Если вы запустите свой топ вот так top -p[pid],[pid], вы сможете смотреть только эти два. Если приложение Java дает сбой каждые 1-2 минуты, а использование оперативной памяти составляет 1,9 г когда-то, пока оно работает в течение этих 1-2 минут, это может указывать на утечку памяти. - person technocrat; 18.01.2012

Так приложение перестало отвечать? (совсем не то же самое, что сбой) Я бы проверил, все ли ваши ресурсы свободны. например сделайте jstack, чтобы проверить, связаны ли какие-либо нити.

Проверьте в MySQL, что у вас есть ожидаемое количество подключений. Если вы постоянно создаете соединения в Java и не очищаете их, база данных будет работать все медленнее и медленнее.

person Peter Lawrey    schedule 18.01.2012

Спасибо всем за ваши советы, mysql действительно был причиной проблемы. Включив журнал медленных запросов в my.conf, я вижу, что один из запросов, который выполняется каждую итерацию, выполняет 300 с (1 поле для поиска не было проиндексировано).

person c1tru55    schedule 18.01.2012