Централ Плейнс Бэнк Практическая дорога Артаса

контейнер облачный носитель

Автор | Юй Шуан инженер по исследованиям и разработкам системы Zhongyuan Bank, в настоящее время занимается распределенным кэшем, очередью сообщений и другими связанными с этим работами в группе промежуточного программного обеспечения комнаты технологической платформы.

[Официальное сообщество Артаса проводит конкурс сочинений, за участие можно получить призы~Нажмите, чтобы отправить

Arthas — это диагностический инструмент с открытым исходным кодом для приложений Java. Благодаря своим мощным возможностям устранения неполадок и диагностики он широко используется разработчиками с момента его открытия. Он много раз поднимался на вершину GitHub Trending и был рекомендован и разделяется многими отечественными техническими СМИ.

1. Индивидуальное преобразование функций

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

1. 连接JVM:通过attach机制,通过attach pid连接正在运行的JVM;
2. 查看及修改JVM字节码:通过instrument技术对运行中的JVM附加或修改字节码来实现增强的逻辑。

В конце 2018 года Zhongyuan Bank начал инвестировать в исследования Arthas и узнал об основных функциях в сообществе с открытым исходным кодом.Прочитав схему проекта Arthas, была выяснена общая структура проекта.Весь процесс выполнения выглядит следующим образом : Артас вызывает ManagementFactory rt.Внутренняя информация, взаимодействует с серверной частью посредством интеграции команд, выполняет и возвращает результаты.Весь проект прост, понятен и удобен в использовании.

В начале 2019 года техническая команда банка Zhongyuan начала использовать и продвигать Arthas для обнаружения и диагностики онлайн-проблем.

Чтобы защитить конфиденциальную информацию клиентов и обеспечить стабильную работу бизнес-системы в производственной среде, мы настроили некоторые функции Arthas и скрыли некоторые команды:

1. watch:watch方法可以在没有打印日志的情况下,看到方法的入参和返回值,有可能暴露客户的敏感信息;
2. mc、redefine:mc组合rdefine可以对代码进行热更新,不能满足我行生产运行管理规范要求。

В то же время для нужд использования были разработаны специальные команды, такие как gc:

1. gc:实时动态展示年轻代,年老代垃圾百分比,回收次数及耗时等情况。 

На следующем этапе наш банк планирует продвигать использование Arthas во всех средах разработки и тестирования, а также в некоторых производственных средах для устранения неполадок и диагностики местоположения. В то же время использование Arthas популяризируется и продвигается среди команды разработчиков приложений в отрасли в форме внутреннего обмена технологиями.

2. Сосредоточьтесь на использовании функций

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

1.target-ip

# target-ip 为指定绑定的IP,如果不指定IP,Arthas只listen 127.0.0.1,所以如果想从远程连接,则可以使用 --target-ip参数指定listen的IP
java -jar arthas-boot.jar --target-ip IP

После привязки IP-адреса удаленного доступа вы можете удаленно подключаться к Arthas через telnet или http для устранения неполадок.

Адрес веб-доступа: ip: 8563

1.png

/telnet доступ: ip: 3658

2.png

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

2.trace

# 查看方法内部调用路径,并输出方法路径上的每个节点上耗时 
trace ClassName methodName

С помощью команды trace можно отслеживать, где тратится время слой за слоем, что очень эффективно при настройке производительности.

3.png

3.ognl

ognl — это язык выражений с открытым исходным кодом, применяемый к Java. Его функция заключается в доступе к данным. Он имеет такие функции, как преобразование типов, доступ к методам объектов и управление объектами коллекций. С помощью ognl можно выполнять ряд мощных операций.

  • выполнить статический метод
# 使用ognl调用静态方法
ognl “@类名@方法名(参数)”
  • получить статические свойства
# 使用ognl获取静态属性
ognl “@类名@属性名”
  • Пример: изменение уровня журнала
# 查找当前类的classloader hashcode
sc -d 类名 | grep classLoaderHash
# 用OGNL获取logger
ognl -c ***** '@类名@logger'
# 单独设置该类的logger level
ognl -c ***** '@类名@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'
#全局设置logger level
ognl -c ***** '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'

4.gc

gc — это специально разработанная функция нашего банка, полученная из команды jstat -gcutil pid timeinterval, где pid можно получить от Артаса, timeinterval (в миллисекундах) представляет временной интервал каждого gc, а значение по умолчанию — 1 с.

# 查看应用gc情况(timeinterval表示间隔时间,单位毫秒,默认为1S)
gc -i timeinterval -n 5

4.png

3. Практические кейсы применения

Ниже приведены некоторые из наших практических примеров применения Arthas (из-за требований конфиденциальности встроенного кода все случаи, показанные ниже, являются примерами кода, написанного для воспроизведения сцены)

Случай 1: высокая загрузка ЦП системы

описание проблемы: Бизнес-персонал сообщил, что одна из страниц системы фонового управления имеет длительное время отклика, и было обнаружено, что загрузка ЦП на сервере входа в систему была высокой, достигая около 80%.

1. Запустите Arthas и подключитесь к соответствующему java-процессу.

Примечание. Arthas запускается с тем же стартовым пользователем, что и процесс Java.

# 启动Arthas
   java -jar arthas-boot.jar
   [INFO] arthas-boot version: 3.2.0
   [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
   * [1]: 11360 org.gradle.launcher.daemon.bootstrap.GradleDaemon
     [2]: 12196 com.durian.ddp.Application
   # 选择要附加的java进程编号
   2
   ...

2. Команда thread для просмотра потоков с высокой загрузкой ЦП.

Запустите Arthas, подключитесь к соответствующему процессу Java и выполните thread -n 5, чтобы просмотреть стеки 5 потоков с максимальной загрузкой ЦП.

# 查看CPU使用率最高的5个线程
thread -n 5
at ***.TreeUtil.findMenuChildren(TreeUtil.java:94)
    at ***.TreeUtil.findMenuChildren(TreeUtil.java:92)
    at ***.TreeUtil.findMenuChildren(TreeUtil.java:92)
    at ***.TreeUtil.findMenuChildren(TreeUtil.java:92)
    at ***.TreeUtil.recursiveTree(TreeUtil.java:74)
    at ***.getOwnerDeparmentTree(DepartmentServiceImpl.java:550)
    ...
at ***.TreeUtil.findMenuChildren(TreeUtil.java:94)
    at ***.TreeUtil.findMenuChildren(TreeUtil.java:92)
    at ***.TreeUtil.findMenuChildren(TreeUtil.java:92)
    at ***.TreeUtil.findMenuChildren(TreeUtil.java:92)
    at ***.TreeUtil.recursiveTree(TreeUtil.java:74)
    at ***.getOwnerDeparmentTree(DepartmentServiceImpl.java:550)
    ...
...

3. Просмотр количества вызовов методов и затрат времени с помощью команды монитора.

С помощью команды thread было обнаружено, что ЦП в основном потребляется вTreeUtilизfindMenuChildrenЧто касается метода, используйте команду монитора, чтобы просмотреть конкретное время вызова и время, затрачиваемое на метод.

# 5s为一个统计周期,统计TreeUtil中findMenuChildren方法的耗时
monitor -c 5 ***.TreeUtil findMenuChildren

5.png

С помощью команды монитора можно увидеть, что среднее время одного вызова этого метода составляет 17 ~ 20 мс, но количество вызовов велико, поэтому общий отклик страницы медленный.

4. Декомпилируйте класс TreeUtil с помощью команды jad и просмотрите исходный код

[arthas@12196]$ jad com.durian.ddp.utils.TreeUtil
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@18b4aac2
  +-sun.misc.Launcher$ExtClassLoader@244038d0
Location:
/*
 * Decompiled with CFR.
 *
 * Could not load the following classes:
 *  ***.ResourceTreeVo
 */
...
public class TreeUtil {
    public static ResourceTreeVo findMenuChildren(ResourceTreeVo resourceTreeVo, List<ResourceTreeVo> treeNodes) {
        for (ResourceTreeVo resource : treeNodes) {
            if (!resourceTreeVo.getResourceId().equals(resource.getResourceParentId())) continue;
            if (resourceTreeVo.getChildResourceVo() == null) {
                resourceTreeVo.setChildResourceVo(new ArrayList());
            }
            resourceTreeVo.getChildResourceVo().add(TreeUtil.findMenuChildren(resource, treeNodes));
        }
        return resourceTreeVo;
    }
    public static List<ResourceTreeVo> recursiveTree(List<ResourceTreeVo> list) {
        ArrayList<ResourceTreeVo> trees = new ArrayList<ResourceTreeVo>();
        for (ResourceTreeVo treeNode : list) {
            if (!StringUtils.isEmpty(treeNode.getResourceParentId())) continue;
            trees.add(TreeUtil.findMenuChildren(treeNode, list));
        }
        return trees;
    }
}

Просмотрев исходный код через команду jad, можно обнаружить, что бизнес-логика здесь примерно черезResourceTreeVoобъектresourceParentIdСписок полей для построения дерева. существуетfindMenuChildrenВ методе есть рекурсивные вызовы, и каждый вызов должен проходить через весьResourceTreeVoСписок для поиска дочерних узлов, временная сложность O (n). так вResourceTreeVoКогда элементов списка много, это займет много времени.

5. Решение проблем

Проблему легко решить, найдя ее, можно заранее составить список на основе списка.parentId->List<ResourceTreeVo>Карту каждого узла можно получить из карты при просмотре списка дочерних узлов. Это делает алгоритм построения всего дерева O (n).

Случай 2: количество подключений к потоку приложения ненормально

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

6.png

1. команда потока для просмотра информации о потоке

Запустите Arthas, подключитесь к соответствующему процессу Java и выполните поток, чтобы проверить его статус.

# 查看线程情况
thread 

7.png

8.png

увидеть многоMasterListener-mymaster-*Нить находится в подключенном состоянии и не была выпущена.

# 选择其中一个线程查看堆栈信息
thread id  

9.png

Откройте для себя эти потокиredis.clients.JedisSentinelPool$MasterListenerСгенерировал, тогда давайте проверимJedisSentinelPool$MasterListenerситуация со звонком.

2. команда стека для просмотра информации о стеке

stack redis.clients.jedis.JedisSentinelPool$MasterListener

Инициируйте запрос приложения и распечатайте следующую информацию о стеке:

10.png

Найдите в цепочке вызововRedisUtilКласс, чтобы узнать, будет ли запускаться каждый запросRedisUtil.getJedisвызов методаJedisSentinelPool$MasterListener, то следующим шагом будет декомпиляцияREedisUtilДобрый.

3. команда jad для декомпиляции и просмотра кода

# 反编译RedisUtil类
jad cn.com.zybank.testredis.starter.RedisUtil

11.png

ПроверитьgetJedisметод, обнаружитьgetJedisКаждый вызов будет создавать новыйJedisSentinelPool.

12.png

В результате анализа обнаружено, что каждый раз, когда используется redis, он будет вызыватьсяgetJedisметод создания новогоJedisSentinelPool, тем самым запустивMasterListener-mymaster-*Поток, поскольку поток будет продолжать прослушивание все время и не будет автоматически освобожден, количество потоков продолжает увеличиваться с увеличением запросов приложений, что приводит к заполнению числа соединений.

4. Решение проблем

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

4. Сводные рекомендации

До того, как я начал использовать Arthas, устранение неполадок через Интернет часто требовало ряда операций, таких как network, jps, jstack, jmap, jhat, jstat, hprof и т. д., которые отнимали много времени и сил. В настоящее время с Артасом можно легко обнаружить и быстро решить наиболее распространенные проблемы.

Установка и запуск Arthas в один клик

  • Способ 1. Внедрение удаленной диагностики Arthas одним щелчком мыши с помощью Cloud Toolkit.

Cloud Toolkit — это бесплатный локальный подключаемый модуль IDE, выпущенный Alibaba Cloud, чтобы помочь разработчикам более эффективно разрабатывать, тестировать, диагностировать и развертывать приложения. С помощью подключаемых модулей локальные приложения можно развернуть на любом сервере или даже в облаке (ECS, EDAS, ACK, ACR и облако апплетов и т. д.) одним щелчком мыши, а диагностика Arthas, инструмент Dubbo, терминальный терминал, загрузка файлов, функция расчет и инструменты, такие как MySQL Executor. Не только основная версия IntelliJ IDEA, но и другие версии, такие как Eclipse, Pycharm, Maven и т. д.

Рекомендуется использовать плагин IDEA для загрузки Cloud Toolkit для использования Arthas:He. Special. Talent/2A5CB HW VE ox…

  • Способ 2: Прямая загрузка

адрес:GitHub.com/Alibaba/art….

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

  • При трассировке, пока в цепочке вызовов присутствует асинхронность, стек будет разорван, и трассировка не может быть отслежена до подпотока, а трассировка может выполняться только вручную слой за слоем, что неэффективно.
  • Я надеюсь, что команда tt может добавить асинхронный переключатель.Если переключатель включен, то COST может отображать время, необходимое для получения результата асинхронно.

На данный момент Arthas GitHub Star превысил 24 000. Я надеюсь, что Arthas сможет завоевать внимание и любовь большего числа глобальных разработчиков, и я также ожидаю, что больше отечественных высококачественных проектов, таких как Arthas, будут с открытым исходным кодом.

Arthas Call for Papers в самом разгаре

Артас держит призыв к бумагам, если у вас есть:

  • Устранение неполадок с Артасом
  • Интерпретация исходного кода Артаса
  • Сделать предложение Артасу
  • Не ограничено, другой контент, связанный с Артасом

Приглашаем принять участие в писательской деятельности, и есть призы, которые можно выиграть~Нажмите, чтобы отправить

"Облачная нативная платформа AlibabaСосредоточьтесь на микросервисах, бессерверных технологиях, контейнерах, Service Mesh и других технических областях, сосредоточьтесь на популярных тенденциях облачных технологий и практиках крупномасштабного внедрения облачных технологий, а также станьте официальной учетной записью самых облачных разработчиков. "