Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > memcached + win7


Автор: infarch 21.1.2014, 14:31
Здравствуйте.

Пытаюсь запустить и использовать memcached под виндовс 7. Сам сервис запустил: 

D:\memcached-amd64>memcached.exe -l localhost -p 12345 -v

Процесс висит в памяти, могу доступиться через телнет. Теперь пробую использовать:

Код

use strict;
use warnings;

use Cache::Memcached;

my $memd = new Cache::Memcached {
  'servers' => [ "localhost:12345" ],
  'debug' => 1,
  'compress_threshold' => 10_000,
};

if( $memd->set("my_key", "Some value") ){
    my $val = $memd->get("my_key");
    print $val;
}


Однако set не работает, возвращает 0. Я полез в сам Cache::Memcached, дошел до вот этой строки:
Код

my $ret = connect($sock, $sin);


На ней все останавливается и в $! я нахожу сообщение "Unknown error". Сам я абсолютно не знаком с использованием сокетов, мне это ни о чем не говорит. Может подскажете в чем может быть проблема?

пс. файрволл отключен

Автор: infarch 21.1.2014, 16:06
UPD. Запустил memcached с ключом -vv. В момент конекта вижу в консоли:

<644 new auto-negotiating client connection
<644 connection closed.

Пациент значит не совсем мертв... Но причина по прежнему не понятна.

Автор: tzirechnoy 21.1.2014, 18:06
1) УМВР. Debian/stable, ровно этот код и строка запуска memcached.
2) Попробуйте 127.0.0.1 вместо localhost и/или проверьте, что возвращает Socket::inet_aton($ip) в $sin = Socket::sockaddr_in...
3) $! можно напечатать в числовом контексте (хотя, вообще говоря, в перле такого нет) -- например, printf "%d", $!. Кроме $! есть ещё $^E. Хотя, конечно, WSA такая вещь, что всего можно ждать...
4) Попробуйте поставить timeout в 0. non-blocking sockets можэт иметь ограничения портируемости.

Автор: infarch 21.1.2014, 19:12
Пробовал использовать айпи вместо локалхост, результата нет. Таймаут в ноль тоже не помог. Да и как его поставить... Вот кусок конструктора:
Код

    # TODO: undocumented
    $self->{'connect_timeout'} = $args->{'connect_timeout'} || 0.25;
    $self->{'select_timeout'}  = $args->{'select_timeout'}  || 1.0;

Ставим ноль, получаем дефолт. Ну я его руками подправил, для восприятия нулей. И не помогло.

Вывел $sin на печать, получил забавные смайлики: sin=☻ 09⌂  ☺.
А вот $^E несколько улучшил читаемость: "A non-blocking socket operation could not be completed immediately". После этого я еще раз пересмотрел код и пришел вот к этому: IO::Handle::blocking($sock, 1). переписал на IO::Handle::blocking($sock, 1) or die $!; и получил "Inappropriate I/O control operation". Что бы это значило?..

Автор: Bulat 22.1.2014, 07:59
infarch, а могешь поискать как определяются переменные $sock и $sin. 

Мож там пафос в криво выставленных флагах. Если найдешь вызов функции socket - тож в студию ! И плюс, ежели вдруг будет вызов функции setsockopt - тоже интересно посмотреть

Добавлено через 4 минуты и 49 секунд
Цитата(infarch @  21.1.2014,  19:12 Найти цитируемый пост)
Вывел $sin на печать, получил забавные смайлики: sin=☻ 09⌂  ☺.


он у тебя в бинарном виде

Автор: infarch 22.1.2014, 11:52
Конечно, могу. Вот в сокращенной форме то что происходит:

Код

my $sock;
my $sin;
my $proto = $PROTO_TCP ||= getprotobyname('tcp');
socket($sock, PF_INET, SOCK_STREAM, $proto);
$sin = Socket::sockaddr_in($port, Socket::inet_aton($ip));

