14 апреля 2009 г.

11 байт

Этап согласования протоколов в моем текущем проекте дал пищу для размышления.

Общая информация: система клиент-серверная,  сервер на джава, клиент нынешний -- на дельфи. Предполагается, что протокол будет открытым, и когда-нибудь информация, предоставляемая через него сервером будет использоваться разными клиентами для разных целей. Система уже существовала в виде версии 1.0, можно считать -- прототипа. Сейчас идет полное переписывание с 0 серверной части, и значительное -- клиентской. 

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

Амбула: обсуждаем формат записи в логе. Унаследованный от прототипа формат такой: каждое измерение одной строкой, в строке время, и, через запятую -- числа-результаты. Время -- в формате hh:mm -- 19:30. Например: 19:30, 123564, 5634565, 345645654, 1233

Первый вопрос, который у меня возник: почему только время? Где дата? Оказывается -- дата берется из названия файла (файлы роллятся каждый день, помните? и дата сохраняется в имени файла). Ок, говорю, но ведь так получается, что запись в логе несамодостаточна -- мало иметь саму строчку, надо знать еще, из какого файла она взялась. Давай вместо (или вместе -- чтобы сохранить обратную совместимость) времени будем писать timestamp -- например, в unix-time. Ответ -- "ну это же лишние 11 байт! Да и парсер надо будет переписывать."

На мой взгляд, это хороший пример того, как
  •  Не надо экономить на спичках. Примерный размер лога за день -- 100Кб. Timestamp может нам сэкономить примерно 10% от этого размера -- 10Кб в день. При том, что сервер, предполагается, мониторит промышленную систему с террабайтами данных -- копейки. Но этого мало: если действительно стоит вопрос оптимизации размера (а его на повестке дня не стояло, и не стоит до сих пор. И при проектировании прототипа, когда этот формат файла создавался, такого вопроса тоже не стояло) то простейшее сжатие логов зипом уменьшит их размер раза в 3-4 -- при полном сохранении данных.
  • Форматы и протоколы надо стараться разрабатывать с возможностью расширения. Почему ради добавления одной колонки надо переделывать парсер?
Как можно было решить эту задачу? С минимальными изменениями я вижу такое решение: первой строчкой в каждом файле идут названия колонок. Таким образом, когда мы разбираем файл, мы обращаемся к колонкам не по индексам (которые могут меняться) а по именам. Парсер сразу же становится переиспользуемым -- один и тот же формат файла с разными именами колонок можно использовать в десятках мест. И формат каждого конкретного файла становится расширяемым с сохранением обратной совместимости -- добавление новой колонки будет проигнорировано старым кодом, который про нее ничего не знает, а новый получит все преимущества