Monday, May 25, 2009

Изменил мою ветвь с Merle.

Вернул все файлы которые удалил в своей версии merle. Это нужно для большей совместимости с основной веткой, и возможности обновления с нее с последующим вливанием изменений, если получиться в основную ветвь кода.

Чтобы отключить использование gen_server2 - нужно только переименовать все gen_server2 -> gen_server.

Friday, May 22, 2009

Повышение надежности системы

Повышение надежности предыдущей схемы (используя nginx).

В предыдущей схему существует один потенциально ненадежный элемент backend сервер. При его сбое система через некоторое время утрачивает возможность отрабатывать запросы, так как время кэширования на memcahed заканчивается и все запросы начинают идти на этот сервер. В результате система не может выдать никакого контента пока он не будет перезапущен. Чтобы этого избежать можно дать возможность frontend возвращать данные с просроченным сроком давности, реализовать это на уровне memcached усложняет способ работы с ним:
  • по умолчанию, если закончилось время хранения контент удаляется;
  • и при смене поведения усложняется алгоритм работы с ним из frontend.
В результате наиболее простым методом, если используется в качестве frontend nginx, можно разрешить ему при сбоях использовать собственный кэш (опция proxy_cache_use_stale). Пример:

proxy_cache_path /var/tmp/nginx/cache levels=1:2 keys_zone=one:10m inactive=20m max_size=500m;

