Передовые технологии в интерактивном прямом эфире — обмен мгновенными сообщениями

WebSocket
Передовые технологии в интерактивном прямом эфире — обмен мгновенными сообщениями

Автор этой статьи: У Цзе

предисловие

Во время эпидемии офисные работники перешли на удаленную работу и испытали на себе различные программы для удаленной работы. Учитель стал ведущим, ученики почувствовали страх перед доминированием Диндин, певцы начали онлайн-концерты, и многие развлекательные шоу стали транслироваться в прямом эфире. В этот период национальной интерактивной прямой трансляции давайте поговорим об использовании технологии обмена мгновенными сообщениями в интерфейсе интерактивной прямой трансляции.

технология обмена мгновенными сообщениями

Обмен мгновенными сообщениями (сокращенно IM) — это система связи в реальном времени, которая позволяет двум или более людям использовать сеть для обмена текстовыми сообщениями, файлами, голосом и видео в режиме реального времени. Как этого достичь, обычно для достижения этого мы будем использовать технологию push-уведомлений сервера. Общие реализации следующие.

голосование

Это техническая реализация, которую мы почти все использовали. Между клиентом и сервером всегда есть связь, время от времени запрашивающая. Внешний интерфейс обычно использует setInterval или setTimeout для непрерывного запроса данных сервера.

Преимущества. Простота реализации и возможность обработки асинхронных служб запросов.

Недостатки: Время опроса обычно мёртвое, слишком длинное и оно не очень в реальном времени, слишком короткое увеличивает нагрузку на серверную сторону. Кроме того, это пустая трата серверных ресурсов на непрерывный запрос бессмысленных обновленных данных.

долгий опрос

Клиент отправляет запрос на сервер, сервер, если нет новых данных, чтобы поддерживать это соединение, пока есть данные. Как только сервер получает данные (сообщение) для клиента, он использует соединение для отправки данных клиенту. Затем соединение закрывается.

Преимущества: По сравнению с опросом он оптимизирован и имеет лучшую своевременность.

Недостатки: занимают больше ресурсов памяти и количество запросов.

поток iframe

Поток iframe предназначен для динамической загрузки iframe в браузере, чтобы его адрес указывал на указанный адрес запрошенного сервера (то есть для отправки http-запроса на сервер), а затем создания функции на стороне браузера для обработки данные, на стороне сервера Через долгое соединение между iframe и браузером данные периодически выводятся на клиент.Когда страница iframe получает эти данные, она разбирает их в код и передает данные на родительскую страницу для достижения Цель обмена мгновенными сообщениями.

Преимущества: По сравнению с опросом он оптимизирован и имеет лучшую своевременность.

Недостатки: плохая совместимость и пользовательский опыт. Сервер поддерживает длительное соединение, что увеличивает накладные расходы. Значки адресной строки некоторых браузеров будут продолжать превращаться в хризантемы.

Server-sent Events(sse)

SSE аналогичен механизму длительного опроса, и разница состоит в том, что каждое соединение не только отправляет сообщение. Клиент отправляет запрос, сервер сохраняет это подключение до тех пор, пока новое сообщение не отправляется обратно к клиенту, который все еще подключен, чтобы соединение снова можно отправить, и сервер отправляется на один путь клиента.

Преимущества: стандарт HTML5, простота реализации, одно соединение может отправлять несколько данных.

Недостатки: плохая совместимость (IE, Edge не поддерживает), сервер может проталкивать данные клиенту только в одном направлении.

WebSocket

Спецификация HTML5 WebSocket определяет API, который позволяет веб-страницам двунаправленно взаимодействовать с удаленными узлами с использованием протокола WebSocket. Значительно сокращает ненужный сетевой трафик и время ожидания по сравнению с опросом и длительным опросом.

WebSocket — это протокол прикладного уровня. Он основан на транспортном протоколе TCP и мультиплексирует канал квитирования HTTP. Но он не основан на протоколе HTTP, просто используйте HTTP перед установкой соединения, а затем обновите протокол до ws или wss при первом рукопожатии.

Преимущества: низкие накладные расходы, двусторонняя связь, поддержка двоичной передачи.

Недостатки: Высокая стоимость разработки, требуется дополнительное переподключение и поддержка.

В сценарии интерактивной прямой трансляции из-за высоких требований к реальному времени серверу и клиенту требуется частая двусторонняя связь, поэтому он очень подходит для этого.

