общение между обработчиком http и обработчиком websocket в Cowboy

Я хотел бы создать веб-приложение в Cowboy, которое получает данные от другого обработчика Cowboy. Допустим, я хочу объединить пример Echo_get из cowboy: https://github.com/ninenines/cowboy/tree/master/examples/echo_get/src

с примером веб-сокета

https://github.com/ninenines/cowboy/tree/master/examples/websocket/src

таким образом, что запрос GET к Echo должен отправить «push» через обработчик websocket на html-страницу в этом примере.

Каков наименее сложный способ сделать это? Могу ли я использовать оператор «pipe» простым способом? Нужно ли мне создавать и промежуточные gen_something для передачи сообщений между ними? Я был бы признателен за ответ с примером кода, показывающим связующий код для обработчиков - я действительно не знаю, с чего начать соединение двух обработчиков вместе.


person voltaire    schedule 30.12.2014    source источник


Ответы (1)


Обработчик websocket в cowboy — это долгоживущий процесс запроса, которому вы можете отправлять сообщения websocket или erlang.

В вашем случае есть 2 типа процессов:

  • процессы веб-сокетов: обработчики веб-сокетов с открытым для клиентов соединением с веб-сокетом.
  • эхо-процессы: процессы, когда клиент обращается к обработчику эха с параметром.

Идея состоит в том, что эхо-процесс отправляет сообщение erlang процессам веб-сокета, которые, в свою очередь, отправляют сообщение клиенту.

Чтобы ваш эхо-процесс мог отправлять сообщения вашим процессам веб-сокетов, вам необходимо сохранить список процессов веб-сокетов, которым вы хотите отправлять сообщения. Gproc — весьма полезная библиотека для этой цели.

Вы можете регистрировать процессы в gproc pubsub с помощью gproc_ps:subscribe/2 и отправлять сообщения к зарегистрированным процессам с gproc_ps:publish/3.

Процессы websocket Cowboy получают сообщения erlang с помощью websocket_info/3функция.

Так, например, обработчик веб-сокета может быть таким:

websocket_init(_, Req, _Opts) ->
  ...
  % l is for local process registration
  % echo is the name of the event you register the process to
  gproc_ps:subscribe(l, echo),
  ...

websocket_info({gproc_ps_event, echo, Echo}, Req, State) ->
  % sending the Echo to the client
  {reply, {text, Echo}, Req, State};

И обработчик эха такой:

echo(<<"GET">>, Echo, Req) ->
    % sending the echo message to the websockets handlers
    gproc_ps:publish(l, echo, Echo),
    cowboy_req:reply(200, [
        {<<"content-type">>, <<"text/plain; charset=utf-8">>}
    ], Echo, Req);
person Eric    schedule 31.12.2014
comment
Только что протестировано, и это работает! Большое спасибо! Знаете ли вы, есть ли у этого метода какие-либо существенные недостатки производительности или масштабируемости (например, если pub и sub находятся на разных машинах и т. д.) по сравнению с другими методами, доступными в erlang? Будет ли размещение моего собственного gen_server для oub/sub между обработчиками эха и веб-сокета более эффективным/масштабируемым, чем gproc? Я пытаюсь понять, могу ли я придерживаться gproc для чего-то большего, чем домашний проект (со значительной связью по линии публикации/подписки (высокая скорость публикации/подписки и количество узлов). - person voltaire; 01.01.2015