Nega UDP paketlar yo'qolib qoladi?
Networking bo'yicha bilmi borlar bilan gaplashsangiz TCP vs UDP haqida gapirishadi. Ular UDP haqida gapirishgan paytda uni "reliable" emas deyishadi. Ammo nega unday deyayotganini so'rasangiz javob yo'q. Bilganlar esa nega packet tushib qolishini aytib bera olishmaydi.
1. Tasavvur qiling siz juda ko'p UDP paketlarni bir manzildan ikkinchisiga yuborayabsiz. Har bir UDP socket'da socket sender buffer degan qismi mavjud. Ya'ni paketlar yuborilishdan oldin ayanan o'sha yerga jamlanadi (buffer bu bir vaqtinchalik xotira). Linux kernel bu paketlarni o'qish va yuborish bilan shug'ullanadi. Agar kompyuteringiz yoki serveringizdagi Network Card tezligi past bo'lsa, dasturni tezligiga tusha olmasligi va yuborish jarayonda paketlar yo'qolishi mumkin. Bu qanchalik odatiyligini bilmayman, ammo bunday holatlar bo'lgan.
2. UDP paketlarni internetga yubordingiz (kompyuteringizdan chiqib ketdi hammasi 100% muvaffaqiyatli), u yo'lda, bir router/switch'dan ikkinchisiga o'tish jarayonida yo'qolishi mumkin. Bu yerda router/switch queue limit tugab qolishi mumkin. TCP va UDP paket kelganda TCP paketlarni himoya qilish orqali UDP paketlarni tashlab yuborishi mumkin. Va yana ko'p boshqa sabablar ham bor.
3. Birinchi va ikkinchi bosqich muvaffaqiyatli bo'ldi ham deylik. Ya'ni yo'l yurib, barcha paketlar ohirgi nuqtaga yetib keldi. Endi sizni dasturingiz paketlarni kutib turibdi. Hammasi juda zo'r. Guess what, paketlar qayerga kelib tushadi? Yes, yana o'sha socket sender buffer ga kelishadi. U buffer hajmi qanchalik katta? U barcha paketlarni sig'dira oladimi? Bu savolga to'liqroq bu yerda o'qib ko'ring [link]. Meni kompyuterimda bunday ekan
# Macbook'da
# socket max buffer size
➜ ~ sysctl kern.ipc.maxsockbuf
kern.ipc.maxsockbuf: 8388608
# send/receive buffer size
➜ ~ sysctl net.inet.udp.recvspace
net.inet.udp.recvspace: 786896
Bu raqamlar byte emas, balkim page degani (bu haqda ko'proq keyinroq yozaman). Meni xolatimda har bir page 16KB degani ekan. Demak mendagi max buffer size 8388608 => 8MB ga to'g'ri kelar ekan (8 388 608 / 1024 / 1024 = 8). Standart receive buffer kengligi esa 0.75MB ekan. Demak agar menga katta miqdorda paketlar kirib kelsa va buffer to'lib qolsa 8MB dan buyog'ini tashlab yuborar ekan. Bu yerda application tezligiga ham bog'liq paketlarni saqlab qolish yoki tashlab yuborilishi. Shu paytgacha kompyuterim qancha paketlarni tashlab yuborgan ekan deb qizdim va natija shunday:
➜ ~ netstat -s -p udp
udp:
141545183 datagrams received
0 with incomplete header
0 with bad data length field
0 with bad checksum
1048 with no checksum
45648 checksummed in software
31046 datagrams (20030730 bytes) over IPv4
14602 datagrams (3553616 bytes) over IPv6
159392 dropped due to no socket
101590 broadcast/multicast datagrams undelivered
0 IPv6 multicast datagram undelivered
0 time multicast source filter matched
9244 dropped due to full socket buffers
0 not for hashed pcb
141274957 delivered
38752867 datagrams output
415727 checksummed in software
8977 datagrams (3238427 bytes) over IPv4
406750 datagrams (117958647 bytes) over IPv6
40 open UDP sockets
Facebook'da ishlaydigan do'stim bir hikoya aytib bergandi. Facebook’ning “Live” funksiyasi ham UDP'dan foydalanar ekan (RTCP/UDP). 2018-yilda ular serverda recv buffer limiti to‘lganida, Linux kernel UDP paketlarni tashlab yuborish muammosiga duch kelishgan ekan. Monitoringda bu drop’larni faqat server metrikalari orqali ko‘rishganda, foydalanuvchi tarafida video ‘pause’ bo'lishi kuzatilgan ekan. Muammoni sababi
net.core.rmem_max juda past bo'lgan ekan. "Live session burst" ya'ni ko'p foydalanuvchilar live ga kirganida socket buffer to'lib ketgan. Yechim sifatida Facebook SRE jamoasi "dynamic UDP buffer autotuning" qo'shishganini aytgandi. Ya'ni kernel sysctl parametrlarini runtime’da trafikga qarab oshirish mumkinligini topishgan. Metrikalarni esa Prometheus bilan qattiq kuzatishgan ekan.Katta tizmlarda ishlasangiz har bir qarich siz uchun muhimligini sezib borar ekansiz.