Создайте свою собственную систему обмена мгновенными сообщениями

Выше кратко изложена технология реализации мгновенного обмена сообщениями, а затем мы поговорим о том, как реализовать собственную систему обмена мгновенными сообщениями.

Построение системы обмена мгновенными сообщениями с нуля по-прежнему сложно и утомительно. Создайте свою собственную рекомендацию на основеsocket.ioреализовать. Инкапсуляция обмена мгновенными сообщениями в Socket.io уже очень хороша. Это относительно зрелая библиотека. Она совместима с различными браузерами и предоставляет решения для каждой стороны, включая сервер. Нам не нужно заботиться о том, какая технология используется на Внизу для реализации передачи данных, конечно же, в основном используется WebSocket в современных браузерах. На рынке также существует множество платформ облачных сервисов обмена мгновенными сообщениями, таких какЮньсинь, с помощью сторонних сервисов тоже можно быстро интегрировать. Далее описывается, как интерфейс интегрирован и разработан на основе socket.io.

основное здание

Сервер интегрирует socket.io (с java версией), сервер готов, вы можете обратиться к следующемуздесь, клиент использует интеграцию socket.io-client. Обратитесь к официальному API socket.io, подпишитесь на жизненный цикл и события и реализуйте базовые функции с помощью подписки. Выполните логику, такую ​​как синтаксический анализ и упаковка, в функции обратного вызова и, наконец, передайте ее бизнесу верхнего уровня для использования.

import io from 'socket.io-client';
import EventEmitter from 'EventEmitter';
class Ws extends EventEmitter {
    constructor (options) {
        super();
        //...
        this.init();
    }
    init () {
        const socket  = this.link = io('wss://x.x.x.x');
        socket.on('connect', this.onConnect.bind(this));
        socket.on('message', this.onMessage.bind(this));
        socket.on('disconnect', this.onDisconnect.bind.(this);
        socket.on('someEvent', this.onSomeEvent.bind(this));
    }
    onMessage(msg) {
        const data = this.parseData(msg);
        // ...
        this.$emit('message', data);
    }
}

Обмен сообщениями

При общении с сервером или другим клиентом проанализированное сообщение обычно инкапсулируется и разрешается на основе протокола бизнес-контракта. Поскольку все они являются асинхронными, для обработки обратных вызовов сообщений требуется уникальный идентификатор. Здесь отмечен самоувеличивающейся последовательностью.

отправлять сообщения

class Ws extends EventEmitter {
    seq = 0;
    cmdTasksMap = {};
    // ...
    sendCmd(cmd, params) {
        return new Promise((resolve, reject) => {
            this.cmdTasksMap[this.seq] = {
                resolve,
                reject
            };
            const data = genPacket(cmd, params, this.seq++);
            this.link.send({ data });
        });
    }
}

получить сообщение

class Ws extends EventEmitter {
    // ...
    onMessage(packet) {
        const data = parsePacket(packet);
        if (data.seq) {
            const cmdTask = this.cmdTasksMap[data.seq];
            if (cmdTask) {
                if (data.body.code === 200) {
                    cmdTask.resolve(data.body);
                } else {
                    cmdTask.reject(data.body);
                }
                delete this.cmdTasksMap[data.seq];
            }
        }
    }
}

Оптимизирован для производственных сред

Вышеизложенное представляет только простую инкапсуляцию основных функций.При использовании его в производственной среде необходимо учитывать множество факторов, особенно в сцене интерактивной прямой трансляции, демонстрации подарков, последовательности пшеницы (последовательности взаимодействия голосового вызова), чате, групповой чат Мы сильно полагаемся на стабильность длинных ссылок, поэтому вот некоторые основы и меры по оптимизации.

удержание соединения

Для того, чтобы установить длинное соединение и стабильно поддерживать длинное соединение. Используются следующие средства:

