2015-12-04 2 views
1

Я использую Mojolicious WebSocket для установления протокола обмена сообщениями между сервером и клиентом.Как отправить события WebSocket из операции блокировки? (Требуется консультация по дизайну)

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

В нескольких точках на стороне сервера код, который я называю $web_socket->send(...) и обработать его на стороне клиента ws.onmessage = function (event) {...};

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

Серверный логика:

some_computation1(); 
$web_socket->send('computation1 end'); 
... 
some_computation15(); 
$web_socket->send('computation15 end'); 
... 
some_computation100(); 
$web_socket->send('computation100 end. All ok!'); 

стороне клиента:

ws = new WebSocket(url); 
ws.onmessage = function (event) { 
    $('#log_view').append('<p>' + event.data + '</p>'); 
}; 
ws.onopen = function (event) { 
    ... 
}; 
ws.onclose = function (event) { 
    ... 
}; 
+3

Является ли ваша «длительная работа» блокирующей сервер iloop? Это, несомненно, вызовет наблюдаемое поведение. Я не могу комментировать дальше, не видя больше кода. –

+0

@Joel Berger, существует примерно 3k строк кода серверной логики и очень похоже на краткий пример выше. Да, эта операция блокирует ioloop. Я не нашел способ «обрабатывать события» (например, в Qt). Я пробовал использовать Mojo :: IOLoop таймер и потоки для отправки сообщений в websocket, но не повезло. – alexandrmoroz

+1

Рассмотрите возможность переноса длинного вычисления в отдельный поток или (еще лучше), чтобы разбить его на ряд задач и обратных вызовов, позволяя собственному обработчику реактора/события управлять параллелизмом и отправлять/получать данные ввода-вывода. – Myst

ответ

0

Я нашел, что это работает для меня: Mojo :: IOLoop-> one_tick;

some_computation1(); 
$web_socket->send('computation1 end'); 
Mojo::IOLoop->one_tick; 

UPD: или может быть это будет лучше, чтобы отделить длительную работу в фоновом потоке («вилку» или «задержки»).

+2

Это будет работать до тех пор, пока ваши работники гипнозагрузки не начнут умирать из-за отсутствия сердечного приступа –

+0

@JoelBerger, спасибо за ваше предупреждение, но это не решает эту проблему :) Как насчет других веб-серверов с поддержкой веб-карт? То же самое плохое? Где я могу найти дополнительную информацию о том, как все это работает под капотом? (IOLoop + WebSocket + Webserver (hypnotoad, daemon, mod_perl ...) – alexandrmoroz

3

There is два примера, как сделать это с помощью одного из двух модулей:

  1. Mojo::IOLoop::ReadWriteFork
  2. Mojo::IOLoop::ForkCall

Чтобы запустить его выполнить команду:
perl perl_ws_long_blocking_operation.pl daemon

U pd,. Если у вас есть много операций долго блокировки вы должны использовать Mojo::IOLoop::Delay:

Example of many long blocking operation

Чтобы запустить его выполнить команду:

morbo perl_ws_many_long_blocking_operations.pl 
+0

Спасибо за решение. Я попробовал ForkCall. Я хочу отправить сообщение websocket в «background» и большой логике - в основном потоке, а не наоборот. Я попытался отправить сообщение websocket в ForkCall (ws setup все еще в основном потоке), но он вообще не отправляет. – alexandrmoroz

+0

Я не понимаю, почему это не работает для вас. Я обновляю ответ для объединения Mojo :: IOLoop :: Delay with Mojo :: IOLoop :: ForkCall. – Logioniz

+0

ок, я попробую. Я принимаю ваш ответ. Если это решение будет лучше моего. – alexandrmoroz

Смежные вопросы