About

Все публикации с тегом “xkcd”

Jabberdict

Запустил новый проект Jabberdict. Это такой бот-словарь для Jabber/XMPP. Написан на Google App Engine.

До того момента у меня был простой бот-словарь с несколькими тысячами пользователей. Бот жил на сервере JB (спасибо, JB!). К сожалению, старый сервер JB каким-то образом заменили на новый с 256 Мб ОЗУ, а в такой ситуации не до ботов.

Я не хотел бросать словарь, в частности потому, что сам им пользуюсь. Чтобы не перегружать сервер xkcd.ru, я решил переписать словарь на App Engine. Для небольших нагрузок App Engine бесплатен. Стоит заметить, что ограничения по XMPP в бесплатной версии App Engine очень либеральные.

При переезде самой сложной частью оказался, как ни странно, процесс переноса словарей в Datastore. Главная проблема в том, что это довольно долгий процесс. В силу распределенности Datastore запись происходит намного медленнее чтения.

Грубо говоря, процесс был таким: StarDict → слегка модифицированный PyStarDict → csv → Datastore. Конец истории хороший, но более 85% бесплатной квоты (1 Гб) уже израсходовано, хотя все словари в формате csv занимали не более 400 Мб; и это при том, что от части словарей пришлось отказаться. Datastore хранилище универсальное, а значит имеет большой оверхед (нужно хранить названия и типы полей каждой записи, а не только их значения).

Следующим этапом была рассылка сообщений старым пользователям. Логично было бы сделать из старого бота простой автоответчик, но новый ejabberd забыл все подписки. В этом случае все видят бота офлайн (даже рассылка presence вручную не до конца решает проблему). Поэтому пришлось активно рассылать сообщения. Собственно говоря, на данный момент процесс рассылки все ещё не закончен (и не закончится ещё как минимум неделю).

Всех интересующихся приглашаю пользоваться. Отзывы отправляются командой «!feedback» любому из словарей.

Исходники xkcd.ru

Под влиянием LiveJournal userhoverhell‘а наконец-то выложил исходники архива на bitbucket. Если кому-то это интересно, изучайте: bitbucket.org/Davydov/xkcdru.

Помимо этого я начал прикручивать постинг в LJ для архива. В связи с чем я выдрал из Zapys файл lj.py. Теперь lj.py живёт независимой жизнью: bitbucket.org/Davydov/ljpy. Из того, что добавил я, следует отметить (безопасную) challenge-response авторизацию. Написал маленький пример использования. Тимофей Бабич собирается включить обновлённую версию lj.py обратно в Zapys.

Ну и до кучи выложил исходники grtoolkit там же. Исходники самого расширения легко достаются из .XPI, интерес представляет лишь система сборки, которая в .XPI не попадает. Система довольно странная (на основе препроцессора GPP), но для меня удобная.

Проблемы Google Reader

Некоторое время назад решил сделать главную страницу архива редиректом HttpResponseRedirect на последний переведённый комикс.

Столкнулся с двумя проблемами. Во-первых, Google теперь не знает, как называется сайт, и в поиске выдаётся ссылка на главную страницу с заголовком последнего проиндексированного перевода. Во-вторых, если в Google Reader добавить RSS по адресу http://www.xkcd.ru (а не http://www.xkcd.ru/feeds/xkcd), то Reader берёт название подписки не из соответствующего поля фида, а по названию сайта, то есть по названию последнего переведённого комикса.

Интересно, что с этим теперь делать?

Стресс-тест

Напомню, что недавно я столкнулся с тем, что в какой-то момент сервер затыкался и переставал отдавать данные наружу. Перезагрузка Apache, как правило, помогала.

Мои наблюдения показали, что дело было в расходе оперативной памяти. Постфактум я попытался удостовериться, что правильно диагностировал проблему.

Сначала решил попробовать httperf от HP, но нагрузка, которую он создаёт, слишком далека от реальной (вероятно, можно что-то сделать, чтобы приблизить условия к боевым, но сходу ничего не придумалось).

Решил сделать свой небольшой стресс-тест:

#!/bin/sh
COUNT=5
for site in $@; do
  for num in `seq $COUNT`; do
    out=`mktemp -d -p .`
    wget --append-output=log --no-verbose --mirror -P $out $site &
  done
done

Этот скрипт на каждый URL, переданный ему в качестве параметра, создаёт COUNT Wget’ов, рекурсивно выкачивающих сайт. Никакой статистики скрипт не отдаёт, но можно в живую понаблюдать за расходом памяти, например, при помощи htop.

На моём сервере крутится архив переводов (два экземпляра), этот блог и несколько редко используемых legacy PHP скриптов. На всё это отводится 294 Mb.

Для тестирования я передавал скрипту 3 URL’а: архив, блог и один из PHP скриптов. Итого 15 Wget’ов. Помимо этого я периодически при помощи Firefox’а проверял, откликается ли сервер.

