http://iakov.davydov.name/blog/tag/xkcd/Iakov Davydov blog blog posts with tag intersection xkcd2011-04-15T12:23:52ZIakovdjango-atompubhttp://iakov.davydov.name/blog/2011/04/15/jabberdict/Jabberdict2011-04-15T12:23:52Z2011-04-15T10:47:39Z<p>Запустил новый проект <a href="http://www.jabberdict.ru">Jabberdict</a>. Это такой бот-словарь для Jabber/<span class="caps">XMPP</span>. Написан на <a href="http://code.google.com/appengine/">Google App Engine</a>.</p> <p>До того момента у меня был <a href="http://code.google.com/p/dictbot/">простой бот-словарь</a> с несколькими тысячами пользователей. Бот жил на сервере <a href="http://www.linux.org.ru/people/JB/profile"><span class="caps">JB</span></a> (спасибо, <span class="caps">JB</span>!). К сожалению, старый сервер <span class="caps">JB</span> каким-то образом заменили на новый с 256 Мб ОЗУ, а в такой ситуации не до&nbsp;ботов.</p> <p>Я не хотел бросать словарь, в частности потому, что сам им пользуюсь. Чтобы не перегружать сервер <a href="http://xkcd.ru">xkcd.ru</a>, я решил переписать словарь на App Engine. Для небольших нагрузок App Engine бесплатен. Стоит заметить, что <a href="http://code.google.com/appengine/docs/quotas.html#XMPP">ограничения по <span class="caps">XMPP</span></a> в бесплатной версии App Engine очень&nbsp;либеральные.</p> <p>При переезде самой сложной частью оказался, как ни странно, процесс переноса словарей в <a href="http://code.google.com/appengine/docs/python/datastore/">Datastore</a>. Главная проблема в том, что это довольно долгий процесс. В силу распределенности Datastore запись происходит намного медленнее&nbsp;чтения.</p> <p>Грубо говоря, процесс был таким: <a href="http://stardict.sf.net">StarDict</a> → слегка модифицированный <a href="https://github.com/lig/pystardict">PyStarDict</a> → csv → Datastore. Конец истории хороший, но более 85% бесплатной квоты (1 Гб) уже израсходовано, хотя все словари в формате csv занимали не более 400 Мб; и это при том, что от части словарей пришлось отказаться. Datastore хранилище универсальное, а значит имеет большой оверхед (нужно хранить названия и типы полей каждой записи, а не только их&nbsp;значения).</p> <p>Следующим этапом была рассылка сообщений старым пользователям. Логично было бы сделать из старого бота простой автоответчик, но новый <a href="http://www.ejabberd.im/">ejabberd</a> забыл все подписки. В этом случае все видят бота офлайн (даже рассылка presence вручную не до конца решает проблему). Поэтому пришлось активно рассылать сообщения. Собственно говоря, на данный момент процесс рассылки все ещё не закончен (и не закончится ещё как минимум&nbsp;неделю). </p> <p>Всех интересующихся приглашаю пользоваться. Отзывы отправляются командой «!feedback» любому из&nbsp;словарей.</p> http://iakov.davydov.name/blog/2009/01/22/xkcdru-sources/Исходники xkcd.ru2011-04-11T00:44:26Z2009-01-22T16:23:37Z<p>Под влиянием <a href="http://hoverhell.livejournal.com/profile"><img src="http://l-stat.livejournal.com/img/userinfo.gif?v=2" alt="LiveJournal user" /></a><a href="http://hoverhell.livejournal.com/">hoverhell</a>&#8216;а наконец-то выложил исходники <a href="http://www.xkcd.ru">архива</a> на <a href="http://www.bitbucket.org">bitbucket</a>. Если кому-то это интересно, изучайте: <a href="http://bitbucket.org/Davydov/xkcdru">bitbucket.org/Davydov/xkcdru</a>.</p> <p>Помимо этого я начал прикручивать постинг в <a href="http://www.livejounral.com"><span class="caps">LJ</span></a> для архива. В связи с чем я выдрал из <a href="http://clear.com.ua/en/projects/python/zapys">Zapys</a> файл <code>lj.py</code>. Теперь <code>lj.py</code> живёт независимой жизнью: <a href="http://bitbucket.org/Davydov/ljpy">bitbucket.org/Davydov/ljpy</a>. Из того, что добавил я, следует отметить (безопасную) challenge-response авторизацию. Написал <a href="http://bitbucket.org/Davydov/ljpy/src/tip/example.py">маленький пример использования</a>. <a href="http://clear.com.ua/ru/">Тимофей Бабич</a> собирается включить обновлённую версию <code>lj.py</code> обратно в&nbsp;Zapys.</p> <p>Ну и до кучи выложил исходники <a href="http://www.myths.ru/grtoolkit">grtoolkit</a> <a href="http://bitbucket.org/Davydov/grtoolkit">там же</a>. Исходники самого расширения легко достаются из <code>.XPI</code>, интерес представляет лишь система сборки, которая в <code>.XPI</code> не попадает. Система довольно странная (на основе препроцессора <a href="http://en.nothingisreal.com/wiki/GPP"><span class="caps">GPP</span></a>), но для меня&nbsp;удобная.</p> http://iakov.davydov.name/blog/2009/01/18/google-reader-problems/Проблемы Google Reader2009-01-18T19:00:52Z2009-01-18T18:40:38Z<p>Некоторое время назад решил сделать <a href="http://www.xkcd.ru">главную страницу архива</a> редиректом <a href="http://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpResponseRedirect">HttpResponseRedirect</a> на последний переведённый&nbsp;комикс. </p> <p>Столкнулся с двумя проблемами. Во-первых, <a href="http://www.google.com">Google</a> теперь не знает, как называется сайт, и в поиске выдаётся ссылка на главную страницу с заголовком последнего проиндексированного перевода. Во-вторых, если в <a href="http://reader.google.com">Google Reader</a> добавить <span class="caps">RSS</span> по адресу <a href="http://www.xkcd.ru">http://www.xkcd.ru</a> (а не <a href="http://www.xkcd.ru/feeds/xkcd">http://www.xkcd.ru/feeds/xkcd</a>), то Reader берёт название подписки не из соответствующего поля фида, а по названию сайта, то есть по названию последнего переведённого&nbsp;комикса. </p> <p>Интересно, что с этим теперь&nbsp;делать? </p>http://iakov.davydov.name/blog/2008/12/28/stress-test/Стресс-тест2008-12-28T01:00:20Z2008-12-28T00:19:32Z<p>Напомню, что недавно я столкнулся с тем, что в какой-то момент сервер затыкался и переставал отдавать данные наружу. Перезагрузка <a href="http://httpd.apache.org/">Apache</a>, как правило,&nbsp;помогала. </p> <p>Мои наблюдения показали, что дело было в расходе оперативной памяти. <a href="http://iakov.davydov.name/blog/2008/12/27/lighttpd/">Постфактум</a> я попытался удостовериться, что правильно диагностировал&nbsp;проблему. </p> <p>Сначала решил попробовать <a href="http://www.hpl.hp.com/research/linux/httperf/">httperf</a> от <a href="http://hp.com"><span class="caps">HP</span></a>, но нагрузка, которую он создаёт, слишком далека от реальной (вероятно, можно что-то сделать, чтобы приблизить условия к боевым, но сходу ничего не&nbsp;придумалось). </p> <p>Решил сделать свой небольшой&nbsp;стресс-тест: </p> <pre><code>#!/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 <span class="amp">&amp;</span> done done </code></pre><p>Этот скрипт на каждый <span class="caps">URL</span>, переданный ему в качестве параметра, создаёт <code>COUNT</code> <a href="http://www.gnu.org/software/wget/">Wget&#8217;ов</a>, рекурсивно выкачивающих сайт. Никакой статистики скрипт не отдаёт, но можно в живую понаблюдать за расходом памяти, например, при помощи <a href="http://htop.sourceforge.net/">htop</a>. </p> <p>На моём сервере крутится <a href="http://www.xkcd.ru">архив переводов</a> (два экземпляра), этот блог и несколько редко используемых legacy <a href="http://php.net"><span class="caps">PHP</span></a> скриптов. На всё это отводится 294&nbsp;Mb. </p> <p>Для тестирования я передавал скрипту 3 <span class="caps">URL</span>&#8217;а: архив, блог и один из <span class="caps">PHP</span> скриптов. Итого 15 Wget&#8217;ов. Помимо этого я периодически при помощи <a href="http://mozilla.org">Firefox&#8217;а</a> проверял, откликается ли&nbsp;сервер. </p> <p>Итак, что же показал тест? При работе Apache через 5 минут свободная память заканчивалась, и начинал расти своп. На запросы сервер отвечал, но иногда с огромной задержкой. В том случае, если в качестве сервера выступал <a href="http://lighttpd.net">lighty</a>, максимум, которого мне удалось достичь &mdash; это 142&nbsp;Mb. </p> <p>В общем, ничего удивительного. Насколько я понимаю, высокое потребление памяти<br /> <a href="http://www.modpython.org/">mod_python</a> &mdash; это общеизвестный факт. И, наверняка, есть масса способов уменьшить потребление памяти в Apache. С другой стороны, мне нужно лишь небольшое подмножество функций Apache, так что переход на lighttpd &mdash; это неплохо: там и конфигурация чуть более очевидная, и ресурсов ему нужно меньше, и со статикой он работает&nbsp;лучше. </p>http://iakov.davydov.name/blog/2008/12/27/lighttpd/lighttpd2008-12-27T18:40:22Z2008-12-27T18:28:28Z<p>За некоторое время <a href="http://mysql.com">MySQL</a> и <a href="http://httpd.apache.org/">Apache 2</a> съедали всю доступную память. Решил вопрос радикально: установил <a href="http://www.lighttpd.net/">lighttpd</a> с <a href="http://www.fastcgi.com/drupal/">FastCGI</a>. </p> <p>Потребление памяти радикально уменьшилось. Посмотрим, что будет под нагрузкой. В <a href="http://hostingfu.com/article/nginx-vs-lighttpd-for-a-small-vps">статье</a> пишут, что lighty&nbsp;течёт. </p> <p>Документация по настройке <a href="http://djangoproject.com">django</a>+lighttpd есть, но она не подробная и не&nbsp;актуальная. </p> <p>mod_rewrite у lighttpd не так крут, но мне его&nbsp;хватило. </p>