На днях обнаружил (для себя) интересную особенность WebSocket-та: onmessage обработчики срабатывают в порядке отличном от порядка send на отправляющей стороне. Казалось бы, web и это вполне может быть в асинхронной среде, но хотелось бы внятного описания в документации, может кто-то встречал??? Самому найти не получилось
Здравствуйте, Videoman, Вы писали:
V>На днях обнаружил (для себя) интересную особенность WebSocket-та: onmessage обработчики срабатывают в порядке отличном от порядка send на отправляющей стороне. Казалось бы, web и это вполне может быть в асинхронной среде, но хотелось бы внятного описания в документации, может кто-то встречал??? Самому найти не получилось
Если это один вебсокет, такого быть не должно. Если два вебсокета, хоть бы и в одно и то же место, такое запросто может быть.
Здравствуйте, Mystic Artifact, Вы писали:
MA>Это вроде не нормальное поведение. Кто является отправителем сообщений? Может быть серверный фреймворк не даёт таких гарантий?
Все происходит в локальной сети. Отправляются пакеты со стороны браузера. На сервере (простейший С++, TCP сокет, свой маленький парсер WebSocket пакетов) они принимаются в точно таком же порядке как и отправлялись. Здесь все как и ожидалось никогда никаких переупорядочиваний нет. Пакеты это простейший json в котором присутствует номер пакета и этот номер отправляется обратно вместе с ответом. С++ сервер работает на одном сокете строго последовательно (принял-отдал, принял-отдал).
На приеме в браузере в обработчиках onmessage детектируется номера ответов. В спокойных условиях порядок также не меняется, а вот если нагрузить сеть близко к 100%, то номера ответов в обратных вызовах onmessage иногда начинают перемешиваться — меняется порядок.
P.S. Браузер Chrome 80.0.3987.116
Здравствуйте, Pzz, Вы писали:
Pzz>Если это один вебсокет, такого быть не должно. Если два вебсокета, хоть бы и в одно и то же место, такое запросто может быть.
Естественно один, иначе бы и вопросов не было. Я в соседней ветке постарался описать подробнее условия WebSocket теста.
Здравствуйте, Videoman, Вы писали:
V>P.S. Браузер Chrome 80.0.3987.116
Попробуй FF. Если всё вышеописанное — правда, то это больше похоже на баг, хотя у них такие жидкие спецификации, что даже если предъявишь — то наверняка найдут оправдание.
Здравствуйте, Mystic Artifact, Вы писали:
MA> Попробуй FF. Если всё вышеописанное — правда, то это больше похоже на баг, хотя у них такие жидкие спецификации, что даже если предъявишь — то наверняка найдут оправдание.
Можно конечно, но FF умирающий браузер и он слишком мало распространен что бы я мог игнорировать Chrome. Пока по экспериментам получается так: если работаем в "расслабленном" режиме, то все ок. Если нагружаем WebSocket на приеме и JS код не успевает растаскивать пакеты, то внутренняя очередь которая дергает onmessage, как-то умудряется менять порядок вызовов. Сразу в onmessage callback стоит логирование, поэтому другую асинхронность я исключаю. Еще что заметил, что порядок меняется как у стека, типа: отправили 1,2,3,4,5,6...
приняли: 3,2,1,4,6,5....
Здравствуйте, Videoman, Вы писали:
V>Можно конечно, но FF умирающий браузер и он слишком мало распространен что бы я мог игнорировать Chrome.
Цель не в том, что бы определить кто из них лучше, а в том, что бы выявить является ли обнаруженное поведение общим. Хотя, рискну предположить, то FF окажется слишком старомодным то бы наступить на эти грабли.
V>Пока по экспериментам получается так: если работаем в "расслабленном" режиме, то все ок. Если нагружаем WebSocket на приеме и JS код не успевает растаскивать пакеты, то внутренняя очередь которая дергает onmessage, как-то умудряется менять порядок вызовов. Сразу в onmessage callback стоит логирование, поэтому другую асинхронность я исключаю. Еще что заметил, что порядок меняется как у стека, типа: отправили 1,2,3,4,5,6... V>приняли: 3,2,1,4,6,5....
В спеке говорится, что message должен становится в очередь задач (tasks), и что только microtasks в некоторых случаях могут переехать в другую очередь. Но очередь на то и очередь, что она упорядочена. Однако в реальной реализации спеки деталей много больше, так например я вполне допускаю (когда-то по крайней мере такое наблюдал), что внутренние меж-процессные сообщения вполне могут доставляться вне своего порядка. Но, это опять таки не про все сообщения, так что тут я не имею никакой информации конкретно на твой случай.
Если данный эффект действительно имеет место быть, то он должен быть вполне легко наблюдаем/повторяемым на одной машине через локалхост, иначе это больше похоже на какие-то странности сети (что тоже звучит дико).
Собственно дальше нужен только код повторения и либо пробовать повторять, репортить ошибку (или получить внятный ответ что это не ошибка), либо искать ошибку в своём коде, либо ещё где...
PS: Я согласен, что вопрос как-то не особо освящен, то ли я тоже слепой. Но код хрома колупать не буду, если не увижу такое поведение сам.
Здравствуйте, reversecode, Вы писали:
R>уверенны что со стороны сервера они уходят в правильном порядке ?
100%. На передающей и принимающей стороне все залогировано. Более того, в нашем протоколе в пакеты специально были заложены порядковые номера для проверки случайного нарушения логики в нашем коде. Код у кучи клиентов работает уже несколько лет. Но вот у одного из клиентов в ситуации загрузки сети стали вылетать ассерты, так я и узнал о проблеме и теперь пытаюсь выяснить причину, и не в коем случае не утверждаю что в нашем коде нет какой-то хитрой ошибки (если есть, то 100% в части JS).
R>вебсокеты в хроме используются везде и по всюду R>если бы были такие проблемы их бы уже выявили
Ну я не знаю. Зачем тогда он сделан message-ориентиованным? Если в протоколе никак не полагаться на порядок сообщений, то можно и не заметить, там же все асинхронно. Полагаться на порядок в вебе даже вредно. Там же кругом асинхронщина и если, например, пакеты пришли 1,2,3 и мы их передали асинхронно на обработку, то обработка пакетов запросто может закончится как 3,2,1.
В RFC я нашел единственно упоминание что сообщение может быть фрагментировано и фрагменты ДОЛЖНЫ быть получены принимающей стороной строго в порядке отправки, но я не понял какие фрагменты они имеют ввиду, сами сообщения или фрагменты сообщений.
R>помнится недавно была тема по переупорядовачивание tcp пакетов R>вы случайно не соседи с тем ТС ? ))
нет
Здравствуйте, Mystic Artifact, Вы писали:
MA> PS: Я согласен, что вопрос как-то не особо освящен, то ли я тоже слепой. Но код хрома колупать не буду, если не увижу такое поведение сам.
Я не могу сейчас сказать 100% где ошибка. Поэтому и спрашиваю у коллег. Может быть кто-то может ткнуть в спецификацию где явно написано что такого быть не может, или наоборорот, скажет что сталкивался с таким поведением, или знает в чем может быть дело. Пока продолжаю рассматривать все выдвинутые версии почему так может быть.
Здравствуйте, reversecode, Вы писали:
R>пусть клиент заллогирует tcp сессию на своей стороне R>и проверите в варешарке что там R>99% это глюкавое оборудование в его сети
Сам TCP ничего не переупорядочивает, никогда. Не вижу смысла это рассматривать серьезно.
R>поверх websocket строятся и чаты и видео сессии R>если бы порядок мог нарушаться — это бы не работало
Вы не поверите, но я именно этим сейчас и занимаюсь, делаю чаты и видео сессии в Web, и я никак не пойму зачем мне закладываться на порядок прихода сообщений по WebSocket-у ??? У каждого сообщения всегда есть метка времени и по ней принимающая сторона все упорядочивает. Я просто пытаюсь точно понять поведение веб сокета (не сокета TCP), что бы избежать проблем в будущем. Так-то можно прямо сейчас пятью строчками сделать очередь и руками упорядочить все запросы. Хочется понять причину и понять как правильно, а заодно исключить причину ошибки где-то еще.
Здравствуйте, Videoman, Вы писали:
V>Я не могу сейчас сказать 100% где ошибка. Поэтому и спрашиваю у коллег. Может быть кто-то может ткнуть в спецификацию где явно написано что такого быть не может, или наоборорот, скажет что сталкивался с таким поведением, или знает в чем может быть дело. Пока продолжаю рассматривать все выдвинутые версии почему так может быть.
Тут в соседней ветке безаппеляционно говорят, что это может быть сеть. Я лично своими глазами видел как работает глючащая сеть, поэтому тоже вполне верю в такое, хотя это и редко (на мой взгляд).
Ты ж сам сказал, что для спец эффектов надо нагрузить сеть. Про нагрузку проца или сопутствующего IO ты умолчал — только гадать. Если это повторимо только на железе клиента... но неповторимо на локальном железе с настоящей сетью, со свичом или без него — то я бы все таки смотрел в сторону сети и/или драйверов.
С той же стороны — вебсокеты можно и по http2 толкать и есть даже мультепликсирование. В хроме фактически есть 3 транспорта для них. Плюс довольно запутанный путь в браузере окромя этого.
Я бы не стал полагаться на то, что в хроме там всё на вебсокетах и все работает — там ничего на вебсокетах нету, кроме девтулз, транспорт к которому обеспечивается обычно не тцп, а парой обычных вызовов и весь протокол полностью асинхронный и на порядок не полагается. Да его там и не может быть — события о которых он говорит из другого процесса и синхронно не обрабатываются.
UPD: Имел ввиду, что так как я видел это изнутри — я знаю что это за халабуда и слепо бы не верил в идеальность браузера. Но вместе с тем, мне лично, кажется объяснение с сетью более вероятным.
Здравствуйте, Videoman, Вы писали:
V>На днях обнаружил (для себя) интересную особенность WebSocket-та: onmessage обработчики срабатывают в порядке отличном от порядка send на отправляющей стороне.
Посмею предположить, что ваш сервер неосознанно делает send из нескольких потоков в один сокет, Unix такое позволяет. В результате получаем race condition и "переупорядочивание" сообщений на принимающей стороне.
Здравствуйте, Videoman, Вы писали:
V>Здравствуйте, Mystic Artifact, Вы писали:
MA>>Это вроде не нормальное поведение. Кто является отправителем сообщений? Может быть серверный фреймворк не даёт таких гарантий?
V>Все происходит в локальной сети. Отправляются пакеты со стороны браузера. На сервере (простейший С++, TCP сокет, свой маленький парсер WebSocket пакетов) они принимаются в точно таком же порядке как и отправлялись. Здесь все как и ожидалось никогда никаких переупорядочиваний нет. Пакеты это простейший json в котором присутствует номер пакета и этот номер отправляется обратно вместе с ответом. С++ сервер работает на одном сокете строго последовательно (принял-отдал, принял-отдал). V>На приеме в браузере в обработчиках onmessage детектируется номера ответов. В спокойных условиях порядок также не меняется, а вот если нагрузить сеть близко к 100%, то номера ответов в обратных вызовах onmessage иногда начинают перемешиваться — меняется порядок. V>P.S. Браузер Chrome 80.0.3987.116
конечно вводных мало,
но например у меня похожая путаница была когда тупо стоял ре-коннектор на webscoket, а разборщик сообщений не учитывал момент реконнекта.
при нагруженной сети бывает что ws рвётся, поэтому простейший реконнектор не помешает...
Здравствуйте, Aquilaware, Вы писали:
A>Посмею предположить, что ваш сервер неосознанно делает send из нескольких потоков в один сокет, Unix такое позволяет. В результате получаем race condition и "переупорядочивание" сообщений на принимающей стороне.
Точно нет. Сервер тупой как валенок — один поток, один сокет, последовательная обработка сообщений — вопрос — ответ.
P.S. Сейчас клиент сказал что у них обращение идет на WebSocket Proxy. Если причина, то в нем скорее всего.
Здравствуйте, Michael, Вы писали:
M>конечно вводных мало, M>но например у меня похожая путаница была когда тупо стоял ре-коннектор на webscoket, а разборщик сообщений не учитывал момент реконнекта. M>при нагруженной сети бывает что ws рвётся, поэтому простейший реконнектор не помешает...
Спасибо большое!!! Попадание 100%. Просто пока мало опыта у наших веб-программистов . При сильной загрузке рвалось соединение (а при работе с обычными сокетами, согласителсь, это не часто происходит) и глючила логика реконекта.