  • Обработка тайм-аута
  • пакет сердцебиения
  • Механизм отсрочки повторного подключения

Обработка тайм-аута

В реальном использовании не обязательно, чтобы сервер отвечал каждый раз, когда отправляется сообщение, и на стороне клиента могло возникнуть исключение. Основываясь на этом, мы можем добавить логику тайм-аута, чтобы определить, успешна ли передача. Затем на основе верхнего уровня обратного вызова появляется дружественная подсказка и вводится обработка исключений. Далее мы дополнительно изменим логику отправки.

class Ws extends EventEmitter {
    // ...
    sendCmd(cmd, params) {
        return new Promise((resolve, reject) => {
            this.cmdTasksMap[this.seq] = {
                resolve,
                reject
            };
            // 加个定时器
            this.timeMap[this.seq] = setTimeout(() => {
                const err = new newTimeoutError(this.seq);
                reject({ ...err });
            }, CMDTIMEOUT);

            const data = genPacket(cmd, params, this.seq++);
            this.link.send({ data });
        });
    }
    onMessage(packet) {
        const data = parsePacket(packet);
        if (data.seq) {
            const cmdTask = this.cmdTasksMap[data.seq];
            if (cmdTask) {
                clearTimeout(this.timeMap[this.seq]);
                delete this.timeMap[this.seq];
                if (data.body.code === 200) {
                    cmdTask.resolve(data.body);
                } else {
                    cmdTask.reject(data.body);
                }
                delete this.cmdTasksMap[data.seq];
            }
        }
    }
}

пакет сердцебиения

Пакет сердцебиения: пакет сердцебиения — это самоопределяемое командное слово, которое периодически информирует другую сторону об их собственном статусе между клиентом и сервером и отправляется с определенным интервалом времени, похожим на сердцебиение, поэтому он называется сердцебиением. пакет.

Пакет сердцебиения является ключевым методом для выживания соединения генерального инспектора.На веб-стороне мы оцениваем, истекло ли время ожидания пакета сердцебиения. Уже в ПТСопция поддержания активностиПочему вы хотите присоединиться к вашему механизму сердцебиения на прикладном уровне?

  • tcp keepalive проверить, живо ли соединение
  • Проверка активности приложения определяет, может ли приложение нормально реагировать

Например: сервер заблокирован и не может обрабатывать бизнес-запросы. Но операционная система по-прежнему может отвечать на пакеты проверки активности сетевого уровня. Поэтому мы обычно используем пустые пакеты пульса и устанавливаем соответствующую частоту отправки и тайм-аут в качестве суждения о сохранении соединения.

Если сервер распознает пакет пульса только как оценку существования соединения, он может регулярно отправлять пульс после установления соединения. Если он считается активным по получению пакета, сбрасывайте его каждый раз при получении сообщения и запускайте таймер для отправки пакета пульса.

class Ws extends EventEmitter {
    // ...
	 onMessage(packet) {
        const data = parsePacket(packet);
        if (data.seq) {
            const cmdTask = this.cmdTasksMap[data.seq];
            if (cmdTask) {
                clearTimeout(this.timeMap[this.seq]);
                if (data.body.code === 200) {
                    cmdTask.resolve(data.body);
                } else {
                    cmdTask.reject(data.body);
                }
                delete this.cmdTasksMap[data.seq];
            }
        }
        this.startHeartBeat();
    }
    startHeartBeat() {
        if (this.heartBeatTimer) {
            clearTimeout(this.heartBeatTimer);
            this.heartBeatTimer = null;
        }
        this.heartBeatTimer = setTimeout(() => {
            // 在sendCmd中指定heartbeat类型seq为0,让业务包连续编号
            this.sendCmd('heartbeat').then(() => {
                // 发送成功了就不管
            }).catch((e) => {
                this.heartBeatError(e);
            });
        }, HEARTBEATINTERVAL);
    }
}

Механизм отсрочки повторного подключения

Не удается подключиться, переподключиться, по-прежнему не удается подключиться, переподключиться, не удается подключиться, переподключиться. Переподключение — это средство поддержания жизни, но оно не может переподключаться постоянно, поэтому мы должны использовать разумные меры для переподключения.

Обычно сервер предоставляет интерфейс lbs (Location Based Services, LBS) для предоставления оптимального узла. Что нам нужно сделать на стороне, так это кэшировать эти адреса и установить механизм отсрочки повторного подключения на стороне. Последующая обработка обычно выполняется по количеству уровней.