server {
listen 80;

location / {
if ( $args = "" ){

set $memcached_key "$uri";
memcached_pass 127.0.0.1:11211;
error_page 404 502 503 504 = @backend;
add_header "Content-Type" "text/html; charset=UTF-8";
add_header "Cache-Control" "max-age=15";
}

proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_buffers 8 32k;

proxy_cache_key "$scheme://$host$uri$is_args$args:";
proxy_cache one;
proxy_cache_min_uses 1;
proxy_cache_valid 200 30s;
proxy_cache_use_stale error timeout http_500 http_502 http_503;

}

location @backend {
proxy_pass http://backend;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header HOST $http_host;
proxy_buffers 8 32k;

proxy_cache_key "$scheme://$host$uri$is_args$args:";
proxy_cache one;
proxy_cache_min_uses 1;
proxy_cache_valid 200 30s;
proxy_cache_use_stale error timeout http_500 http_502 http_503;
}
...............
В данном случае frontend не обязательно слабое звено - его можно продублировать с меньшими затратами по сравнению с дублированием backend + slaveDB.

Thursday, May 21, 2009

Код корректного перезапуска merle

При использование кода связи с memcached возможен случай когда соединение с memcached по каким-то причинам потеряно, например: рестарт memcached.
  • В данном случае возможен случай когда выполнить вызов не удается, но пересоединение не получается (закрытие (disconnect) сообщает - что закрывать нечего, а открытие (connect) сообщает - что уже есть соединение). В данном случае нужно убить это псевдо-рабочее соединение и запустить наново.
  • Другой случай когда соединяться не с кем - тогда метод connect просто выходит, не вызывая исключение, что очень плохо, так как не понятно, что произошло с системой - чтобы отловить эту ситуацию нужно разрешить посылку сигнала о завершении потока и ожидать получение этого сообщения.
Пример кода:

%%use with restart
try_with_restart(LU, F) ->
try
F()
catch
Sub : Reson ->
debug_log(LU, "Start procedure restart connect:~p~n",[{Sub,erlang:get_stacktrace(),Reson}]),
spawn(fun() ->
process_flag(trap_exit, true),
Connect = merle:connect(?MEMCACHED_HOST,?MEMCACHED_PORT),
case Connect of
{error, {already_started, Client}} ->
debug_log(LU, "try kill client status:~p~n",[Connect]),
exit(Client,kill);
Value ->
debug_log(LU, "Some other error:~p~n",[Value])
end,
receive
{'EXIT', Pid, Why} ->
debug_log(LU, "Me killed~p~n", [{Pid, Why}])
end
end),
undefined
end.

Примечание:
  1. F - функция обращающаяся к merle;
  2. debug_log() - вывод в логи отладочной информации.

Sunday, May 17, 2009

merle совместимый с nginx

Выложил коды проектов используемых мною с некоторыми изменениях в них.

Изменения в коде merle (memcached erlang interface) нацелено на совместимость с другими языками программирования, в частности возможность получения сохраненного контента из nginx.

Стандартный код использует binary_to_term для сохранения контента в результате при попытке получить контент из memcahed из других программ, ожидающих возврат обычной строки, в начале контента невозможно так как появляются служебные данные erlang.

В код добавлены функции сохранения как строка merle:setlist( url, time, content), и получения контента в виде строки merle:getkeylist (url). Также удалено использование нестандартного gen_server. Удален только для упрощения поддержки кода, так как усовершенствования по очередям сообщений в проекте были не нужны.

В результате этих изменений удалось организовать систему когда frontend server(использовался nginx) мог не запрашивая backend получить сразу данные из кэша, также получилось использовать как общих кэш и для php.

Остальные функции постарался оставить без изменений их поведения и формата сохраняемых ими данных(term_to_binary), измения заключаются в переносе функций преобразования term_to_binary(getkey) и binary_to_list (getkeylist) из вызовов gen_server.

В erlyweb изменены:
  • опции компиляции по умолчанию, теперь поведение подобно поведению make, когда компилируются только измененные файлы;
  • добавлена обработка исключение при рендеренге компонентов встроенных в основную страницу (вместо него при ошибке выдается указание, что компонент отработал с ошибкой), исключение при отработке основной страницы не отлавливается и передается при ошибке дальше, его нужно отлавливать внутри этой страницы самостоятельно;
  • также, добавлена поддержка использования прописных букв в пути к каталогам с компонентами(ранее использовалось преобразование всех букв к строчным).

Friday, May 15, 2009

Я тебя породил, я тебя и убью!

Я тебя породил, я тебя и убью!
Н. Гоголь "Тарас Бульба".
Старые ошибки или почему иногда, большое удобство плохо.

Если человеку дают очень удобное и красивое средство он теряет нюх и начинает ошибаться, конечно, потом он находит свои ошибки, и не считает, что все что блестит золото , но все таки. Как пример можно привести мелкие ошибки в решении которых я когдато участвовал (примеры относяться к .Net).

Как известно эта платформа обладает очень хорошим свойством как сборщик мусора, вот понимание его работы и вызвало ошибку: когда теряется ссылка на объект через некоторое время этот объект будет удален, но бывают некоторые особенности. Иногда остаются скрытые ссылки на этот объект, и как следствие он остается на вечно и скрытно жрет ресурсы: например окошко с созданным в нем таймером по которому в этот окошке , что то изменяется, вызывает такую особенность: система обрабатывает это окошко по особенному. В системе есть команда: 'выполнять по таймеру событие' и вся эта система, когда вы думаете уже мертва, начинает жить по собственным правилам, и не давать сборщику мусора удалить себя, так как есть круговая зависимость окошко->таймер->система и через некоторое время все ресурсы съедены и система уже не может создавать новые компоненты. Но и умереть она не может, так как не понятно, что происходит и нужно сообщить разработчикам или умереть, одно выполнить не можем, а другое не красиво, а решение простое: когда вам что то уже не нужно разрывайте и останавливаете связи сами, а не ждите, пока это сделает система, так хоть немного дольше проживете(в смысле программы).

Я тебя породил я тебя и убью... всегда сохраняйте взаимосвязь внутри приложения родитель -> потомок. Так как поток созданный в программе обладающей выше указанным багом некогда не умрет при исключении в основном потоке и программа постепенно 'захватит мир или моск'. В данном случае поток выполняющийся в программе был создан, как отдельный процесс не связанный с основным, в деструкторе основного потока он не уничтожался и потихоньку держал ресурсы всей программы. Решение было простое создавать не новый поток, а вызывать асинхронно делегат, который заменил этот поток.

И будьте внимательны к мелочам, лучше самому все уничтожить в деструкторе и не делать асинхронно, то что можно сделать проще и синхронно, чем надеяться на ум среды разработки - она только помощь, а не решение.

Wednesday, May 6, 2009

Маленькие выводы по кэшированию

Или временное завершение этой темы...
  • Проверить качество кэширования можно используя эту ссылку, на этом сайте также даются рекомендации по сжатию контента и приводятся данные относительно времени загрузки через различные каналы;
  • статья относительно указания параметров кэширования на примере использования Apache, даются достаточно универсальные методы указания параметров кэширования;
  • эталонное описание как должно работать кэширование rfc2616;
  • идеи относительно времени кэширования, построения гибкой версии указания этого времени и перенаправления во время обработки для увеличения степени валидности кэша;
  • и как заключение пример архитектуры.