Мысли, вызванные онлайн-устранением неполадок

интервью Java Redis задняя часть
Мысли, вызванные онлайн-устранением неполадок

предисловие

Поделился более или менее раньшемодель памяти,создание объектаТакое содержание, на самом деле, большинство людей остаются в неведении после прочтения, и они не знают фактического их значения.

Пока однажды вы не столкнетесь со странными проблемами в сети, такими как:

  • Поток выполняет задачу и не возвращается, и приложение приостанавливается.
  • Интерфейс отвечает медленно, и даже время запроса истекает.
  • ЦП работает с высокой нагрузкой.

Этот вид проблемы не так очевиден, как нулевой указатель или выход за границы массива.В настоящее время модель памяти, создание объекта, поток и другие только что упомянутые связанные знания должны быть объединены для устранения проблемы.

Только на этот раз я использовал предыдущую производственную проблему, чтобы рассказать о том, как устранить неполадки и решить проблему.

феномен производства

Давайте сначала посмотрим на предысторию проблемы:

На самом деле это временная задача: в фиксированное время одновременно запускаются N потоков для получения данных от Redis для работы.

Бизнес-логика очень проста, но приложение обычно включает в себя многопоточность, и к простым вещам следует относиться с осторожностью.

Конечно же, на этот раз возникла проблема.

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

Итак, мы начали локализовать проблему.

проблема позиционирования

Так как нет возможности найти исключения напрямую из лога, вы можете видеть только то, что делает приложение.

Наиболее распространенными инструментами являются те, которые поставляются с JDK.

На этот раз я использовалjstackЧтобы просмотреть выполнение потока, его функция на самом деле состоит в том, чтобы сбросить текущий стек потока.

Конечно перед дампом нужно знать pid моего приложения, можно использоватьjps -vТаким образом, перечислены все процессы Java.

Конечно, если вы знаете ключевое слово, используйте его напрямую.ps aux|grep javaэто тоже хорошо.

получитьpid=1523можно использовать послеjstack 1523 > 1523.logТаким образом, файл дампа выводится в файл журнала.

Если приложение простое и не сложное, а тредов относительно немного, то его можно открыть прямо для просмотра.

Однако файлы журналов, экспортируемые сложными приложениями, также относительно велики, поэтому рекомендуется использовать профессиональные инструменты анализа.

У меня здесь меньше журналов, и я могу просто открыть их напрямую.

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

Поэтому обычно рекомендуется давать осмысленное имя потока, что необходимо при устранении неполадок.

На самом деле несколько других потоков похожи на стек здесь, и очевидно, что все они выполняют соединения Redis.

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

Таким образом, реакция Redis, естественно, станет медленнее.

Затем используйтеjps -vСписок запущенных в данный момент процессов Java.Конечно, несколько приложений запрашивают Redis, и все они подключены одновременно, поэтому проблема, естественно, обнаружена.

Решение

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

Теперь, когда проблема найдена, как ее решить?

  • Сократите количество приложений, одновременно запрашивающих Redis, и уменьшите нагрузку на Redis в отдельные периоды.
  • Redis реплицируется в несколько кластеров, и каждое приложение опрашивается отдельно. Однако это потребует операций по эксплуатации и техническому обслуживанию, таких как синхронизация данных или синхронизация с помощью программы, что также усложнит процесс.

В настоящее время мы выбрали первую схему, и эффект очевиден.

локальное моделирование

Проблемы, связанные с потоками, описаны выше, а теперь давайте проанализируем проблему с памятью.

Возьмем, к примеру, этот класс:

GitHub.com/crossover J я…

public class HeapOOM {

    public static void main(String[] args) {
        List<String> list = new ArrayList<>(10) ;
        while (true){
            list.add("1") ;
        }
    }
}

Параметры запуска следующие:

-Xms20m
-Xmx20m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/Users/xx/Documents

Чтобы быстрее выявлять проблемы с памятью, максимальная память кучи фиксируется на уровне 20 МБ, и память автоматически сбрасывается в JVM при возникновении OOM./Users/xx/Documents(Если путь не совпадает, он будет сгенерирован в текущем каталоге).

После выполнения произошло исключение, как и ожидалось:

В то же время также создается соответствующий файл дампа памяти.

анализ памяти

В настоящее время для анализа необходимы соответствующие инструменты, и наиболее часто используемым, естественно, является МАТ.

Я попробовал онлайн-инструмент, и он отлично работает (не подходит для больших файлов):

heaphero.io/index.jsp

После загрузки файла памяти, который вы только что создали:

Поскольку это переполнение памяти, мы в основном наблюдаем большие объекты:

Также есть соответствующая подсказка, это, вероятно, объект переполнения памяти, после нажатия:

Видеть этот стек на самом деле довольно очевидно:

При непрерывной записи данных в ArrayList это вызовет частое расширение, то есть процесс копирования массива, и в конечном итоге достигнет верхнего предела в 20M, что приведет к переполнению памяти.

больше предложений

Как упоминалось выше, если вы используете многопоточность, вы должны быть особенно осторожны.

Вот несколько рекомендаций на каждый день:

  • Старайтесь не выполнять в потоке много трудоемких сетевых операций, таких как запросы к базе данных (по возможности проверьте данные из БД и подготовьте их в начале).
  • Максимально сведите к минимуму многопоточные конфликтные блокировки. Данные могут быть сегментированы и прочитаны отдельно каждым потоком.
  • Используйте большеCAS+自旋способ обновления данных и сокращения использования блокировок.
  • добавить в заявку-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmpможно хотя бы получить лог памяти при переполнении памяти.
  • Мониторинг пула потоков. Такие данные, как размер пула потоков, размер очереди и максимальное количество потоков, можно оценить заранее.
  • Мониторинг JVM, вы можете увидеть тенденцию к увеличению памяти кучи, кривую GC и другие данные, а также можете заранее подготовиться.

Суммировать

Позиционирование проблемы в Интернете требует всесторонних навыков, поэтому необходимы некоторые базовые навыки. Например, потоки, модель памяти, Linux и т. д.

Конечно, эти задачи только на бумаге без практики, если вы впервые столкнулись с онлайн-проблемой, не паникуйте, но вы должны радоваться тому, что вы научитесь навыку после ее решения.

Дополнительный

Недавно я обобщил некоторые знания, связанные с Java, и заинтересованные друзья могут поддерживать их вместе.

адрес:GitHub.com/crossover J я…

Добро пожаловать, чтобы обратить внимание на публичный аккаунт, чтобы общаться вместе: