Клиент SOAP::LITE в Catalyst заставляет ВСЕ мое приложение Catalyst ждать во время доступа или тайм-аута
В моем приложении Catalyst у меня есть очень важное соединение с удаленным сервером, использующим SOAP с WSDL.
Все работает нормально, но когда удаленный сервер отключается по любой причине, ВСЕ мое приложение ждет, пока не истечет время ожидания. ВСЕ. ВСЕ контроллеры и процессы, ВСЕ клиенты!!
Если я установлю тайм-аут на 15 секунд для ошибки транспорта SOAP LITE, все будет ждать 15 секунд. Любая страница от любого пользователя или соединения не может быть отображена во время ожидания.
Я использую Fast CGI и Ngnix для приложения Catalyst. Если я использую несколько процессов fcgi, когда один ожидает, другие позаботятся о соединениях, но если все они попытаются получить доступ к неисправной службе SOAP... они все ждут и ждут ответа, пока не достигнут своих тайм-аутов. Когда все они ждут, больше никаких соединений не разрешено.
В поисках ответов я где-то читал, что SOAP::LITE является "однопоточным".
Это правда? Означает ли это, что ВСЕ мое приложение со ВСЕМИ посетителями может использовать только одно SOAP-соединение? В это трудно поверить.
Это мой код для звонка:
sub check_result {
my ($self, $code, $IP, $PORT) = @_;
my $soap = SOAP::Lite->new( proxy => "http://$IP:$PORT/REMOTE_SOAP
+");
$soap->autotype(0);
$soap->default_ns('http://REMOTENAMESPACE/namespace/default');
$soap->transport->timeout(15);
$soap-> on_fault(sub { my($soap, $res) = @_;
eval { die ref $res ? $res->faultstring : $soap->transport->st
+atus };
return ref $res ? $res : new SOAP::SOM;
});
my $som = $soap->call("remote_function",
SOAP::Data->name( 'Entry1' )->value( $code ),
);
return $som->paramsout;
}
Я также попробовал этот немного другой подход, любезно предложенный в perlmonks, но ничто не улучшилось
Пожалуйста, кто-то может указать мне в правильном направлении?
Migue
1 ответ
Это не проблема с SOAP::Lite или Catalyst как таковыми. Практически любой ресурс, который вы запрашиваете, скорее всего будет ожидать возврата (т. Е. Чтение файла на диске, доступ к базе данных). Если ресурс блокируется в течение длительного времени, есть вероятность, что вы могли бы "голодать" другие запросы, ожидая этого возврата.
Нет простого ответа на эту проблему, но вы можете создать "очередь заданий", которую выполняет отдельный процесс, затем вместо вызова другой службы вы добавите запись в очередь и получите токен. Когда запрос завершен, очередь сохраняет результат, связанный с этим токеном, а затем ваше приложение в отдельном запросе проверяет, есть ли у токена, который вы хотите, уже есть результат или нет.
Существуют специализированные структуры "очереди заданий", такие как RabbitMQ, ApacheMQ и даже некоторые решения поверх Redis. Если ваше веб-приложение использует богатый Javascript, вы даже можете получить уведомление о "очереди заданий" до клиента javascript, используя, например, WebSockets, но в противном случае просто опрашивайте каждую секунду, чтобы узнать, есть ответ или нет.