Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 10.04.2020, 22:16
Новичок на форуме
Отправить личное сообщение для NatalliaF Посмотреть профиль Найти все сообщения от NatalliaF
 
Регистрация: 10.04.2020
Сообщений: 4

WebSockets - большой поток данных
Клиент и сервер общаются посредством WebSockets. Сервер передает клиенту непрерывно сообщения. Клиент их получает в onmessage. Стандартно. Но! Сообщений о-очень много. Очередное сообщение может быть передано сервером, когда клиент еще не закончил обрабатывать предыдущее. Может, спрошу очевидную вещь. Но вопрос мой такой. Когда в процессе обработки полученного в onmessage сообщения приходит еще одно сообщение, то создается новый поток и код в onmessage для нового сообщения выполняется в этом новом потоке или все происходит последовательно (пока предыдущее сообщение не обработается, новое обрабатываться не будет)?
Ответить с цитированием
  #2 (permalink)  
Старый 10.04.2020, 23:32
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Конечно последовательно. javascript в принципе не предназначен для параллельной работы. Ведь функции, которые вызываются по onmessage, разделяют (им доступны) все переменные и объекты. Их параллельное изменение может нарушить и механизмы оптимизации и сборку мусора.
Только worker может работать параллельно в другом потоке, но он полностью изолирован, использует другую область видимости.
Ответить с цитированием
  #3 (permalink)  
Старый 11.04.2020, 08:52
Новичок на форуме
Отправить личное сообщение для NatalliaF Посмотреть профиль Найти все сообщения от NatalliaF
 
Регистрация: 10.04.2020
Сообщений: 4

Т.е. в onmessage при получении очередного сообщения я его просто обрабатываю и уверена, что пока не закончу обработку, сервер больше ничего не отправит. А если хочу обрабатывать быстро и параллельно, то, получая сообщение в onmessage, каким-то образом должна создать что-то типа отдельного потока, передать ему сообщение и быстро выйти из onmessage, чтобы сервер продолжил передавать данные.
Веб-воркеры - потоки, принадлежащие браузеру. А у меня клиент не браузерный. Выходит, надо искать что-то другое.
Ответить с цитированием
  #4 (permalink)  
Старый 11.04.2020, 10:52
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Сообщение от NatalliaF Посмотреть сообщение
Т.е. в onmessage при получении очередного сообщения я его просто обрабатываю и уверена, что пока не закончу обработку, сервер больше ничего не отправит. А если хочу обрабатывать быстро и параллельно, то, получая сообщение в onmessage, каким-то образом должна создать что-то типа отдельного потока, передать ему сообщение и быстро выйти из onmessage, чтобы сервер продолжил передавать данные.
Веб-воркеры - потоки, принадлежащие браузеру. А у меня клиент не браузерный. Выходит, надо искать что-то другое.
Нет. Такой уверенности быть не должно. Сервер может отправлять данные когда ему вздумается. Данные будут буферизироваться и обрабатываться клиентом по мере готовности.
Чтобы обеспечить параллельную обработку (в другом потоке) нужен Worker, они есть не только в браузерах. В Node тоже есть.
Ответить с цитированием
  #5 (permalink)  
Старый 12.04.2020, 13:02
Аватар для SuperZen
Профессор
Отправить личное сообщение для SuperZen Посмотреть профиль Найти все сообщения от SuperZen
 
Регистрация: 08.11.2017
Сообщений: 642

package.json
{
  "name": "ws-seq-para",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "ws": "^7.2.3"
  }
}


server.js
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 2999 })
wss.on('connection', function connection(ws) {
  ws.send(JSON.stringify({ type: 'long' }))
  setTimeout(() => {
    ws.send(JSON.stringify({ type: 'short' }))
  }, 1000)
})


client.js
const WebSocket = require('ws')
const ws = new WebSocket('ws://localhost:2999')
ws.on('message', function incoming(json) {
  const { type } = JSON.parse(json)
  switch (type) {
    case 'long':
      console.log('long start')
      setTimeout(console.log, 2000, 'long stop')
      break
    case 'short':
      console.log('short running')
      break
    default:
      break
  }
})


вывод консоли:
long start
short running
long stop

резюме: нужен queue... воркер не решает эту проблему...
Ответить с цитированием
  #6 (permalink)  
Старый 12.04.2020, 14:20
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Сообщение от SuperZen Посмотреть сообщение

резюме: нужен queue... воркер не решает эту проблему...
Если сообщения требуется обрабатывать именно в порядке их поступления, но поступают они чаще, чем их возможно обработать, то и queue не решит эту проблему.
А если их можно обрабатывать независимо, то можно и несколько воркеров запустить и передавать тому, который освободился.
Ответить с цитированием
  #7 (permalink)  
