Вы пишете код с ошибками? Нет, конечно нет. Для остальных из нас, простых смертных, которые пишут код с ошибками, я хотел бы решить очень деликатную проблему: отладку приложения, работающего на рабочем сервере.
Итак, ваше приложение готово к развертыванию. Модульные тесты были успешными, тестеры обнаружили некоторые незначительные ошибки, которые были немедленно исправлены, интеграционные тесты с модулями другого отдела прошли довольно гладко, отдел QA не жаловался, и UAT были переданы с плавающими цветами. Таким образом, ваш потрясающий код теперь запущен и работает на рабочем сервере.
Когда происходит немыслимое. Ваш клиент замечает некоторое некорректное поведение приложения, и некоторые из его клиентов уже начали жаловаться. Кажется, что какая-то неприятная маленькая ошибка сумела пройти все процедуры тестирования и добраться до работающей системы. Пользователи клиента оказывают давление на клиента, менеджеры клиентов оказывают давление на ваших менеджеров, и, знаете, что ваши менеджеры начинают давить на вас.
Вы запускаете тестовый сервер и пытаетесь воспроизвести ошибку . Увы, на тестовом сервере все работает правильно, поэтому это может быть странная проблема конфигурации или крайний случай, вызывающий проблемное поведение. Суть в том, что вы не можете отследить ошибку с помощью своего тестового стенда.
Что должен делать бедный разработчик? Отладка приложения, работающего на рабочем сервере. Обратите внимание, что это следует рассматривать как последнее средство и когда все другие попытки обнаружить ошибку потерпели неудачу. Убедитесь, что малейшее неправильное перемещение на рабочем сервере (обслуживающем большое количество пользователей) может серьезно повлиять на работу приложения и вызвать еще большие проблемы или полное отключение службы.
Итак, если вы решите пойти по рискованному пути, прочитайте, как это сделать. Некоторые основные рекомендации, прежде чем начать. Прежде всего, сообщите своему клиенту, что вы подключитесь к производственной системе и «выполните некоторые проверки». Вам не нужно быть конкретным в отношении того, что будет сделано, но, безусловно, ничего не делать без информирования клиента. Во-вторых, выберите время, когда реальный трафик будет как можно ниже. Это не сложно, вы хотите, чтобы как можно меньше пользователей было затронуто, плюс вы не хотите, чтобы сервер работал под большой нагрузкой. В-третьих, будьте осторожны и старайтесь не спешить. Там может быть давление, но не торопитесь, будет легче отследить проблему.
Я буду использовать JBoss AS и Eclipse для предоставления практического примера того, как выполнять отладку. Мы смоделируем работающее приложение, развернув простой фрагмент кода на JBoss и выполнив определенный метод. На большинстве серверов приложений на основе Java достаточно просто настроить JVM с включенной удаленной отладкой. Затем вы используете вашу любимую IDE, в моем случае Eclipse, чтобы подключить отладчик к порту сервера и начать отладку. Обратите внимание, что включение удаленной отладки приводит к небольшому снижению производительности, но я обычно предпочитаю включить параметр отладки, чтобы я мог подключаться к серверу по желанию. В другом случае для применения новых настроек потребуется перезапуск JVM, то есть перезапуск сервера.
Во-первых, давайте создадим код, который будет выполнять отладку. Мы будем использовать Java MBean, который развернут на JBoss и имеет предопределенный жизненный цикл. MBeans — это управляемые bean-объекты, объекты Java, представляющие ресурсы, которыми нужно управлять. JBoss фактически обеспечивает реализацию сервера MBean , поэтому на нем можно развернуть MBean.
Самый простой способ — расширить абстрактный класс ServiceMBeanSupport и реализовать сервис, соответствующий интерфейсу ServiceMBean . Сначала мы создаем проект Eclipse с именем «SimpleMBeanProject». Затем мы создаем интерфейс, который должен реализовать наш сервис. Исходный код:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
package com.javacodegeeks.jboss; import org.jboss.system.ServiceMBean; public interface SimpleServiceMBean extends ServiceMBean { void start() throws Exception; void stop(); String getName(); void execute(String input); } |
Затем мы создаем соответствующий класс реализации:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package com.javacodegeeks.jboss; import org.jboss.system.ServiceMBeanSupport; public class SimpleService extends ServiceMBeanSupport implements SimpleServiceMBean { @Override public void start() throws Exception { System.out.println( "Starting SimpleService MBean" ); } @Override public void stop() { System.out.println( "Stopping SimpleService MBean" ); } @Override public String getName() { return SimpleService. class .getCanonicalName(); } public void execute(String input) { System.out.println( "Executing with input " + input); } } |
Код действительно упрощен, но с достаточной функциональностью для демонстрационных целей. Метод «execute» — это метод, который будет вызываться для эмуляции запущенного приложения.
Способ развертывания MBean заключается в объединении двух классов в файл служебного архива (SAR) . Этот файл является заархивированным файлом, который включает в себя классы MBean и соответствующий дескриптор развертывания, который в данном случае является файлом с именем «jboss-service.xml» со следующим содержимым:
1
2
3
4
5
6
7
8
9
|
<? xml version = "1.0" encoding = "UTF-8" ?> < service > < mbean code = "com.javacodegeeks.jboss.SimpleService" name = "javacodegeeks:name=SimpleService" > </ mbean > </ service > |
Файл «jboss-service.xml» должен находиться в папке с именем «META-INF» внутри пакета SAR. Затем архив должен быть помещен в каталог <jboss-base-dir> / server / default / deploy для развертывания MBean. Архив может быть создан вручную, в конце концов, это просто заархивированный файл, но более элегантным способом является создание сценария ANT , который автоматизирует процедуру.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<? xml version = "1.0" encoding = "UTF-8" ?> < project name = "SimpleService Project Build" default = "build-sar" > < target name = "init" > < property name = "base.dir" value = "." /> < property name = "lib.dir" value = "${base.dir}/lib" /> < property name = "bin.dir" value = "${base.dir}/bin" /> < property name = "src.dir" value = "${base.dir}/src" /> < property name = "dist.dir" value = "${base.dir}/dist" /> < delete dir = "${dist.dir}" /> < mkdir dir = "${dist.dir}" /> </ target > < target name = "compile" depends = "init" > < echo message = "Compiling source files..." /> < javac destdir = "${bin.dir}" debug = "on" > < src path = "${src.dir}" /> < classpath > < fileset dir = "${lib.dir}" > < include name = "**/*.jar" /> </ fileset > </ classpath > < include name = "**/*.java" /> </ javac > </ target > < target name = "build-sar" depends = "compile" > < jar destfile = "dist/SimpleService.sar" > < zipfileset dir = "bin" > < include name = "com/javacodegeeks/**/*.class" /> </ zipfileset > < zipfileset dir = "resources" prefix = "META-INF" > < include name = "jboss-service.xml" /> </ zipfileset > </ jar > </ target > </ project > |
Когда SAR будет развернут, MBean «SimpleService» появится на консоли JMX сервера. Это веб-интерфейс, доступ к которому можно получить по следующему URL-адресу (замените хост соответственно):
HTTP: // хост: 8080 / JMX-консоль
Прокрутите вниз, пока не найдете запись «name = SimpleService» и перейдите по ссылке. Атрибуты Mbean вместе со списком операций появятся там.
Вы можете вручную вызвать метод execute с аргументом String, и соответствующий ввод будет записан в стандартный вывод.
Хорошо, после развертывания SAR пришло время начать отладку. Первым шагом является запуск JVM JBoss с включенной удаленной отладкой сокетов. Конечно, это делается с помощью аргументов JVM, и для его настройки необходимо сделать следующее:
Платформа Linux: Откройте файл /bin/run.conf и раскомментируйте строку (удалите «#»), которая гласит:
JAVA_OPTS = ”$ JAVA_OPTS -Xrunjdwp: транспорт = dt_socket, адрес = 8787, сервер = y, приостановить = n”
Платформа Windows: откройте файл /bin/run.bat и раскомментируйте строку (удалите ключевое слово «rem»)
set JAVA_OPTS = -Xdebug -Xrunjdwp: transport = dt_socket, address = 8787, server = y, suspend = n% JAVA_OPTS%
Используемый порт — 8787. Убедитесь, что для параметра «suspend» установлено значение «n» (отключено) или, в другом случае, при первом запуске сервера он остановится и будет ждать, пока удаленный отладчик не выполнит команду быть прикрепленным, прежде чем продолжить.
После этого запустите сервер нормально. Настало время подключиться к серверу через Eclipse. Перейти к «Бежать? Отладка конфигураций… », а затем дважды щелкните параметр« Удаленное приложение Java ». На вкладке «Подключение» убедитесь, что выбран «SimpleMBeanProject», укажите IP-адрес или имя хоста «хоста» (в моем случае «localhost») и «Порт», который сервер прослушивает для входящих сеансов отладки (8787 как настроено ранее). Наконец, убедитесь, что «Разрешить завершение удаленной виртуальной машины» НЕ выбрано, потому что если это так, JVM сервера отключится, как только вы отключите отладку. Не очень хорошая вещь, чтобы случиться с производственным сервером. Хорошо, нажмите кнопку «Отладка», чтобы продолжить.
Если удаленная отладка не включена или если есть проблема с подключением (возможно, проблема с брандмауэром), вы увидите следующее изображение:
Но если все работает правильно, отладчик Eclipse присоединится к серверу, и вы должны увидеть что-то вроде этого:
Как видите, отслеживаемые потоки отображаются в представлении «Отладка». Если этот вид не появляется, перейдите к «Окно? Показать вид? Другое … »и найдите его в категории« Отладка ».
Теперь давайте предположим, что метод execute класса «SimpleService» имитирует код, который выполняется на рабочем сервере при каждом входящем запросе. Если вы выполняли отладку на тестовом сервере, все, что вам нужно было сделать, это добавить точку останова внутри метода, вызвать запрос и продолжить отладку. Однако что-то подобное точно не будет работать на производственном сервере. В тот момент, когда вы переключаете точку останова, все запросы приостанавливаются и ждут вашего действия (если, конечно, путь выполнения проходит от этого метода). Это остановит выполнение запросов и, скорее всего, будет замечено пользователями. Кроме того, вы будете поражены масштабами запросов, которые вам придется отслеживать одновременно.
Что вам нужно сделать, это добавить условную точку останова, которая будет останавливаться только тогда, когда предоставлен конкретный ввод, то есть тот, который вы предоставляете. Итак, отключитесь от удаленного сервера, а затем добавьте точку останова в метод «execute» (в строке 23). Затем щелкните правой кнопкой мыши точку останова и в появившемся меню выберите «Свойства точки останова» (последняя).
Появится меню свойств. Установите флажок «Enable Condition» и в текстовой области введите условие. Точка останова будет действительной и приостановит выполнение только тогда, когда это условие выполнено. Обратите внимание, что вы на самом деле пишете Java-код внутри текстовой области и что вы можете использовать для этого знакомую помощь по коду (используя Ctrl + Space). Разве Eclipse не невероятный инструмент? Мы хотим, чтобы точка останова включалась только тогда, когда аргумент метода — «myinput».
Снова запустите удаленную отладку, и теперь вы уверены, что выполнение будет приостановлено, если вы предоставите свой собственный ввод. Чтобы продемонстрировать это, вернитесь к консоли JMX и представлению MBean «SimpleService». В методе execute используйте случайный аргумент:
Нажмите кнопку «Invoke» и обратите внимание, что Eclipse не приостанавливает выполнение. Теперь используйте «myinput» в качестве входного значения, нажмите «Invoke» и обратите внимание, что Eclipse фиксирует выполнение.
Теперь вы готовы перейти к хорошо известным параметрам отладки (шаг в методы, просмотр значений переменных и т. Д.), Не беспокоясь о том, что это повлияет на пользователей системы.
Вы можете скачать проект Eclipse здесь .
Удачной охоты на жуков!