Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> lwp завершить соединение по таймауту 
:(
    Опции темы
burakov
Дата 11.12.2013, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



Добрый день.

необходимо прервать соединение LWP по таймауту.

родной 
$lwp -> timeout ($timeout);

это для того, чтобы не останавливаться, когда ждешь ответа сервера ..

но бывают ситуации, когда ответ есть, но очень медленный.
такие ответы нужно прерывать по таймауту
есть ли в LWP такая опция?

попробовал использовать в своем многопоточном грабере 

конструкцию вида

            my $response = undef;
            eval {
                local $SIG{ALRM} = sub { die "timeout"; };
                alarm ($timeout);
                UNSAFE_SIGNALS {                
                    $response = $lwp -> request ($req);
                };
                if (defined $response -> code) {
                    print $response -> code ."\t". scalar (@threads). "\t" .$url. "\n";
                } 
                alarm (0);
            };


но в виндоус она не работает.
в линукс работает, но 
eval обрывает все потоки и останавливает грабер
вообщем вообще работает некорректно
многопоточная работа основана на 

use threads;
use threads::shared;
use Thread::Queue;


подскажите как быть 
кто где и как (многопоточно) реализовывал  обрыв соединения по таймауту??

большое спасибо




--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Bulat
Дата 11.12.2013, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: нет
Всего: 57



Цитата(burakov @  11.12.2013,  14:40 Найти цитируемый пост)
но бывают ситуации, когда ответ есть, но очень медленный.

эээ... имеешь ввиду узкий канал??


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
burakov
Дата 11.12.2013, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



совершенно верно. 
бывает канал сам по себе узкий. а бывает его преднамеренно сужают... smile.
но мне нужно просто оборвать в таком случае выполнение запроса и продолжить дальше.


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Bulat
Дата 11.12.2013, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: нет
Всего: 57



Цитата(burakov @  11.12.2013,  14:40 Найти цитируемый пост)
многопоточная работа основана на 

use threads;
use threads::shared;
use Thread::Queue;


а ежели через fork попробовать?


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
burakov
Дата 11.12.2013, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



ну можно попробовать через fork, 
можно через wget на крайний случай.

хотелось волшебное решение через LWP, чтобы двиг не переписывать. (тем более все должно и на винде работать, а форки в винде по моему еще хуже чем threads)


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Bulat
Дата 11.12.2013, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: нет
Всего: 57



burakov, ну выложи более подробный код, а то по кускам все ж не до конца понятно, где и что можно изменить.

Цитата(burakov @  11.12.2013,  15:53 Найти цитируемый пост)
хотелось волшебное решение через LWP


Цитата(burakov @  11.12.2013,  14:40 Найти цитируемый пост)
родной 
$lwp -> timeout ($timeout);


Добавлено через 40 секунд
Цитата(burakov @  11.12.2013,  15:53 Найти цитируемый пост)
тем более все должно и на винде работать, а форки в винде по моему еще хуже чем threads

для граббера сойдет


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
krypt3r
Дата 12.12.2013, 06:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 359
Регистрация: 9.6.2009

Репутация: нет
Всего: 16



Может поможет
Код

# Create thread with a task that may time out
my $thr->create(sub {
    threads->yield();
    eval {
        $SIG{ALRM} = sub { die("Timeout\n"); };
        alarm(10);
        ... # Do work here
        alarm(0);
    };
    if ($@ =~ /Timeout/) {
        warn("Task in thread timed out\n");
    }
};
# Set signal handler to relay SIGALRM to thread
$SIG{ALRM} = sub { $thr->kill('ALRM') };
... # Main thread continues working

PM MAIL   Вверх
vadiml
Дата 12.12.2013, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 310
Регистрация: 27.7.2007

Репутация: нет
Всего: 7



Если у Вас коннект по https, то в LWP есть с timeout-ом баг
http://stackoverflow.com/questions/9400068...useragent-https

Т.е. надо писать timeout => 5, Timeout => 5



PM MAIL Jabber   Вверх
Pfailed
Дата 12.12.2013, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



Цитата(vadiml @  12.12.2013,  14:52 Найти цитируемый пост)
Если у Вас коннект по https, то в LWP есть с timeout-ом баг

Его же пофиксили давно, там даже написано.

А что касается LWP, то вся соль здесь https://metacpan.org/source/GAAS/libwww-per...ol/http.pm#L128
Соответственно для реализациии dead line таймаута потребуется либо реализовать свой имплементор для http и https схемы, унаследовавшись от LWP::Protocol::http и LWP::Protoco::https сответственно и переопределив метод request. Либо переопределить LWP::Protocol::http::request напрямую monkey патчингом.


--------------------
PM MAIL   Вверх
ginnie
Дата 12.12.2013, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 4
Всего: 49



В обсуждении на stackoverflow.com посоветовали LWPx::ParanoidAgent, в нем реализован общий timeout().


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
Pfailed
Дата 12.12.2013, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



ginnie, он там реализован как раз с помощью SIGALRM

Я тут придумал как это можно сделать дёшево и сердито. Делаем tied handle, который при каждом read/write проверяет а не наступил ли таймаут (прошло больше времени, чем задано). Если прошло возвращает ошибку. Далее нужно связать с этим умным handl'ом сокет, который создаёт LWP. Это можно легко сделать подменив IO::Socket::INET::new на наш со связыванием (локализовав эту подмену внутри функции, где LWP создаёт сокет).
Далее тестовый скрипт, показавший, что это более менее работает. При установленном таймауте 3 секунды проходит 4. А на простом LWP все 10 (собственно столько создаваемый сервер и отдаёт контент). На винде тоже работает.

Код

use strict;

package Tie::Handle::WithTimeout;

use Errno;
use IO::Handle;
use parent 'Tie::Handle';

sub TIEHANDLE {
    my ($class, %opts) = @_;
    
    $opts{start} = time();
    $opts{fh} = IO::Handle->new_from_fd($opts{fh}, '+<');
    bless \%opts, $class;
}

sub READ {
    my $self = shift;
    
    if (time() - $self->{start} > $self->{timeout}) {
        $! = Errno::ETIMEDOUT;
        return undef;
    }
    
    sysread($self->{fh}, $_[0], $_[1], $_[2]);
}

sub WRITE {
    my $self = shift;
    
    if (time() - $self->{start} > $self->{timeout}) {
        $! = Errno::ETIMEDOUT;
        return undef;
    }
    
    syswrite($self->{fh}, $_[0], $_[1], $_[2]);
}

sub FILENO {
    fileno $_[0]->{fh};
}

package main;

use LWP::UserAgent;
use LWP::Protocol::http;

use constant TIMEOUT => 3;

my $lwp_protocol_http_new_socket = \&LWP::Protocol::http::_new_socket;
my $io_socket_inet_new = \&IO::Socket::INET::new;

*LWP::Protocol::http::_new_socket = sub {
    local *IO::Socket::INET::new = sub {
        my $sock = $io_socket_inet_new->(@_);
        if ($sock) {
            tie *$sock, Tie::Handle::WithTimeout::, fh => $sock, timeout => TIMEOUT;
        }
        
        return $sock;
    };
    
    $lwp_protocol_http_new_socket->(@_);
};

# test it

my ($server, $host, $port) = make_slow_http_server();
my $start = time;

my $ua = LWP::UserAgent->new(timeout => TIMEOUT);
print $ua->get("http://$host:$port/")->as_string();

my $elapsed = time - $start;
warn "TOTAL ELAPSED: ", $elapsed;

$server->kill(15);

sub make_slow_http_server {
    use threads;
    
    my $serv = IO::Socket::INET->new(Listen => 3)
        or die $@;
    
    my $thread = threads->create(sub {
        $SIG{TERM} = sub { threads->exit() };
        
        while (1) {
            my $client = $serv->accept()
                or next;
            
            my $buf;
            while (1) {
                $client->sysread($buf, 1024, length $buf)
                    or last;
                if (rindex($buf, "\015\012\015\012") != -1) {
                    last;
                }
            }
            
            $client->syswrite(
                join(
                    "\015\012",
                    "HTTP/1.1 200 OK",
                    "Connection: close",
                    "Content-Type: text/html",
                    "\015\012"
                )
            );
            
            for (1..10) {
                $client->syswrite(rand);
                sleep 1;
            }
            
            $client->close();
        }
        
    });
    $thread->detach();
    
    return ($thread, $serv->sockhost eq "0.0.0.0" ? "127.0.0.1" : $serv->sockhost, $serv->sockport);
}


Добавлено через 3 минуты и 41 секунду
ginnie, прошу прощенья. Перепутал с LWP::UserAgent::Paranoid


--------------------
PM MAIL   Вверх
Pfailed
Дата 12.12.2013, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 2
Всего: 39



Да, на моём тесте LWPx::ParanoidAgent выдал ровно 3 отведённые ему секунды. Можно рекомендовать к использованию.


--------------------
PM MAIL   Вверх
burakov
Дата 17.12.2013, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



посоветовали еще WGET

--connect-timeout=СЕК     установка тайм-аута подключения в СЕК.
 --read-timeout=СЕК        установка тайм-аута чтения в СЕК.



попробовал

Код

my $system = $wget .
'  --no-verbose --server-response --quota="1000000"'.
' --connect-timeout="'.$read_inifile -> {connect_timeout}.'"'.
' --read-timeout="'.$read_inifile -> {read_timeout}.'"'.
' --user-agent="'.$useragent.'"'.
' --output-document="'. $file .'" '.
$url;



но коннект не обрывает. а это вроде все таймауты, которые у него есть. просто по идее грабер должен кроссплатформенно виндоус, линукс работать..
а под виндоусом alarm не особо на многопотоке.

как то можно оборвать по таймауту wget соединение?


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Bulat
Дата 17.12.2013, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


татарский Нео
***


Профиль
Группа: Завсегдатай
Сообщений: 1701
Регистрация: 22.3.2006
Где: Альметьевск

Репутация: нет
Всего: 57



Цитата(burakov @  17.12.2013,  16:45 Найти цитируемый пост)
как то можно оборвать по таймауту wget соединение? 

ну там еще и dns-timeout был(что-то вроде этого), хотя это наверно зависит еще и от самой оси, у меня на убунту по крайней мере что-то такое есть. В других не знаю.

Но на тему wget тогда у меня вопрос - разве его винда поддерживает?


--------------------
менеджер по кодеврайтингу  smile 
PM MAIL WWW   Вверх
burakov
Дата 17.12.2013, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 554
Регистрация: 28.7.2006

Репутация: нет
Всего: нет



ну есть сборка win32, а как же.
но че то не работает обрыв (по крайней мере видно это не те таймауты)
пришлось даже админа знакомого упросить смоделировать на линуксе ситуацию на моем ай пи.
wget не обрывает, хотя было бы удобно его как клиента получающего контент использовать


--------------------
Нотный архив http://libnote.ru скачать ноты бесплатно
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.1017 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.