Geri basınç uygulayarak uygulamanızın WebSocket mesajlarına boğulmasını veya WebSocket sunucusunun mesajlarla dolmasını önleyin.
Arka plan
WebSocket API, WebSocket protokolü için bir JavaScript arayüzü sağlar. Bu arayüz, kullanıcının tarayıcısı ile bir sunucu arasında iki yönlü etkileşimli bir iletişim oturumu açmayı mümkün kılar. Bu API ile, sunucuya yanıt için yoklama yapmadan sunucuya mesaj gönderebilir ve etkinliğe dayalı yanıtlar alabilirsiniz.
Streams API
Streams API, JavaScript'in ağ üzerinden alınan veri parçaları akışlarına programatik olarak erişmesini ve bunları istediği şekilde işlemesini sağlar. Akışlar bağlamında önemli bir kavram geri basınçtır. Bu, tek bir akışın veya bir boru zincirinin okuma ya da yazma hızını düzenlediği süreçtir. Akışın kendisi veya ardışık düzen zincirindeki sonraki bir akış hala meşgul olduğunda ve henüz daha fazla parça kabul etmeye hazır olmadığında, zincir boyunca geriye doğru bir sinyal göndererek teslimatı uygun şekilde yavaşlatır.
Mevcut WebSocket API'siyle ilgili sorun
Alınan mesajlara geri basınç uygulamak mümkün değildir.
Mevcut WebSocket API'sinde, bir mesaja tepki verme işlemi WebSocket.onmessage
içinde gerçekleşir. Bu, sunucudan bir mesaj alındığında çağrılan bir EventHandler
'dir.
Yeni bir mesaj alındığında yoğun veri işleme işlemleri yapması gereken bir uygulamanız olduğunu varsayalım.
Akışı büyük olasılıkla aşağıdaki koda benzer şekilde ayarlarsınız ve await
process()
çağrısının sonucunu aldığınız için sorun olmaz, değil mi?
// A heavy data crunching operation.
const process = async (data) => {
return new Promise((resolve) => {
window.setTimeout(() => {
console.log('WebSocket message processed:', data);
return resolve('done');
}, 1000);
});
};
webSocket.onmessage = async (event) => {
const data = event.data;
// Await the result of the processing step in the message handler.
await process(data);
};
Yanlış! Mevcut WebSocket API'sindeki sorun, geri basınç uygulamanın mümkün olmamasıdır.
Mesajlar, process()
yönteminin işleyebileceğinden daha hızlı geldiğinde oluşturma işlemi, bu mesajları arabelleğe alarak belleği doldurur, %100 CPU kullanımı nedeniyle yanıt vermez veya her ikisi de gerçekleşir.
Gönderilen mesajlara geri basınç uygulamak ergonomik değildir
Gönderilen iletilere geri basınç uygulamak mümkündür ancak bu işlem, verimsiz ve ergonomik olmayan WebSocket.bufferedAmount
özelliğinin yoklanmasını gerektirir.
Bu salt okunur özellik, WebSocket.send()
çağrıları kullanılarak sıraya alınmış ancak henüz ağa iletilmemiş veri baytı sayısını döndürür.
Bu değer, sıraya alınan tüm veriler gönderildikten sonra sıfıra sıfırlanır.
Ancak WebSocket.send()
'yı çağırmaya devam ederseniz
değer artmaya devam eder.
WebSocketStream API nedir?
WebSocketStream API, akışları WebSocket API ile entegre ederek var olmayan veya ergonomik olmayan geri basınç sorununu ele alır. Bu, geri basıncın ek bir maliyet olmadan "ücretsiz" olarak uygulanabileceği anlamına gelir.
WebSocketStream API için önerilen kullanım alanları
Bu API'yi kullanabilen sitelere örnek olarak şunlar verilebilir:
- Etkileşimi koruması gereken yüksek bant genişliğine sahip WebSocket uygulamaları (özellikle video ve ekran paylaşımı).
- Benzer şekilde, tarayıcıda çok fazla veri oluşturan ve sunucuya yüklenmesi gereken video çekimi ve diğer uygulamalar. Geri basınç sayesinde istemci, verileri bellekte biriktirmek yerine üretmeyi durdurabilir.
Mevcut durum
Step | Durum |
---|---|
1. Açıklayıcı oluşturma | Tamamlandı |
2. Spesifikasyonun ilk taslağını oluşturma | Devam ediyor |
3. Geri bildirim toplama ve tasarım üzerinde yineleme yapma | Devam ediyor |
4. Kaynak denemesi | Tamamlandı |
5. Başlat | Başlatılmadı |
WebSocketStream API'yi kullanma
WebSocketStream API, söz tabanlıdır. Bu nedenle, modern JavaScript dünyasında bu API ile çalışmak doğal bir deneyim sunar.
Öncelikle yeni bir WebSocketStream
oluşturup WebSocket sunucusunun URL'sini ileterek işe başlarsınız.
Ardından, bağlantının opened
olmasını beklersiniz. Bu işlem sonucunda ReadableStream
ve/veya WritableStream
elde edilir.
ReadableStream.getReader()
yöntemini çağırarak sonunda bir
ReadableStreamDefaultReader
elde edersiniz. Bu nesneden, akış tamamlanana kadar (yani {value: undefined, done: true}
biçiminde bir nesne döndürene kadar) read()
verilerini alabilirsiniz.
Buna göre, WritableStream.getWriter()
yöntemini çağırarak sonunda WritableStreamDefaultWriter
elde edersiniz. Ardından, write()
verilerini kullanabilirsiniz.
const wss = new WebSocketStream(WSS_URL);
const {readable, writable} = await wss.opened;
const reader = readable.getReader();
const writer = writable.getWriter();
while (true) {
const {value, done} = await reader.read();
if (done) {
break;
}
const result = await process(value);
await writer.write(result);
}
Geri basınç
Vaat edilen geri basınç özelliği ne zaman kullanıma sunulacak?
Bu özelliği "ücretsiz" olarak kullanabilirsiniz. Başka bir işlem yapmanız gerekmez.
process()
ek süre alırsa bir sonraki mesaj yalnızca kanal hazır olduğunda tüketilir.
Benzer şekilde, WritableStreamDefaultWriter.write()
adımı yalnızca güvenliyse devam eder.
Gelişmiş örnekler
WebSocketStream'in ikinci bağımsız değişkeni, gelecekteki genişletmeye olanak tanıyan bir seçenek paketidir.
Tek seçenek protocols
'dır. Bu seçenek, WebSocket oluşturucusunun ikinci bağımsız değişkeni ile aynı şekilde çalışır:
const chatWSS = new WebSocketStream(CHAT_URL, {protocols: ['chat', 'chatv2']});
const {protocol} = await chatWSS.opened;
Seçilen protocol
ve olası extensions
, WebSocketStream.opened
sözüyle kullanılabilen sözlüğün bir parçasıdır.
Bağlantı başarısız olursa bu durum önemli olmadığından canlı bağlantıyla ilgili tüm bilgiler bu söz tarafından sağlanır.
const {readable, writable, protocol, extensions} = await chatWSS.opened;
Kapatılan WebSocketStream bağlantısı hakkında bilgi
WebSocket API'deki WebSocket.onclose
ve WebSocket.onerror
etkinliklerinden elde edilen bilgiler artık WebSocketStream.closed
sözü aracılığıyla kullanılabilir.
Temiz olmayan bir kapatma durumunda söz reddedilir, aksi takdirde sunucu tarafından gönderilen kod ve nedene göre çözümlenir.
Olası tüm durum kodları ve anlamları, CloseEvent
durum kodları listesinde açıklanmıştır.
const {code, reason} = await chatWSS.closed;
WebSocketStream bağlantısını kapatma
WebSocketStream, AbortController
ile kapatılabilir.
Bu nedenle, AbortSignal
öğesini WebSocketStream
oluşturucusuna iletin. AbortController.abort()
yalnızca el sıkışmadan önce çalışır, sonrasında çalışmaz.
const controller = new AbortController();
const wss = new WebSocketStream(URL, {signal: controller.signal});
setTimeout(() => controller.abort(), 1000);
Alternatif olarak WebSocketStream.close()
yöntemini de kullanabilirsiniz ancak bu yöntemin asıl amacı, sunucuya gönderilen kodu ve nedeni belirtmeye izin vermektir.
wss.close({closeCode: 4000, reason: 'Game over'});
Progresif geliştirme ve birlikte çalışabilirlik
Chrome şu anda WebSocketStream API'yi uygulayan tek tarayıcıdır.
Klasik WebSocket API ile birlikte çalışabilirlik için,
alınan mesajlara geri basınç uygulamak mümkün değildir.
Gönderilen iletilere geri basınç uygulamak mümkündür ancak bu işlem, verimsiz ve ergonomik olmayan WebSocket.bufferedAmount
özelliğinin yoklanmasını gerektirir.
Özellik algılama
WebSocketStream API'nin desteklenip desteklenmediğini kontrol etmek için şunu kullanın:
if ('WebSocketStream' in window) {
// `WebSocketStream` is supported!
}
Demo
Desteklenen tarayıcılarda, yerleştirilmiş iFrame'de veya doğrudan Glitch'te WebSocketStream API'nin nasıl çalıştığını görebilirsiniz.
Geri bildirim
Chrome Ekibi, WebSocketStream API ile ilgili deneyimlerinizi öğrenmek istiyor.
API tasarımı hakkında bilgi verin.
API'nin beklentilerinizi karşılamayan bir özelliği var mı? Yoksa fikrinizi uygulamak için eksik yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var? İlgili GitHub deposunda bir spesifikasyon sorunu bildirin veya düşüncelerinizi mevcut bir soruna ekleyin.
Uygulamayla ilgili sorun bildirme
Chrome'un uygulamasında bir hata mı buldunuz?
Yoksa uygulama, spesifikasyondan farklı mı?
new.crbug.com adresinden hata bildirin.
Mümkün olduğunca fazla ayrıntı eklediğinizden, hatayı yeniden oluşturmak için basit talimatlar verdiğinizden ve Bileşenler kutusuna Blink>Network>WebSockets
girdiğinizden emin olun.
API'ye desteğinizi gösterme
WebSocketStream API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı satıcılarına bu özellikleri desteklemenin ne kadar önemli olduğunu gösterir.
#WebSocketStream
hashtag'ini kullanarak @ChromiumDev'e tweet gönderin
ve nerede, nasıl kullandığınızı bize bildirin.
Faydalı bağlantılar
- Herkese açık açıklama
- WebSocketStream API Demosu | WebSocketStream API Demosu kaynağı
- İzleme hatası
- ChromeStatus.com girişi
- Blink Bileşeni:
Blink>Network>WebSockets
Teşekkür
WebSocketStream API, Adam Rice ve Yutaka Hirano tarafından uygulanmıştır.