предисловие
С развитием Интернета пользователи предъявляют все более высокие требования к работе в Интернете в режиме реального времени.Например, мониторинг промышленных операций, онлайн-общение в Интернете, системы котировок в реальном времени, онлайн-игры и т. д. и в режиме реального времени передавать изменения, происходящие в фоновом режиме, на сторону браузера, не требуя от пользователя ручного обновления страницы. В этой статье сравниваются и обобщаются прошлые и настоящие популярные технологии web push в реальном времени.
Щелкните полный исходный код этой статьи.Блог на гитхабе, Это мелко на бумаге, я предлагаю вам начать вводить код.
1. Двусторонняя связь
У протокола HTTP есть недостаток: обмен данными может быть инициирован только клиентом. Например, если мы хотим узнать сегодняшнюю погоду, мы можем только сделать запрос от клиента к серверу, и сервер вернет результат запроса. Протокол HTTP не может позволить серверу активно передавать информацию клиенту. Характеристики этого одностороннего запроса обречены быть очень неприятными для клиента, чтобы узнать, есть ли у сервера непрерывные изменения состояния.До появления протокола WebSocket существовало три способа двунаправленной связи: опрос, длительный опрос и потоковая передача iframe..
1. Опрос
Опрос — это постоянное соединение между клиентом и сервером, которое запрашивается время от времени. Недостаток тоже очевиден: количество подключений будет велико, одно на прием и одно на отправку. иКаждый раз, когда отправляется запрос, будет Http Header, который будет потреблять много трафика и загружать ЦП..- Преимущества: простая реализация, нет необходимости вносить слишком много изменений.
- Недостатки: Если интервал опроса слишком велик, пользователи не смогут вовремя получать обновленные данные, если интервал опроса слишком мал, это приведет к слишком большому количеству запросов и увеличению нагрузки на серверную часть.
// 1.html
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock');
setInterval(function(){
let xhr = new XMLHttpRequest;
xhr.open('GET','/clock',true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
clockDiv.innerHTML = xhr.responseText;
}
}
xhr.send();
},1000);
</script>
//轮询 服务端
let express = require('express');
let app = express();
app.use(express.static(__dirname));
app.get('/clock',function(req,res){
res.end(new Date().toLocaleString());
});
app.listen(8080);
Запустите локальную службу, откройтеhttp://localhost:8080/1.html
, и получены следующие результаты:
2. Долгий опрос (long-polling)
Длинный опрос – это улучшенная версия опроса. После того, как клиент отправляет серверу HTTP, он проверяет, нет ли нового сообщения. Если нового сообщения нет, он продолжает ждать. При появлении нового сообщения оно будет возвращено клиенту. В некоторой степени уменьшаются такие проблемы, как пропускная способность сети и загрузка ЦП. Поскольку объем данных заголовка http-пакетов часто велик (обычно более 400 байт), а данных, действительно необходимых серверу, очень мало (иногда всего около 10 байт), такие пакеты циклически передаются по сети. неизбежныйэто пустая трата пропускной способности сети.- Преимущества: По сравнению с опросом, он оптимизирован и имеет лучшую своевременность.
- Недостатки: сохранение соединения потребляет ресурсы; сервер не возвращает достоверных данных, время ожидания программы истекло.
// 2.html 服务端代码同上
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock')
function send() {
let xhr = new XMLHttpRequest()
xhr.open('GET', '/clock', true)
xhr.timeout = 2000 // 超时时间,单位是毫秒
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
//如果返回成功了,则显示结果
clockDiv.innerHTML = xhr.responseText
}
send() //不管成功还是失败都会发下一次请求
}
}
xhr.ontimeout = function() {
send()
}
xhr.send()
}
send()
</script>
3. потоковая передача iframe (потоковая передача)
Метод потоковой передачи iframe заключается в том, чтобы вставить скрытый iframe на страницу и использовать его атрибут src для создания длинного соединения между сервером и клиентом.Обновить страницу.- Преимущества: сообщения могут приходить в режиме реального времени, хорошая совместимость с браузерами.
- Недостатки: сервер поддерживает длительное соединение, что увеличивает накладные расходы; IE, chrome, Firefox будут показывать, что загрузка не завершена, а значок будет продолжать вращаться.
// 3.html
<body>
<div id="clock"></div>
<iframe src="/clock" style="display:none"></iframe>
</body>
//iframe流
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.get('/clock', function(req, res) {
setInterval(function() {
let date = new Date().toLocaleString()
res.write(`
<script type="text/javascript">
parent.document.getElementById('clock').innerHTML = "${date}";//改变父窗口dom元素
</script>
`)
}, 1000)
})
app.listen(8080)
Запустите локальную службу, откройтеhttp://localhost:8080/3.html
, и получены следующие результаты:
В приведенном выше коде клиент запрашивает только один раз, но сервер постоянно отправляет данные клиенту, поэтому сервер поддерживает длительное соединение, что увеличивает накладные расходы.
Выше мы представили три технологии push в реальном времени, но их недостатки очевидны, и они не идеальны для использования.Далее мы сосредоточимся на другой технологии — websocket, которая является идеальной технологией двусторонней связи.
2. Веб-сокет
1. Что такое веб-сокет
WebSocket — это совершенно новый протокол. Благодаря постоянному совершенствованию черновика HTML5 все больше и больше современных браузеров начали полностью поддерживать технологию WebSocket. Он применяет TCP-сокет (сокет) к веб-странице, тем самым обеспечивая связь. Две стороны устанавливают канал связи, который остается активным.
После того как между веб-сервером и клиентом установлено соединение по протоколу WebSocket, все последующие соединения основаны на этом выделенном протоколе. В процессе связи данные в любом формате, таком как JSON, XML, HTML или изображения, могут быть отправлены друг другу.Поскольку это протокол, основанный на HTTP, инициатором соединения по-прежнему является клиент.После установления коммуникационного соединения WebSocket либо сервер, либо клиент могут напрямую отправлять сообщения другой стороне..
Любой, кто новичок в WebSockets, задает один и тот же вопрос: у нас уже есть протокол HTTP, зачем нам еще один протокол?
2. Ограничения HTTP
- HTTP является полудуплексным протоколом, то есть данные могут передаваться одновременно только в одном направлении, клиент отправляет запрос серверу (односторонний), а сервер отвечает на запрос (односторонний).
- Сервер не может активно отправлять данные в браузер. Это затрудняет реализацию некоторых расширенных функций, таких как сценарии чата.
3. Особенности веб-сокета
- Поддержка двусторонней связи, более в режиме реального времени
- Может отправлять текст или двоичные данные
- Уменьшите трафик: пока установлено соединение WebSocket, вы хотите, чтобы оно оставалось подключенным. По сравнению с HTTP сокращаются не только общие накладные расходы на каждое соединение, но и, поскольку информация заголовка WebSocket очень мала, соответственно уменьшается и объем связи.
По сравнению с традиционным режимом HTTP, в котором каждый запрос-ответ требует от клиента установления соединения с сервером, WebSocket представляет собой режим связи, аналогичный длинному TCP-соединению Socket.После установления соединения WebSocket последующие данные передаются в виде последовательность кадров. Прежде чем клиент разорвет соединение WebSocket или сервер разорвет соединение, клиенту и серверу не нужно повторно инициировать запрос на соединение.В случае массового параллелизма и большой нагрузки и трафика взаимодействия клиент-сервер потребление ресурсов пропускной способности сети значительно экономится, и есть очевидные преимущества в производительности, а клиент отправляет и получает сообщения по одному и тому же постоянному соединению.Очевидное сексуальное преимущество.
Далее позвольте мне увидеть, как websocket реализует двустороннюю связь между клиентом и сервером:
// websocket.html
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock')
let socket = new WebSocket('ws://localhost:9999')
//当连接成功之后就会执行回调函数
socket.onopen = function() {
console.log('客户端连接成功')
//再向服务 器发送一个消息
socket.send('hello') //客户端发的消息内容 为hello
}
//绑定事件是用加属性的方式
socket.onmessage = function(event) {
clockDiv.innerHTML = event.data
console.log('收到服务器端的响应', event.data)
}
</script>
// websocket.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
//http服务器
app.listen(3000)
let WebSocketServer = require('ws').Server
//用ws模块启动一个websocket服务器,监听了9999端口
let wsServer = new WebSocketServer({ port: 9999 })
//监听客户端的连接请求 当客户端连接服务器的时候,就会触发connection事件
//socket代表一个客户端,不是所有客户端共享的,而是每个客户端都有一个socket
wsServer.on('connection', function(socket) {
//每一个socket都有一个唯一的ID属性
console.log(socket)
console.log('客户端连接成功')
//监听对方发过来的消息
socket.on('message', function(message) {
console.log('接收到客户端的消息', message)
socket.send('服务器回应:' + message)
})
})
Запустите локальную службу, откройтеhttp://localhost:3000/websocket.html
, и получены следующие результаты:
3. Сравнение веб-технологии push-уведомлений в реальном времени
Способ | тип | Техническая реализация | преимущество | недостаток | Применимая сцена |
---|---|---|---|---|---|
Опрос | клиент→сервер | Запрос цикла клиента | 1. Простота реализации. 2. Поддержка междоменного доступа. | 1. Пустая трата пропускной способности и ресурсов сервера 2. Большая часть информации запроса бесполезна (полная информация заголовка HTTP) 3. Задержка 4. Большая часть недействительных запросов | Подходит для небольших приложений |
Долгий опрос | клиент→сервер | Сервер удерживает соединение и возвращается до тех пор, пока не появятся данные или тайм-аут, что уменьшает количество повторных запросов. | 1. Простая реализация 2. Отсутствие частых запросов 3. Экономия трафика 4. Низкая задержка | 1. Сервер удерживает соединение, которое потребляет ресурсы 2. Большая часть запрошенной информации бесполезна | WebQQ, Привет веб-версия, Facebook IM |
длинное соединение iframe | клиент→сервер | Вставьте скрытый iframe в страницу, установите атрибут src этого iframe в запрос на длительное соединение, и сервер сможет непрерывно вводить данные клиенту. | 1. Доставка данных в режиме реального времени 2. Никаких бесполезных запросов, одна ссылка, несколько "пушей" | 1. Сервер увеличивает накладные расходы 2. Невозможно точно узнать статус подключения 3. IE, хром и т.д. всегда будут в состоянии загрузки | Чат Gmail |
WebSocket | сервер⇌клиент | new WebSocket() | 1. Поддержка двусторонней связи, более высокая производительность в режиме реального времени. 2. Можно отправлять двоичные файлы. 3. Уменьшить количество сообщений. | 1. Степень поддержки браузера непостоянна 2. Отключение и повторное подключение не поддерживаются | Онлайн-игры, банковские операции и платежи |
Подводя итог: протокол Websocket не только решает пассивность сервера в протоколе HTTP, то есть связь может быть инициирована только клиентом, но и решает проблему задержки синхронизации данных, а также приносит очевидные преимущества в производительности, поэтому websocket Это идеальное решение для веб-технологии push-уведомлений в реальном времени, но если вы хотите быть совместимым с браузерами с более низкими версиями, вы можете рассмотреть возможность опроса.
Порекомендуйте полезный инструмент мониторинга ошибок для всехFundebug, добро пожаловать, чтобы попробовать это бесплатно!
Добро пожаловать в публичный аккаунт:Мастер по фронтенду, мы будем свидетелями вашего роста вместе! Если вы чувствуете, что что-то приобрели, пожалуйста, дайте мне вознаграждение, чтобы мотивировать меня выпускать больше высококачественного контента с открытым исходным кодом.
Справочная статья
- Учебник по веб-сокетам
- Курс по интерфейсной архитектуре Everest
- Краткий обзор технологии веб-передачи в реальном времени
- WebSocket (1): эволюция «проталкивания в реальном времени» на стороне сервера
- Сравнение основных серверных технологий push-уведомлений, таких как длинное соединение/веб-сокет/SSE.