Teslimat garantileri
Mesaj sıralama
Socket.IO, hangi düşük düzey taşıma kullanılırsa kullanılsın (HTTP uzun bekletmeden WebSocket'e geçiş sırasında bile) mesaj sıralamasını garanti etmektedir.
Bu, aşağıdakiler sayesinde gerçekleştirilir:
- Temel TCP bağlantısının sağladığı garantiler
Yükseltme mekanizmasının
dikkatli tasarımı
Örnek:
socket.emit("event1");
socket.emit("event2");
socket.emit("event3");
Yukarıdaki örnekte, olaylar her zaman diğer taraf tarafından aynı sırayla alınacaktır (gerçekten var oldukları sürece, aşağıda
bakın).
Mesaj varışı
En fazla bir kez
Varsayılan olarak, Socket.IO, teslimat için en fazla bir kez garantisi sağlar:
- Bir olay gönderilirken bağlantı koparsa, diğer tarafın bunu alıp almadığına dair bir garanti yoktur ve yeniden bağlantı sağlandığında tekrar deneyemiyecektir.
- Bağlantısı kopmuş bir istemci,
yeniden bağlantı sağlanana kadar olayları tamponlayacaktır
(ancak önceki nokta hala geçerlidir). - Sunucuda böyle bir tampon yoktur, bu da demektir ki, bağlantısı kopmuş bir istemcinin kaçırdığı herhangi bir olay, yeniden bağlantı sağlandığında o istemciye iletilmeyecektir.
Şu anda, ek teslimat garantileri uygulamanızda uygulanmalıdır.
En az bir kez
İstemciden sunucuya
İstemci tarafında, onaylar ve zaman aşımı
ile en az bir kez garantisi elde edebilirsiniz:
function emit(socket, event, arg) {
socket.timeout(2000).emit(event, arg, (err) => {
if (err) {
// Sunucudan onay yok, yeniden deneyelim.
emit(socket, event, arg);
}
});
}
emit(socket, "foo", "bar");
Yukarıdaki örnekte, istemci belirli bir gecikmeden sonra olayı göndermeyi yeniden deneyecektir, bu nedenle sunucu aynı olayı birkaç kez alabilir.
Bu durumda, kullanıcı sekmesini yenilerse herhangi bir bekleyen olay kaybolacaktır.
Sunucudan istemciye
Sunucu tarafından gönderilen olaylar için ek teslimat garantileri şu şekilde uygulanabilir:
- Her olaya benzersiz bir kimlik atama
- Olayları bir veritabanında saklama
- İstemci tarafında son alınan olayın ofsetini saklama ve yeniden bağlantı sağlandığında bunu gönderme
Örnek:
İstemci
const socket = io({
auth: {
offset: undefined
}
});
socket.on("my-event", ({ id, data }) => {
// Verilerin üzerinde bir şey yap ve sonra ofseti güncelle
socket.auth.offset = id;
});
Sunucu
io.on("connection", async (socket) => {
const offset = socket.handshake.auth.offset;
if (offset) {
// Bu bir yeniden bağlantı
for (const event of await fetchMissedEventsFromDatabase(offset)) {
socket.emit("my-event", event);
}
} else {
// Bu ilk bağlantı
}
});
setInterval(async () => {
const event = {
id: generateUniqueId(),
data: new Date().toISOString()
}
await persistEventToDatabase(event);
io.emit("my-event", event);
}, 1000);
Eksik yöntemlerin (fetchMissedEventsFromDatabase()
, generateUniqueId()
ve persistEventToDatabase()
) uygulanması veritabanına özgüdür ve okuyucuya bir alıştırma olarak bırakılmıştır.
Referanslar
socket.auth
(istemci)socket.handshake
(sunucu)