Автор: tzirechnoy 22.1.2014, 12:09
ActivePerl 5.16 for win32, memcached 1.4.5 64-бит от northscale: В sub _connect_sock {
заменить 
Код
    if (!$ret && $timeout && $!==EINPROGRESS) {
на
[code]    if (!$ret && $timeout && ( ($!==EINPROGRESS) || ($!==EWOULDBLOCK)) ) {


Работать будет видимо только с неблокирующими сокетами (timeout > 0)

Автор: infarch 22.1.2014, 12:20
tzirechnoy, ваш рецепт сработал! Огромное спасибо!

Автор: Bulat 22.1.2014, 12:27
Цитата(infarch @  22.1.2014,  11:52 Найти цитируемый пост)
Конечно, могу. Вот в сокращенной форме то что происходит:

здесь вроде бы все кошерно.

Посему можешь попробовать совет tzirechnoy

Или эту строку подхачить

Код

IO::Handle::blocking($sock, 1)


на

Код

IO::Handle::blocking($sock, 0)


Если не поможет - попробуем ковырятся дальше!

Автор: tzirechnoy 22.1.2014, 13:33
Цитата
на Код IO::Handle::blocking($sock, 0)


Он ужэ сказал -- что это просто неработает. Точнее, неработает конкретно blocking($sock, 1) -- но во-первых blocking($sock, 0) -- не выглядит осмысленным, поскольку ошыбки и так явно идут от неблокирующихся хэгдлов, во-вторых почти наверняка если код для установки blocking неправильный/не от того API -- то и для снятия будет такжэ.

Впрочем, мне до сих пор непонятно, как он всё-таки получился non-blocking. Возможно, это поведение по умолчанию в WSA.

В-третьих -- это WSA, что вы хотели. Ад, заборы, коровники. Проще всего -- отправить однострочный патч автору и забить. Можно попытаться представить, что IO::Socket::INET более используемый, потому там большэ шансов, что заработает сразу, и потому переписать на IO::Socket::INET -- но как бы видно, что надо переписывать и отлажывать десяток-другой строк -- и непонятно в чём будет выигрыш дажэ если что-то получится.

Автор: Bulat 22.1.2014, 14:24
tzirechnoy, много эмоций, а по сути - практически ничего. Это во-первых.

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

В-третьих, то, что не работает вызов blocking($sock, 1), вовсе не означает, что вызов blocking($sock, 0) - тоже не будет работать! Почему - читай дальше.

В четвертых, учитывая, что это windows - лично я не знаю, какие константы из fcntl, socket и прочих функций в ней реализованы кошерно, а какие нет.

В пятых, и конечных, я могу найти не одно верное решение данной проблемы, когда будет понятно в чем суть, но каждый выбирает сам, какое ему любо. Однако от выбора одного решения из множества, вовсе не означает, что другие способы решения - бесмысленны!

В шестых, на этом, я надеюсь флуд будет закончет!

Автор: tzirechnoy 22.1.2014, 15:02
Цитата
tzirechnoy, много эмоций, а по сути - практически ничего.


Верно подмечено. Я не модэратор, но по мне так -- обращайтесь, когда потребуется ещё раз выплеснуть.

Автор: infarch 22.1.2014, 16:06
Друзья, не ссорьтесь ) Проблема решена для меня и это главное. Тут такая ситуация - на девелоперской машине я модуль мемкешед и попатчить могу, не критично. А в продакшене это будет линукс сервер и я думаю там то проблем не будет.
Вот кстати вопрос еще: я в примере к модулю видел что в конструкторе определяется несколько серверов. Что это дает? Можно ли мемкешед инстансы организовать в устойчивый кластер?

Автор: tzirechnoy 22.1.2014, 17:14
Цитата
Что это дает?


Распределение нагрузки. Ключ хэшыруется, и на основании хеша определяется, на какой сервер его отправлять.

Цитата
Можно ли мемкешед инстансы организовать в устойчивый кластер?


memcached и устойчивость -- какое-то странное сочетание. Как минимум -- зачем вам устойчивый кластер из memcached, всё равно жэ его значения периодически выкидываются?

Автор: infarch 22.1.2014, 17:34
Насколько я понимаю, выкидываются если настроить таймаут, иначе хранятся до последнего. Или не так? Я вообще предполагал там хранить объекты которые часто читаются из базы, но редко изменяются. Еще хранить сесии. Причем сесии будут только там, в базу данных не пойдут. И вот возникает сомнение... Если один сервер упадет или станет недоступен то получается что куча юзеров окажутся разлогинеными. Это мне не нравится.

Автор: tzirechnoy 22.1.2014, 17:41
Цитата
иначе хранятся до последнего. Или не так?


Или если память закончится. Или если демон перезагрузят.

Цитата
И вот возникает сомнение...


Не должно быть тут никаких сомнений: это -- кэш. Для ускорения. Никаких основных копий там хранить нельзя.

Автор: infarch 22.1.2014, 18:36
Да, правда ваша... Ну значит буду думать об его использовании чисто как кеша. Спасибо всем за участие, закрываю тему.

Автор: Grost 31.1.2014, 10:07
Значения в мемкеше удаляются если закончилось время жизни или заканчивается память, т.е. для записи нового элемента будет удалён старый. Так же, если вдруг сервер упадёт, то мемкеш будет чист. 
Для важных записей можно использовать Redis который время от времени пишит свои данные на диск, что помогает ему восстановить данные после падении.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)