понедельник, 28 февраля 2011 г.

Reddwarf Periodic Profiler 0.1

Для игровой платформы Reddwarf (бывший Darkstar) существует собственный профайлер.
Он работает таким образом: записывает информацию обо всех выполненных задачах в бинарный лог собственного формата. Этот лог можно открыть с помощью специальной программы, благодаря которой можно будет посмотреть, что за задачи были выполнены, как долго, сколько задач завершились неудачей. Недостаток данного профайлера в том, что необходимо записывать всю информацию о задачах в большой бинарный лог: на боевом сервере это быстро заполнит диск, к тому же файлы лога надо будет передавать на локальную машину для анализа и просмотра.

Для более удобной работы с результатами профилирования прямо на боевом сервере был написан специальный профайлер. Этот профайлер в прямом эфире собирает данные о выполняемых задачах и периодически (каждую минуту) скидывает суммарную информацию в текстовый файл. Открыв на боевом сервере текстовый файл, можно смотреть, какие задачи нагружают сервер в данный момент.

Страничка проекта: http://code.google.com/p/reddwarf-periodic-profiler/

среда, 16 февраля 2011 г.

Этот безумный JMX, jconsole и 127.0.1.1

В моем сервере на платформе Reddwarf для мониторинга производительности сервера используется JMX.
Для этого добавляю в параметры запуска 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(). Следовательно, при перезапуске сервера меняются адреса ссылок, соответственно меняются хеш-коды объектов. И из карты невозможно вытащить объект с новым хеш-кодом, сохраненный по старому хеш-коду!

вторник, 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 родительского процесса).

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, но потом оказалось, что удобней писать логи обычным текстом, а раскрашивать - уже при просмотре.


понедельник, 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