Для игровой платформы Reddwarf (бывший Darkstar) существует собственный профайлер.
Он работает таким образом: записывает информацию обо всех выполненных задачах в бинарный лог собственного формата. Этот лог можно открыть с помощью специальной программы, благодаря которой можно будет посмотреть, что за задачи были выполнены, как долго, сколько задач завершились неудачей. Недостаток данного профайлера в том, что необходимо записывать всю информацию о задачах в большой бинарный лог: на боевом сервере это быстро заполнит диск, к тому же файлы лога надо будет передавать на локальную машину для анализа и просмотра.
Для более удобной работы с результатами профилирования прямо на боевом сервере был написан специальный профайлер. Этот профайлер в прямом эфире собирает данные о выполняемых задачах и периодически (каждую минуту) скидывает суммарную информацию в текстовый файл. Открыв на боевом сервере текстовый файл, можно смотреть, какие задачи нагружают сервер в данный момент.
Страничка проекта: http://code.google.com/p/reddwarf-periodic-profiler/
понедельник, 28 февраля 2011 г.
среда, 16 февраля 2011 г.
Этот безумный JMX, jconsole и 127.0.1.1
В моем сервере на платформе Reddwarf для мониторинга производительности сервера используется JMX.
Для этого добавляю в параметры запуска java-машины
После успешных экспериментов с JConsole я настроил выгрузку данных в cacti. Для этого использовал jmxtrans. Он делает запрос к серверу, получает данные и сохраняет и в архив. Всё замечательно...
Проблемы начались при попытке подключиться к JMX-агенту на боевом сервере. Параметры добавил, перезагрузил...
JConsole подключаться не хочет:
Connection failed: Retry?
The connection to mygameserver.ath.cx:3333 did not succeed.
Would you like to try again?
Без объяснения причин.
Для этого добавляю в параметры запуска java-машины
-Dcom.sun.management.jmxremote.port=3333 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false . В результате сервер запускается с JMX-агентом, к которому можно подключиться с помощью JConsole.После успешных экспериментов с JConsole я настроил выгрузку данных в cacti. Для этого использовал jmxtrans. Он делает запрос к серверу, получает данные и сохраняет и в архив. Всё замечательно...
Проблемы начались при попытке подключиться к JMX-агенту на боевом сервере. Параметры добавил, перезагрузил...
JConsole подключаться не хочет:
Connection failed: Retry?
The connection to mygameserver.ath.cx:3333 did not succeed.
Would you like to try again?
Без объяснения причин.
пятница, 21 мая 2010 г.
Нестабильность Enum.hashCode() и HashMap
На днях обнаружилась любопытная особенность enum'ов. В коде сервера я использовал ScalableHashMap для хранения некоторых данных, где ключом является enum. ScalableHashMap - это специальная реализация хешмапа для сервера Reddwarf.
После первого запуска сервера и инициализации карты всё работало замечательно.
Потом ScalableHashMap был сериализован и сохранен на диск.
Дальше сервер был перезагружен, и ScalableHashMap десериализован с диска.
Делаю ScalableHashMap.get(key) и... получаю null!
Вывожу ScalableHashMap на экран с помощью toString() - там всё есть! Но почему-то он не хочет доставать записанные данные.
Оказалось загвоздка вот в чем:
Enum использует hashCode(), унаследованный от Object(). Следовательно, при перезапуске сервера меняются адреса ссылок, соответственно меняются хеш-коды объектов. И из карты невозможно вытащить объект с новым хеш-кодом, сохраненный по старому хеш-коду!
После первого запуска сервера и инициализации карты всё работало замечательно.
Потом ScalableHashMap был сериализован и сохранен на диск.
Дальше сервер был перезагружен, и ScalableHashMap десериализован с диска.
Делаю ScalableHashMap.get(key) и... получаю null!
Вывожу ScalableHashMap на экран с помощью toString() - там всё есть! Но почему-то он не хочет доставать записанные данные.
Оказалось загвоздка вот в чем:
Enum использует hashCode(), унаследованный от Object(). Следовательно, при перезапуске сервера меняются адреса ссылок, соответственно меняются хеш-коды объектов. И из карты невозможно вытащить объект с новым хеш-кодом, сохраненный по старому хеш-коду!
вторник, 20 апреля 2010 г.
Sun Tech Days 2010
"Как жаль, что эта конференция проходит не в Москве" - думал я в прошлом году, когда понял, что не получится внезапно поехать на Sun Tech Days 2009.
"Как хорошо, что эта конференция проходит не в Москве" - думал я в этом году, прогуливаясь по северной столице по прекрасной погоде, любуясь красотами этого замечательного города и предвкушая много нового и интересного на конференции.
"Как хорошо, что эта конференция проходит не в Москве" - думал я в этом году, прогуливаясь по северной столице по прекрасной погоде, любуясь красотами этого замечательного города и предвкушая много нового и интересного на конференции.
пятница, 19 марта 2010 г.
Как получить Unix PID в Java-приложении
Для контроля работоспособности сервера я использовал monit. Очень удобная штука, единственной сложностью оказалось то, что monit требовал, чтобы приложение писало свой PID в файл.
В результате недолгих поисков был найден способ узнать PID: Java-приложение должно запустить процесс, который выведет PID родителя. Один из самых простых вариантов - выполнить команду "echo $PPID" командного интерпретатора bash ($PPID - переменная, хранящая PID родительского процесса).
В результате недолгих поисков был найден способ узнать PID: Java-приложение должно запустить процесс, который выведет PID родителя. Один из самых простых вариантов - выполнить команду "echo $PPID" командного интерпретатора bash ($PPID - переменная, хранящая PID родительского процесса).
import java.io.*;
public class UnixUtils {
public static String getPid() throws IOException, InterruptedException {
// Запускаем bash с параметром -c, что означает "выполнить команду"
// Командой будет "echo $PPID" - вывести PID родительского процесса
ProcessBuilder pb=new ProcessBuilder("/bin/bash", "-c", "echo $PPID");
Process pr=pb.start();
pr.waitFor();
// Если процесс завершился успешно, вернул код 0, считаем, что он нам вывел
if (pr.exitValue() == 0) {
BufferedReader outReader=new BufferedReader(new InputStreamReader(pr.getInputStream()));
return outReader.readLine().trim();
} else {
return null;
}
}
}
понедельник, 15 февраля 2010 г.
Цветное логирование
Цвета порой очень облегчают восприятие информации.
Попытка раскрасить логи была сделана сначала просто забавы ради, но потом, когда я понял, насколько это удобно, уже не мог работать с однообразными одноцветными логами.
Изначально логи раскрашивались с помощью расширения для logback, но потом оказалось, что удобней писать логи обычным текстом, а раскрашивать - уже при просмотре.
Попытка раскрасить логи была сделана сначала просто забавы ради, но потом, когда я понял, насколько это удобно, уже не мог работать с однообразными одноцветными логами.
Изначально логи раскрашивались с помощью расширения для logback, но потом оказалось, что удобней писать логи обычным текстом, а раскрашивать - уже при просмотре.
понедельник, 11 января 2010 г.
Tomcat и CharConversionException
При разработке сервлета под Tomcat столкнулся со следующей проблемой и долго мучился:
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
java.io.CharConversionException: Not an ISO 8859-1 character: з javax.servlet.ServletOutputStream.print(ServletOutputStream.java:89) dating.servlet.TestServlet.service(TestServlet.java:77) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs.
Apache Tomcat/6.0.20
Подписаться на:
Сообщения (Atom)