  • Повторное подключение (время ожидания
  • Измените адрес подключения и переподключитесь (время ожидания>=X раз)
  • Повторно получить адрес соединения (X
  • Обработка верхнего уровня (выше MAX)

После повторного подключения X раз выберите изменение адреса.После сбоя адреса выберите получение адреса еще раз и повторите попытку в цикле. Конкретное количество попыток зависит от фактического бизнеса. Конечно, в случае сбоев снова и снова следует сообщать об исключениях, чтобы облегчить анализ и решение проблем.

Оптимизация получения сообщений

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

Fn.startMsgFlushTimer = function () {
    this.msgFlushTimer = setTimeout(() => {
    const msgs = this.msgBuffer.splice(0, BUFFERSIZE);
    // 回调消息通知
    this.onmsgs(msgs);
    if (!this.msgBuffer.length) {
      this.msgFlushTimer = null;
    } else {
      this.startMsgFlushTimer();
    }
  }, MSGBUFFERINTERVAL);
};

Оптимизация трафика

постоянное хранение

В сценарии с одним чатом каждый раз синхронизировать все разговоры, исторические сообщения и т. д. — большая цена. Кроме того, отключение Интернета также является относительно простой операцией (в основном требуется повторная синхронизация). Если мы будем синхронизироваться поэтапно, мы можем уменьшить много трафика. Реализация добавочной синхронизации, естественно, подразумевает веб-хранилище.

Обычно используемые файлы cookie веб-хранилища, localStorage и sessionStorage недостаточны для удовлетворения наших постоянных сценариев, но indexedDB html5 обычно удовлетворяет наши потребности. IndexedDB использует хранилище объектов для внутреннего хранения данных. Все типы данных могут храниться напрямую, включая объекты JavaScript. Может быть неудобно использовать API indexedDB напрямую, вы можете использоватьDexie.js,db.jsЭти вторичные инкапсулированные библиотеки реализуют уровень данных бизнеса.

После удовлетворения постоянного хранения мы можем использовать отметку времени для синхронизации инкрементных, при получении сообщения уведомления сохраняется в веб-базе данных. Лучшие операции Извлеките данные, данные приоритетного доступа из базы данных, всегда избегайте высокочастотных данных, объемных данных с сервером. Конечно, не существуют в конфиденциальной информации базы данных или указывают на увеличенные сложности ^ решение, в конце концов, все локально сохраненные веб-сайты могут видеть. Также обратите внимание, что размер магазина есть ограничения,Каждый браузер может отличаться, но он намного больше, чем другие локальные веб-хранилища.Пока данные, которые должны быть размещены в облаке, размещены в облаке (например, обмен сообщениями в облаке), особых проблем не возникнет.

С точки зрения реализации кодирования, поскольку обработка уведомлений о сообщениях является асинхронной операцией, необходимо поддерживать гарантию очередиСроки складирования. Кроме того, сделайтеСценарий понижения версии.

уменьшить количество подключений

В сцене интерактивной прямой трансляции на веб-рабочем столе должно быть очень часто открывать доступ к нескольким вкладкам на одной и той же странице. В бизнесе тоже будут многотерминальные межкик-операции, но если в веб-сценарии может взаимодействовать только одна страница, то точно не получится.Если не быть внимательным, то не будешь знать, на какую вкладку резать. Поэтому обычно устанавливается максимальное количество многотерминальных онлайнов, и при его превышении происходит кик. Поэтому очень часто браузер устанавливает 7 или 8 длинных ссылок, и это также большая трата ресурсов на стороне сервера.

Web Workers предоставляют веб-содержимому простой способ запуска сценариев в фоновом потоке, где поток может выполнять задачи, не мешая пользовательскому интерфейсу. И сообщение может быть отправлено коду JavaScript, который его создал, отправив сообщение в обработчик событий, указанный этим кодом (и наоборот). Хотя DOM API нельзя использовать в Web Worker, нет никаких ограничений на коммуникационные API, такие как XHR и WebSocket (и они могут работать с локальным хранилищем). Таким образом, мы можем создать сценарий, который выполняет указанный сценарий для совместного использования веб-работника через SharedWorker API, чтобы реализовать повторное использование связи перед несколькими вкладками, чтобы достичь цели сокращения количества подключений. Вы можете попробовать его в сценариях, где требования совместимости не так высоки.

резюме

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

использованная литература

Эта статья была опубликована сКоманда внешнего интерфейса NetEase Cloud Music, Любое несанкционированное воспроизведение статьи запрещено. Мы всегда нанимаем, если вы готовы сменить работу и вам нравится облачная музыка, тоПрисоединяйтесь к нам!