Итак, что же показал тест? При работе Apache через 5 минут свободная память заканчивалась, и начинал расти своп. На запросы сервер отвечал, но иногда с огромной задержкой. В том случае, если в качестве сервера выступал lighty, максимум, которого мне удалось достичь — это 142 Mb.

В общем, ничего удивительного. Насколько я понимаю, высокое потребление памяти
mod_python — это общеизвестный факт. И, наверняка, есть масса способов уменьшить потребление памяти в Apache. С другой стороны, мне нужно лишь небольшое подмножество функций Apache, так что переход на lighttpd — это неплохо: там и конфигурация чуть более очевидная, и ресурсов ему нужно меньше, и со статикой он работает лучше.

lighttpd

За некоторое время MySQL и Apache 2 съедали всю доступную память. Решил вопрос радикально: установил lighttpd с FastCGI.

Потребление памяти радикально уменьшилось. Посмотрим, что будет под нагрузкой. В статье пишут, что lighty течёт.

Документация по настройке django+lighttpd есть, но она не подробная и не актуальная.

mod_rewrite у lighttpd не так крут, но мне его хватило.

Обновление архива

Очередное небольшое обновление архива.

Список изменений:

  • Кнопка добавления в закладки.
  • Теперь кликнув на непереведённый комикс можно попасть на страничку с ним. Только для залогиненных.

И самое главное, Андрей любезно согласился выделить нам домен xkcd.ru.

Спасибо, Андрей!

Обновление архива

Сегодня был свободный час, так что я обновил архив переводов xkcd.

Список изменений:

  • По умолчанию теперь показывается последний переведённый комикс.
  • Как побочный эффект, теперь записи в RSS сортирются по дате публикации. Вероятно, пользователи некоторых RSS-читалок это заметят.
  • Кстати, RSS фид теперь указывает на правильный адрес архива.
  • Убрана дурацкая ссылка на википедию из меню навигации.
  • Теперь старые ссылки на неопубликованные переводы (вида http://xkcd.myths.ru/777/1223398281/) продолжают работать после публикации перевода.

Время простоя, как всегда, маленькое. На этот раз несколько секунд (с момента изменения таблицы до перезапуска Apache).

7 минут

Во время переезда на новый хостинг сервер не работал около семи минут. На сервере находятся две версии архива: обычная и отладочная. Естественно, они используют разные базы данных. Поэтому можно довольно свободно экспериментировать с отладочной версией, не боясь поломать основную. Когда отладочная версия работает хорошо, можно сделать hg pull path_to_dev && hg update, и обычная версия обновится до отладочной.

Процедура переезда была такова:

  1. Копирование исходников обеих версий на новый сервер.
  2. Изменение исходников отладочной версии до рабочего состояния (в основном исправление путей к файлам и путей на сервере).
  3. Отключение возможности записи в базу данных на старом сервере. Да, это довольно грубый хак, но в рассылке все были предупреждены. В MySQL это делается приблизительно так: mysql> REVOKE INSERT,DELETE,UPDATE on db.* from 'usr'@'localhost'; flush privileges;
  4. Создание на новом домене (DNS запись которого была предусмотрительно переведена на новый сервер) новой рабочей копии архива. Для этого на старом сервере делаем: python manage.py dumpdata > backup.json. Затем на новом python manage.py syncdb, python manage.py (вывод передаём в ваш любимый клиент) и python manage.py loaddata backup.json.
  5. Создание редиректа при помощи mod_rewrite со старого сервера на новый (несколько простых правил). Собственно, на этом пункте и возник простой. Он длился точно не более 7 минут, а скорее всего меньше. Если бы я не поленился и отладил правила для mod_rewrite на другом сервере, то задержка составляла бы несколько секунд.
  6. Поднятие виртуального хоста для старого домена на новом сервере.
  7. Изменение DNS старого домена на новый сервер.

Вся процедура заняла около двух часов спокойной работы (включая не быстрое перекачивание всех картинок со старого сервера на новый).

Пока, FirstVds, здравствуй, TekTonic

Желание создать свой технический блог победило.

Вскоре, впрочем, оказалось, что 64 Мб, которые предлагает на самом дешёвом тарифе FirstVDS, — это очень мало для двух разных Django сайтов: блога на Byteflow и архива переводов xkcd. При одновременной работе двух сайтов они начинали страшно тормозить, и иногда вместо нужной страницы сервер выдавал ответ нулевой длины. Причём, я опасался, что 96 Мб на более дорогом тарифе не изменят ситуацию радикально.

По совету Ивана Сагалаева я купил себе VDS на TekTonic. За немного большие деньги (от 15$ в месяц) я получаю намного больше: 13 Гб под файлы (против 1 Гб), 294 Мб оперативной памяти (против 64 Мб), 500 Гб трафика (против 25 Гб) и 64-битную Ubuntu, c который я имею больший опыт общения, чем с FreeBSD. Единственный замеченный на данный момент недостаток: терминал работает несколько медленней. Видимо, сказывается то, что сервера находятся дальше.