Старый 12.04.2020, 15:40
Аватар для SuperZen
Профессор
Отправить личное сообщение для SuperZen Посмотреть профиль Найти все сообщения от SuperZen
 
Регистрация: 08.11.2017
Сообщений: 642

Сообщение от voraa
Если сообщения требуется обрабатывать именно в порядке их поступления, но поступают они чаще, чем их возможно обработать, то и queue не решит эту проблему.
сообщения поступают, и их надо обрабатывать именно в порядке поступления, то нужен queue

Сообщение от voraa
А если их можно обрабатывать независимо, то можно и несколько воркеров запустить и передавать тому, который освободился.
это да
Ответить с цитированием
  #8 (permalink)  
Старый 12.04.2020, 23:11
Новичок на форуме
Отправить личное сообщение для NatalliaF Посмотреть профиль Найти все сообщения от NatalliaF
 
Регистрация: 10.04.2020
Сообщений: 4

Спасибо, ребята, за информацию и идеи.

Выше упоминалось, что если сервер посылает сообщения быстрее, чем они обрабатываются, то на клиенте сообщения буферизуются. Отсюда возник еще один вопрос. Если клиента надо отключить (он прекратит принимать сообщения от сервера), как при этом извлечь из буфера имеющиеся сообщения с целью их обработки (информацию терять нельзя)?

Последний раз редактировалось NatalliaF, 13.04.2020 в 08:08.
Ответить с цитированием
  #9 (permalink)  
Старый 13.04.2020, 09:17
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,745

Очень абстрактный вопрос.
Получение сообщения начинается с сетевой карты и ее драйвера. Потом это сообщение передается ОС, потом ОС передает его клиенту (браузеру, еще чему то...) Потом браузер передает его программе на javascrit в виде события message. И если отключить клиента до этого момента (как? снять задачу? выключить компьютер?) то с этим сообщением мы ничего сделать не сможем. Оно в любом случае потеряется.
А вот с теми, которые пришли в качестве событий message уже можно разбираться.
Как мне представляется у события есть следующие фазы:
Прием (вызывается функция, указанная в onmessage)
Обработка (Какая то длительная операция)
Использование результата обработки (Сравнительно короткая операция)

Ну, например, мы принимаем какие то массивы
Обработка - это сортировка массива
Использование - вывод массива на экран.

Можно написать функцию
onmessage = function (ev) {
sort(0)
output ()
}
Если, скажем sort - занимает 1 сек, а сообщения приходят каждые 300 мс, то у нас выстроится очередь из необработанных событий. Т.к функция обработки события выполняется в основном потоке, и обрабатывать следующее событие мы можем только после того, как закончится обработка текущего.
Допустим сообщения могут обрабатываться независимо друг от друга.
Тогда мы можем операцию сортировки выполнять в другом потоке. Например, запустим Воркер, передадим ему данные и завершим обработку события. И начнем обработку следующего.
Таким образом мы быстро обрабатываем события message, очередь необработанных не скапливается, но висят несколько (3-4) параллельных потока.

В этом случае, сообщение можно куда то сохранять. Не знаю, что у вас за клиент, и какого размера и вида сообщения, но на браузере можно было бы воспользоваться localStorage или indexedDB. В функции обработки события сначала сохраняем сообщение, а после окончания его обработки в Воркере удаляем. В этом случае у нас в базе при выключении клиента останутся необработанные сообщения.
Ответить с цитированием
  #10 (permalink)  
Старый 13.04.2020, 11:21
Новичок на форуме
Отправить личное сообщение для NatalliaF Посмотреть профиль Найти все сообщения от NatalliaF
 
Регистрация: 10.04.2020
Сообщений: 4

Т.е. в onmessage происходит лишь сохранение сообщений для последующей обработки воркерами? Количество воркеров определяется экспериментально (и зависит от загруженности клиента).
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Работа с базой данных kda7979 AJAX и COMET 38 15.04.2019 07:35
Подчитывание данных в компонент по HTTP sniffysko Angular.js 3 06.07.2018 15:10
Ошибка при обработке данных TBUCTEP Общие вопросы Javascript 11 12.05.2017 14:56
Не понимаю JavaScript. Как сделать ожидание события загрузки данных? xintrea AJAX и COMET 7 01.06.2013 17:18
Двойная Фильтрация данных таблицы David0707 Общие вопросы Javascript 0 19.03.2012 13:00