Автор | Юй Шуан инженер по исследованиям и разработкам системы 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
/telnet доступ: ip: 3658
Когда возникает проблема с онлайн-приложением, проблемную машину можно изолировать, а target-ip можно указать при запуске через Arthas, а несколько техников могут проводить устранение неполадок через удаленные подключения одновременно.
2.trace
# 查看方法内部调用路径,并输出方法路径上的每个节点上耗时
trace ClassName methodName
С помощью команды trace можно отслеживать, где тратится время слой за слоем, что очень эффективно при настройке производительности.
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
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
С помощью команды монитора можно увидеть, что среднее время одного вызова этого метода составляет 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: количество подключений к потоку приложения ненормально
описание проблемы: количество дескрипторов сервера исчерпано, и обнаружено, что приложение занимает большое количество дескрипторов.
1. команда потока для просмотра информации о потоке
Запустите Arthas, подключитесь к соответствующему процессу Java и выполните поток, чтобы проверить его статус.
# 查看线程情况
thread
увидеть многоMasterListener-mymaster-*
Нить находится в подключенном состоянии и не была выпущена.
# 选择其中一个线程查看堆栈信息
thread id
Откройте для себя эти потокиredis.clients.JedisSentinelPool$MasterListener
Сгенерировал, тогда давайте проверимJedisSentinelPool$MasterListener
ситуация со звонком.
2. команда стека для просмотра информации о стеке
stack redis.clients.jedis.JedisSentinelPool$MasterListener
Инициируйте запрос приложения и распечатайте следующую информацию о стеке:
Найдите в цепочке вызововRedisUtil
Класс, чтобы узнать, будет ли запускаться каждый запросRedisUtil.getJedis
вызов методаJedisSentinelPool$MasterListener
, то следующим шагом будет декомпиляцияREedisUtil
Добрый.
3. команда jad для декомпиляции и просмотра кода
# 反编译RedisUtil类
jad cn.com.zybank.testredis.starter.RedisUtil
ПроверитьgetJedis
метод, обнаружитьgetJedis
Каждый вызов будет создавать новыйJedisSentinelPool
.
В результате анализа обнаружено, что каждый раз, когда используется 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 и других технических областях, сосредоточьтесь на популярных тенденциях облачных технологий и практиках крупномасштабного внедрения облачных технологий, а также станьте официальной учетной записью самых облачных разработчиков. "