привет~ Уважаемые наблюдатели и господа, Привет всем~ Первая неделя китайского Нового года закончилась, и пришло время начать составлять новый план работы. Основным ответственным проектом является платформа визуализации данных, и если у сервера есть возможность отправить страницу для получения соответствующих уведомлений, можно добиться многих функциональных оптимизаций. Ввиду того, что Node-сторона проекта официально введена в эксплуатацию, а у front-end есть свой сервер, заниматься делами, естественно, гораздо удобнее.
Выбор технологии: SSE (отправленные сервером события) или WebSocket
Несколько лет назад у сервера не было возможности активно пушить, в основном за счет опроса, чтобы добиться возможности аппроксимации пуша сервера. Сейчас нет нужды так утруждать себя, опрос — это только решение с обратной совместимостью, а нынешняя мейнстримная прошивка сервера реализована с использованием SSE или WebSocket. Сравнение между ними выглядит следующим образом:
Основано ли оно на новом соглашении? | Двусторонняя ли связь | Поддерживать ли междоменное | стоимость доступа | |
---|---|---|---|---|
SSE | нет(Http ) |
Нет (сервер однонаправленный) | Нет (Firefox поддерживает междоменный доступ) | Низкий |
WebSocket | Да(ws ) |
да | да | высоко |
Одна вещь, которая нуждается в небольшом объяснении, — это стоимость доступа. SSE — это относительно легкий протокол, (Node) код относительно прост в реализации, а WebSocket — более сложный протокол. реализация на стороне сервера не сложная. При этом для реализации WebSocket нужно запустить еще один сервис, а SSE это не нужно.
После сравнения у меня есть общее представление о SSE и WebSocket. Требованием проекта к серверу push является отправка уведомлений, и в будущем может потребоваться доступ к функции синхронизации в реальном времени.После объединения фактической ситуации проекта и стоимости доступа был выбран SSE.
Наконец, взгляните на поддержку браузера для справки:
IE
Сразуlet it go
Ну, в повседневной жизни он не поддерживается ~ Другие браузеры все еще зеленые, и поддержка все еще довольно высока.
Пример
Сторона узла
В качестве каркаса в проекте используется яйцо, а нижний слой — Koa2, поэтому Koa2 используется в качестве примера. Код ключа на стороне узла выглядит следующим образом:
app.use(async (ctx) => {
const { res, request: { url } } = ctx;
res.writeHead(200, {
'Content-Type': 'text/event-stream', // 服务器声明接下来发送的是事件流
});
let stream = new PassThrough();
let i = 0;
let timer = setInterval(() => {
if (i === 5) {
stream.write('event: pause\n'); // 事件类型
} else {
stream.write('event: test\n'); // 事件类型
}
stream.write(`id: ${+new Date()}\n`); // 消息ID
stream.write(`data: ${i}\n`); // 消息数据
stream.write('retry: 10000\n'); // 重连时间
stream.write('\n\n'); // 消息结束
i++;
}, 1000);
stream.on('close', function() {
console.log('closed.')
clearInterval(timer);
})
ctx.body = stream;
});
Сервер сообщает клиенту, что возвращаемый тип является потоком событий (текст/поток событий), см.MDNВ документации показано, что поток событий — это просто поток текстовых данных, и текст должен быть закодирован в формате UTF-8. Каждое сообщение отделяется пустой строкой. Строки комментариев к поведению, начинающиеся с двоеточия, игнорируются.
Затем следует тело сообщения, хотя в примере используетсяsetInterval
Симуляция постоянно отправляет push-уведомления, но также можно переключиться на запуск push-уведомлений с произвольными условиями.stream.write
Вызывается 5 раз, соответствуя каждому полю в спецификации, понимается следующим образом:
-
event
является типом события сообщения. клиент вEventSource
сквозьaddEventListener
Слушайте соответствующие новости. Это поле можно опустить, и клиент инициируетmessage
мероприятие. -
id
это идентификатор события. Как значение свойства "идентификатора последнего события" внутри клиента, оно используется для повторного подключения и не может быть опущено. -
data
Короче говоря, это поле данных сообщения после того, как клиент прослушает некоторое время, черезe.data
полученные данные. -
retry
Для времени переподключения этот параметр можно не указывать. - Наконец, уведомление заканчивается
\n\n
, нельзя опускать. За исключением имен полей, указанных выше, все остальные имена полей игнорируются.
Более подробное объяснение можно найти вMDNдокументация. Следует отметить небольшую деталь: в черновике SSE упоминается, что передачи MIME-типа «текст/поток событий» должны автоматически отключаться через 15 секунд бездействия. Однако после фактического измерения (только с помощью Chrome) было обнаружено, что даже если статическое время превышает 15 секунд, браузер и клиент не будут отключены. Прочитав множество статей, рекомендуется вести набор рассылки\n\n
механизм сердцебиения. Лично я думаю, что это поможет улучшить надежность клиентской программы, но это не обязательно.
Наконец, прослушайте поток событийclose
Событие, используемое для завершения этой ссылки. После тестирования выяснилось, что стоит ли давать клиенту звонитьclose
метод (примеры ниже) или аварийное завершение, в том числе закрытие окна, закрытие программы и т. д., могут вызватьclose
мероприятие.
клиент
Код клиента проще, пример такой:
const source = new EventSource('http://localhost:3000/test');
source.addEventListener('open', () => {
console.log('Connected');
}, false);
source.addEventListener('message', e => {
console.log(e.data);
}, false);
source.addEventListener('pause', e => {
source.close();
}, false);
Обувь передней стороны Для такого кода должна быть довольно знакомой, все происходит с учетом событий, соответствующий код выполнен в соответствии с различными событиями. Объяснить немногоEventSource
Я считаю, что со свойствами и методами каждый может с удовольствием использовать его.
EventSource
Есть три события по умолчанию, а именно:
-
open
: Вызывается при открытии соединения. -
message
: Вызывается при получении сообщения без атрибута события. -
error
: вызывается при возникновении ошибки.
Два свойства только для чтения:
-
readyState
: представляет состояние подключения. Возможные значения: ПОДКЛЮЧЕНИЕ (0), ОТКРЫТО (1) или ЗАКРЫТО (2). -
url
: представляет URL-адрес соединения.
Метод:
-
close
: Закрыть соединение после звонка (то есть упомянутого выше).
Более подробное объяснение можно найти вMDNДокументация
резюме
Это конец краткого введения в SSE сервера.Как видите, SSE относительно прост в разработке, а стоимость доступа очень низкая. Но это не значит, что WebSocket — это плохо, говорить о бизнесе в отрыве от реального сценария — это хулиганство. Кроме того, приведенный выше код является лишь демонстрацией и может быть дополнительно оптимизирован. Например, чтобы уменьшить нагрузку на сервер, можно установить механизм для целенаправленного отключения и повторного подключения, и вы можете реализовать его самостоятельно.
Соответствующий код был удаленGithub, добро пожаловать на чтение.
Спасибо всем судьям за то, что увидели это, легче сказать, чем сделать, надеюсь, эта статья будет вам полезна~ Спасибо!
использованная литература
20 строк кода для написания службы отправки данных