এই পর্বে যা শিখবেন
- একটি অনুরোধ DNS থেকে উত্তরের প্রথম byte পর্যন্ত কোন কোন ধাপ পার হয়, প্রতিটিতে কত RTT — আর হাতে time to first byte হিসাব করা
- DNS-এর নাম খোঁজার পথ, TTL আর caching; round-robin, GeoDNS আর anycast দিয়ে ভিড় ভাগ, আর failover-এর প্রয়োজন থেকে TTL বাছাই
- TCP, TLS 1.2/1.3 আর QUIC-এর handshake-খরচ; keep-alive, connection pool, slow start, ephemeral port আর TIME_WAIT-এর নকশাগত প্রভাব
- HTTP/1.1, HTTP/2, HTTP/3 আর UDP-কে design choice হিসেবে তুলনা — কোন কাজে কোনটি, আর কেন
- আলোর গতি থেকে দুই শহরের সর্বনিম্ন RTT বের করা, region আর CDN-এর যুক্তি, আর VPC, NAT/CGNAT ও IPv6-এর জরুরি কথা
১ · নকশাকারের চোখে network — প্রতিটি round trip-এ সময়, প্রতিটি connection-এ খরচ
একটি কাল্পনিক অনলাইন বাজারের দল নতুন অ্যাপ চালু করল। সার্ভার রাখা হলো US East-এর একটি cloud region-এ, কারণ সেখানে খরচ কম মনে হয়েছিল। সার্ভারের dashboard বলছে, প্রতিটি অনুরোধে সার্ভারের কাজ মাত্র ২০ ms. অথচ ঢাকার ব্যবহারকারীরা বলছেন, অ্যাপ খুললে প্রথম পাতা আসতে প্রায় এক সেকেন্ড লাগে।
দুই পক্ষই ঠিক। ২০ ms সার্ভারের ভেতরের কাজ; বাকি সময় গেছে পথে। ঢাকা থেকে US East-এর একবার যাওয়া-আসা (round trip) কয়েকশো মিলিসেকেন্ড, আর নতুন HTTPS অনুরোধ প্রথম উত্তরের আগে কয়েকবার যাওয়া-আসা করে: নাম খোঁজা, connection খোলা, চাবি ঠিক করা, তারপর আসল অনুরোধ। এই পর্বে শিখবেন এগুলো গুনতে, আর কোন সিদ্ধান্ত এগুলো কমায়।
- প্রতিটি round trip সময় নেয়। একটি অনুরোধের network-সময় ≈ (কতবার যাওয়া-আসা) × RTT. RTT কমাতে হলে সার্ভারকে ব্যবহারকারীর কাছে আনতে হয়; যাওয়া-আসার সংখ্যা কমাতে হলে protocol আর API-র নকশা বদলাতে হয়।
- প্রতিটি connection resource নেয়। Handshake-এ CPU, খোলা connection-এ memory, file descriptor আর port, আর load balancer ও NAT-এর টেবিলে একটি করে ঘর। তাই connection কম খুলুন, বেশি দিন ব্যবহার করুন।
ফোনে মুদি দোকানে অর্ডার দেওয়ার কথা ভাবুন: আগে নম্বর খোঁজা (DNS), তারপর “হ্যালো, শুনতে পাচ্ছেন?” (TCP), তারপর দুই পক্ষের পরিচয় নিশ্চিত করা (TLS), শেষে আসল কথা — “এক কেজি চাল” (HTTP). প্রতিটি জিনিসের জন্য আলাদা ফোন করলে প্রতিবার এই আনুষ্ঠানিকতা; এক কলেই দশটি জিনিস বললে হাত মেলানো একবারই।
নিচের ছবিতে একটি অনুরোধের পথ: নাম থেকে ঠিকানা, কাছের CDN edge-এর সাথে connection, আর edge-এ না থাকলে দূরের origin সার্ভার। সংখ্যাগুলো ধরে নেওয়া, গোল করা।
একটি অনুরোধের পথ — ব্যবহারকারী থেকে origin পর্যন্ত
Client → DNS resolver → CDN edge → origin region (assumed, rounded RTTs)
Computer Networks কোর্স প্রতিটি protocol বাইট ধরে শেখায়; এই পর্ব নকশাকারের সারাংশ:
| নকশার প্রশ্ন | এই পর্বে | গভীরে (Computer Networks) |
|---|---|---|
| ব্যবহারকারী কোন সার্ভারে যাবেন? | DNS, TTL, GeoDNS, anycast (অংশ ২–৩) | DNS, BGP |
| প্রথম byte আসতে কত round trip? | TCP, TLS, QUIC-এর handshake (অংশ ৪) | TCP সংযোগ, TLS আর HTTPS |
| Connection কতক্ষণ, কতগুলো? | keep-alive, pool, port, TIME_WAIT (অংশ ৫) | Congestion control |
| কোন HTTP সংস্করণ? | HTTP/1.1, 2, 3 (অংশ ৬) | HTTP/2 আর HTTP/3, QUIC |
| TCP না UDP? | অংশ ৭ | UDP, Transport layer |
| সার্ভার কোথায় রাখব? | আলোর গতি, region, CDN (অংশ ৮) | Delay আর throughput |
| ভেতরের network কেমন হবে? | VPC, NAT, CGNAT, IPv6 (অংশ ৯) | Cloud networking, NAT |
২ · DNS নকশার চোখে — নাম খোঁজার পথ, TTL আর caching
ব্যবহারকারী লেখেন shop.example.com, কিন্তু connection খুলতে লাগে IP ঠিকানা। নাম থেকে ঠিকানা বের করে DNS. নকশাকারের কাছে এটি তিন কারণে জরুরি: প্রথম অনুরোধের সময়ে যোগ হয়, ঠিক করে ব্যবহারকারী কোন সার্ভারে যাবেন, আর বসে গেলে সুস্থ সার্ভারও কেউ খুঁজে পায় না।
- যন্ত্রের নিজের cache: কিছুক্ষণ আগে খোঁজা হলে উত্তর ব্রাউজার বা OS-এ — প্রায় ০ ms. OS-এর এই ছোট অংশ stub resolver নিজে খোঁজে না, প্রশ্নটি পরের ধাপে পাঠায়।
- Recursive resolver: সাধারণত ISP-র বা কোনো public DNS সেবার সার্ভার। তার cache-এ থাকলে খরচ একটি ছোট round trip, প্রায়ই কয়েক থেকে কয়েক দশ ms.
- Root → TLD → authoritative: resolver-এর cache-এ না থাকলে সে ধাপে ধাপে খোঁজে, আর শেষে domain-এর authoritative server দেয় আসল উত্তর। Root আর TLD-এর উত্তর অনেকক্ষণ cache-এ থাকে, তাই miss মানে প্রায়ই শুধু authoritative পর্যন্ত এক-দুটি যাত্রা — দূরে হলে কয়েক দশ থেকে শতাধিক ms.
পাড়ার মুদি দোকানদারের খাতা ভাবুন। কারও ঠিকানা জানতে চাইলে খাতায় থাকলে সাথে সাথে বলেন — cache hit. না থাকলে ওয়ার্ড অফিসে খোঁজ নিয়ে খাতায় টুকে রাখেন, পাশে লেখেন “এক সপ্তাহ ভরসা”। এই মেয়াদটিই TTL. মেয়াদের মধ্যে কেউ বাসা বদলালেও দোকানদার পুরোনো ঠিকানাই বলবেন — DNS failover-এর জটিলতা এখান থেকেই (অংশ ৩)।
TTL ঠিক করেন domain-এর মালিক, authoritative-এ record-এর সাথে; resolver উত্তরটি সেই মেয়াদ পর্যন্ত রাখে। একটি কাল্পনিক উত্তর — দুটি IP, প্রতিটির TTL ৩০০ সেকেন্ড:
$ dig +noall +answer shop.example.com A
shop.example.com. 300 IN A 203.0.113.10
shop.example.com. 300 IN A 203.0.113.11দ্বিতীয় কলাম resolver-এর কাছে বাকি মেয়াদ, সেকেন্ডে; একটু পরে জিজ্ঞেস করলে কমবে। নকশায় প্রভাব:
- নতুন hostname মানে নতুন খরচ: প্রতিটি আলাদা নামে আলাদা DNS খোঁজা আর আলাদা connection. পাতায় দশটি domain থেকে জিনিস আনলে প্রথম লোডে দশবার এই খরচ;
preconnectদিয়ে আগেভাগে সারা যায়, তবে সবচেয়ে ভালো নামের সংখ্যা কম রাখা। - “নেই” উত্তরও cache হয়: এখনো না-বানানো নাম কেউ খুঁজলে “এমন নাম নেই” উত্তরটিও কিছুক্ষণ থাকে — negative caching (RFC 2308).
- DNS নিজেই একটি dependency: DNS সেবা বসে গেলে cache ফুরানোর পর কেউ আপনার সার্ভার খুঁজে পান না — তাই নির্ভরযোগ্য, ছড়ানো DNS সেবা availability-র হিসাবের অংশ (পর্ব ৫; ভাবনার প্রশ্ন ২)।
১৯৮৩ সালে Paul Mockapetris DNS-এর নকশা প্রকাশ করেন (RFC 882 ও 883); আজকের মূল মান RFC 1034 আর 1035 আসে ১৯৮৭ সালে। তার আগে ARPANET-এর সব নাম-ঠিকানা থাকত একটি কেন্দ্রীয় ফাইলে (HOSTS.TXT), যা যন্ত্র বাড়তেই অচল হয়ে পড়ে।
Zone, delegation আর record-এর ধরন: Computer Networks কোর্সের DNS পর্ব।
৩ · DNS দিয়ে ভিড় ভাগ আর failover — round-robin, GeoDNS, anycast আর TTL-এর দর-কষাকষি
DNS কোন ঠিকানা বলবে, তা বেছে নিয়ে ব্যবহারকারীদের ভাগও করতে পারে। তিনটি প্রচলিত কৌশল:
Round-robin DNS
একটি নামের জন্য কয়েকটি IP, যেমন উপরের উদাহরণে। সরল, কিন্তু সাধারণ DNS জানে না কোন সার্ভার বিকল, আর ভাগ অসমান। মোটা দাগের ভাগে চলে; সার্ভারগুলোর মধ্যে ভাগ load balancer-এর কাজ (পর্ব ১৪)।
সরল, health-অন্ধGeoDNS / latency-based routing
Authoritative দেখে প্রশ্নটি কোন এলাকা থেকে এল, আর কাছের বা দ্রুততম region-এর IP দেয়; অনেক managed DNS সেবা health check করে বিকল region সরিয়েও দেয়। ব্যবহারকারী দূরের public resolver ব্যবহার করলে এলাকা ভুল ধরা পড়তে পারে; তাই কিছু resolver ব্যবহারকারীর IP-র একটি অংশ পাঠায় — EDNS Client Subnet (RFC 7871), গোপনীয়তার দাম দিয়ে।
কাছের regionAnycast
এখানে কাজ করে routing. একই IP অনেক জায়গা থেকে BGP দিয়ে ঘোষণা করা হয়, আর router-গুলো প্রতিটি packet পাঠায় routing-এর হিসাবে কাছের জায়গায়। একটি জায়গা বিকল হলে ঘোষণা তুলে নেওয়া হয়, traffic যায় পরের জায়গায় — TTL-এর অপেক্ষা ছাড়াই। Root DNS, বড় public resolver আর CDN এভাবে চলে।
এক IP, বহু জায়গাএকটি কাল্পনিক পিৎজা চেইনের হটলাইন নম্বর সারা দেশে একটিই: ঢাকা থেকে করলে কল যায় ঢাকার শাখায়, সিলেট থেকে করলে সিলেটের শাখায়, একটি শাখা বন্ধ থাকলে পরের কাছের শাখায়। Anycast ঠিক এমন — তবে “কাছের” মানে network-পথের হিসাবে, কিলোমিটারে নয়।
ভেতরের কৌশল: BGP আর Web cache আর CDN পর্বে; CDN-এর নকশা এই কোর্সের পর্ব ১৭-এ।
TTL বনাম failover-এর গতি
DNS দিয়ে failover সরল শোনায়: region ক বসে গেলে record-এ region খ-এর IP বসান। কিন্তু যে resolver পুরোনো উত্তর টুকে রেখেছে, সে TTL ফুরানো পর্যন্ত পুরোনো IP-ই দেবে — DNS-এ বদল “ঠেলে পাঠানো” হয় না। তাই:
গড় কেমন? Resolver-দের cache এলোমেলো সময়ে, সমানভাবে ছড়িয়ে ভরা হলে বদলের মুহূর্তে প্রতিটির বাকি মেয়াদ ০ থেকে TTL-এর মধ্যে uniform. বদলের τ সেকেন্ড পরে শুধু যাদের বাকি মেয়াদ τ-এর বেশি ছিল, তারাই পুরোনো IP দিচ্ছে:
যেমন TTL ৩০০ সেকেন্ডে বদলের এক মিনিট পরে প্রায় ৮০% resolver পুরোনো ঠিকানায়, আড়াই মিনিটে ৫০%, পাঁচ মিনিটে ০% (আদর্শ মডেল)। ধরা আর বদলাতে মোট ৪০ সেকেন্ড ধরে:
| TTL | সর্বোচ্চ failover | গড় | Authoritative-এ query (TTL ৩০০-এর তুলনায়) |
|---|---|---|---|
| ৩০ সেকেন্ড | ৭০ সেকেন্ড | ৫৫ সেকেন্ড | প্রায় ১০ গুণ |
| ৬০ সেকেন্ড | ১০০ সেকেন্ড | ৭০ সেকেন্ড | প্রায় ৫ গুণ |
| ৩০০ সেকেন্ড | ৩৪০ সেকেন্ড | ১৯০ সেকেন্ড | ১ গুণ |
| ৩,৬০০ সেকেন্ড | ৩,৬৪০ সেকেন্ড (প্রায় ১ ঘণ্টা) | ১,৮৪০ সেকেন্ড (প্রায় ৩১ মিনিট) | প্রায় ১২ ভাগের ১ ভাগ |
| region ক বিকল হওয়ার পর | |
| নতুন region-এ পাঠাচ্ছে |
- t = ০: region ক বিকল।
api.example.com-এর IP 203.0.113.10, TTL ৩০০ সেকেন্ড। তিনটি resolver উত্তরটি এনেছিল ২৫০, ১০০ আর ১০ সেকেন্ড আগে, তাই মেয়াদ বাকি ৫০, ২০০ আর ২৯০ সেকেন্ড। সবার ব্যবহারকারী এখন বিকল region-এ যাচ্ছেন। - t = ৪০: DNS বদলাল, কিন্তু কেউ জানে না। Health check ৩০ সেকেন্ডে বিকলতা ধরল (প্রতি ১০ সেকেন্ডে পরীক্ষা, পরপর ৩ বার ব্যর্থ), পরের ১০ সেকেন্ডে record-এ region খ-এর IP বসল। Resolver-রা আবার জিজ্ঞেস করবে শুধু মেয়াদ ফুরালে।
- t = ৫০: R1-এর মেয়াদ শেষ। R1 আবার জিজ্ঞেস করে নতুন IP পেল, আর নতুন করে ৩০০ সেকেন্ডের জন্য রাখল — তিনজনের একজন এখন region খ-এ।
- t = ২০০: R2-ও নতুন। R2-এর পেছনে একটি বড় ISP-র অনেক ব্যবহারকারী থাকলে তাঁরা সবাই তিন মিনিটের বেশি বিকল region-এ আটকে ছিলেন।
- t = ২৯০: তিনজনই নতুন। তবে এটিই সবচেয়ে খারাপ নয়: কোনো resolver-এর মেয়াদ ৩৯ সেকেন্ডে ফুরালে — বিকলতার পরে, DNS বদলের ঠিক আগে — সে আবার পুরোনো IP-ই পেত, আর ৩৩৯ সেকেন্ড পর্যন্ত রাখত।
- সারসংক্ষেপ: ধরা পড়া + বদল + TTL. TTL ৩০০-এ সবচেয়ে খারাপ ৪০ + ৩০০ = ৩৪০ সেকেন্ড; TTL ৬০-এ ১০০ সেকেন্ড, তবে authoritative-এ প্রশ্ন প্রায় ৫ গুণ। আর হিসাবটি ধরে নেয় সবাই TTL মানে — যা সবসময় সত্য নয়।
“সবাই TTL মানবে” — ধরে নেবেন না। কিছু resolver খুব ছোট TTL নিজের ন্যূনতম মানে বাড়িয়ে নেয়, কিছু client বা runtime নিজের মতো আরও বেশি সময় cache রাখে (সংস্করণভেদে আলাদা)। সবচেয়ে বড় ফাঁদ খোলা connection: keep-alive বা pool-এর connection আর DNS জিজ্ঞেস করে না, তাই আধা-বিকল, ধীর region-এ টিকে থাকে — pool-এ connection-এর সর্বোচ্চ বয়স রাখুন (অংশ ৫)। আর পরিকল্পিত migration-এর আগে TTL কমান, অন্তত পুরোনো TTL-এর সমান সময় আগে।
দ্রুত failover লাগলে শুধু DNS নয় — স্থির anycast IP বা global load balancer, যা health check দেখে DNS না বদলেই region বদলায়। পূর্ণ নকশা পর্ব ৫১-এ (Failover আর disaster recovery).
৪ · TCP, TLS আর QUIC-এর হাত মেলানো — প্রথম byte আসতে কত RTT
ঠিকানা পাওয়া গেল, এবার connection. TCP ডেটা পাঠানোর আগে three-way handshake করে: client পাঠায় SYN, সার্ভার SYN-ACK, client ACK. তৃতীয় বার্তার সাথেই client ডেটা পাঠাতে পারে, তাই খরচ ১ RTT.
তারপর TLS — চাবি ঠিক করা আর সার্ভারের certificate যাচাই। TLS 1.2-এর পূর্ণ handshake-এ ২ RTT; TLS 1.3 (২০১৮) প্রথম বার্তাতেই চাবির অংশ পাঠিয়ে সেটি ১ RTT-এ নামিয়েছে। পুরোনো সংযোগের ticket দেখিয়ে client দ্রুত ফিরতে পারে (session resumption), আর চাইলে প্রথম বার্তার সাথেই অনুরোধ পাঠাতে পারে — 0-RTT. HTTP/3-এর নিচের QUIC দুই handshake একসাথে করে: নতুন connection ১ RTT-এ, ফিরে আসা client 0-RTT-এ।
| পদ্ধতি | Handshake | অনুরোধ-উত্তর | প্রথম byte পর্যন্ত মোট |
|---|---|---|---|
| TCP + TLS 1.2 (পূর্ণ) | ১ + ২ RTT | ১ RTT | ৪ RTT |
| TCP + TLS 1.3 | ১ + ১ RTT | ১ RTT | ৩ RTT |
| TCP + TLS 1.3, 0-RTT | ১ + ০ RTT | ১ RTT | ২ RTT |
| QUIC, নতুন connection | ১ RTT | ১ RTT | ২ RTT |
| QUIC, 0-RTT | ০ | ১ RTT | ১ RTT |
| আগে থেকে খোলা connection | ০ | ১ RTT | ১ RTT |
0-RTT-এর দাম: প্রথম বার্তার অনুরোধ (early data) কেউ ধরে রেখে আবার পাঠালে সার্ভার সেটি দুবার পেতে পারে — replay. তালিকা দুবার পড়লে ক্ষতি নেই, “৫,০০০ টাকা পাঠান” দুবার হলে বিপদ। তাই 0-RTT শুধু নিরাপদ, idempotent অনুরোধে; সার্ভার early data ফিরিয়ে দিয়ে handshake-এর পরে আবার চাইতে পারে (HTTP status 425 Too Early, RFC 8470). Idempotency-র নকশা: পর্ব ৮.
এবার পুরো যাত্রাটি সময়সহ দেখুন। ধরা যাক সার্ভার পর্যন্ত RTT ৫০ ms, নামটি কোনো cache-এ নেই (খুঁজতে ৫০ ms), TLS 1.3, আর সার্ভারের কাজ ২০ ms:
- চাপ দিলেন
t = 0cache-এ নাম নেই - DNS
+50 msresolver → authoritative - TCP
+1 RTTSYN · SYN-ACK - TLS 1.3
+1 RTTচাবি আর certificate - HTTP GET
+25 +20 msযাওয়া আর সার্ভারের কাজ - প্রথম byte
t = 220 msTTFB
| ঘড়ি t | |
| এই ধাপে | |
| খোঁজা আর হাত মেলানোয় মোট |
- t = ০: ব্যবহারকারী চাপ দিলেন। অ্যাপ যাবে
shop.example.com-এ, কিন্তু যন্ত্রের cache-এ ঠিকানা নেই। ধরে নেওয়া: RTT ৫০ ms, সার্ভারের কাজ ২০ ms. - DNS: t = ৫০ ms. Stub resolver প্রশ্ন পাঠাল ISP-র recursive resolver-কে (round trip ১০ ms); তার cache-এও নেই, তাই সে authoritative server-এ গেল (আরও ৪০ ms). IP হাতে এল ৫০ ms-এ। TTL-এর মধ্যে পরের বার এই ৫০ ms আর লাগবে না।
- TCP: t = ১০০ ms. Client পাঠাল SYN, সার্ভার ফেরত দিল SYN-ACK — এক RTT, ৫০ ms. তৃতীয় বার্তা ACK-এর সাথেই client TLS-এর প্রথম বার্তা (ClientHello) জুড়ে দিল, তাই আলাদা অপেক্ষা নেই।
- TLS 1.3: t = ১৫০ ms. সার্ভার এক উত্তরে পাঠাল নিজের চাবির অংশ, certificate আর Finished — আরও এক RTT. Connection এখন এনক্রিপ্টেড; client নিজের Finished-এর সাথেই HTTP অনুরোধ পাঠাল। TLS 1.2 হলে এখানে আরও এক RTT লাগত।
- HTTP: t = ১৯৫ ms. অনুরোধটি সার্ভারে পৌঁছাল অর্ধেক RTT পরে (১৭৫ ms), সার্ভার ২০ ms কাজ করল (১৯৫ ms). উত্তর এখন পথে।
- প্রথম byte: t = ২২০ ms. উত্তর ফিরতে আরও ২৫ ms. মোট TTFB ২২০ ms, যার ১৫০ ms (৬৮%) গেছে শুধু নাম খোঁজা আর হাত মেলানোয় — সার্ভারের আসল কাজ মাত্র ২০ ms. একই connection-এ পরের অনুরোধে লাগবে ৫০ + ২০ = ৭০ ms.
একই হিসাব নানা RTT-তে চালিয়ে দেখুন। নিচের calculator প্রতিটি পদ্ধতির জন্য time to first byte (TTFB) ছাপে। এখানে TTFB মানে ব্যবহারকারীর চাপ থেকে উত্তরের প্রথম byte পর্যন্ত — DNS আর handshake-সহ। টুলভেদে TTFB-র শুরু আলাদা ধরা হয়, তাই রিপোর্টে সংজ্ঞা লিখে রাখুন।
// Time to first byte (TTFB) of ONE new HTTPS request, in a simple model:
// TTFB = DNS time + (round trips before the response can start) x RTT + server time.
// ASSUMED: DNS answer already cached on the device = 0 ms; DNS miss = 50 ms
// (resolver ~10 ms away + its trip to the authoritative server ~40 ms); server work 20 ms.
const DNS = { hit: 0, miss: 50 }, SERVER_MS = 20;
// Round trips before the first response byte can arrive (request + response = 1 of them):
const SETUP = [
["TCP+TLS1.2", 4], // TCP 1 + TLS 1.2 full handshake 2 + request 1
["TCP+TLS1.3", 3], // TCP 1 + TLS 1.3 handshake 1 + request 1
["QUIC 1-RTT", 2], // QUIC sets up transport + TLS 1.3 together: 1 + request 1
["QUIC 0-RTT", 1], // resumed: request rides in the first flight (replay risk!)
];
const ttfb = (rtt, dns, trips) => dns + trips * rtt + SERVER_MS;
let head = "RTT(ms) DNS ".padEnd(13);
for (const [name] of SETUP) head += name.padStart(12);
console.log(head + " reused conn");
for (const rtt of [10, 50, 150, 300]) {
for (const d of ["hit", "miss"]) {
let row = (String(rtt).padStart(5) + " " + d).padEnd(13);
for (const [, trips] of SETUP) row += String(ttfb(rtt, DNS[d], trips)).padStart(12);
// an already-open, warm connection needs no DNS and no handshake: 1 RTT
console.log(row + String(ttfb(rtt, 0, 1)).padStart(14));
}
}
const saved = ttfb(150, DNS.miss, 4) - ttfb(150, DNS.miss, 1);
console.log("RTT 150, DNS miss: TLS 1.2 -> QUIC 0-RTT saves " + saved + " ms = 3 round trips");আউটপুট:
RTT(ms) DNS TCP+TLS1.2 TCP+TLS1.3 QUIC 1-RTT QUIC 0-RTT reused conn
10 hit 60 50 40 30 30
10 miss 110 100 90 80 30
50 hit 220 170 120 70 70
50 miss 270 220 170 120 70
150 hit 620 470 320 170 170
150 miss 670 520 370 220 170
300 hit 1220 920 620 320 320
300 miss 1270 970 670 370 320
RTT 150, DNS miss: TLS 1.2 -> QUIC 0-RTT saves 450 ms = 3 round trips
RTT ১০ ms-এ সব পদ্ধতি ১১০ ms-এর মধ্যে — সার্ভার কাছে থাকলে protocol-এর পার্থক্য প্রায় চোখে পড়ে না। RTT ৩০০ ms-এ DNS miss-সহ TLS 1.2 নেয় ১,২৭০ ms, QUIC 0-RTT ৩৭০ ms — ৯০০ ms-এর পার্থক্য, পুরোটাই round trip-এর গুণফল। খোলা connection-এ (শেষ কলাম) RTT ১৫০-এ ১৭০ ms, নতুন TLS 1.3-এর প্রায় তিন ভাগের এক ভাগ। DNS miss-এর ৫০ ms সব কলামে সমান যোগ হয়; আর শেষ লাইন দেখায়, ৩টি round trip কমলে RTT ১৫০-এ বাঁচে ৪৫০ ms.
হিসাবটি ইচ্ছা করে সরল: TLS 1.2-এর False Start বা TCP Fast Open (RFC 7413)-এ সংখ্যা কমে, packet হারালে বা certificate-এর লম্বা chain-এ বাড়ে। আসল মাপ নিন ব্রাউজারের network টুল বা curl -w দিয়ে (নেটওয়ার্ক পারফরম্যান্স); handshake-এর বার্তা ধরে ধরে: TLS আর HTTPS, QUIC.
৫ · Connection বারবার ব্যবহার — keep-alive, pool, slow start, ephemeral port আর TIME_WAIT
প্রতিটি connection-এর দাম শুধু সময়ে নয়। TLS-এর চাবি বিনিময় আর certificate যাচাইয়ের public-key গণনা ডেটা এনক্রিপ্ট করার চেয়ে অনেক ভারী; প্রতিটি খোলা connection-এ kernel-এর buffer, একটি file descriptor আর TLS-এর অবস্থা লাগে; load balancer, firewall আর NAT প্রতিটির জন্য টেবিলে একটি ঘর রাখে; আর নতুন connection পুরো গতিতে শুরুও করে না (নিচের slow start).
সমাধান: একবার খুলুন, বারবার ব্যবহার করুন। HTTP/1.1-এ connection ডিফল্টভাবে খোলা থাকে — persistent connection বা keep-alive. সার্ভিসের ভেতরে, app server থেকে database বা অন্য সার্ভিসে, আগে থেকে খোলা connection-এর ভান্ডার রাখা হয় — connection pool; মাপের হিসাব Little-এর সূত্রে (পর্ব ৪)।
মুদি দোকানে নিয়মিত খদ্দেরের খাতা খোলা থাকে, তাই প্রতিবার পরিচয় দিতে হয় না — “খাতায় লিখে রাখুন” বললেই হয়। খাতা খোলা একবারের খরচ; তবে শত শত খাতায় তাক ভরে যায়, তাই অনেক দিন না আসা খদ্দেরের খাতা তুলে রাখা হয় — অলস connection বন্ধ করার মতো।
নিচের মডেলে একই সার্ভারে ২০টি অনুরোধ, চারভাবে। RTT ৫০ আর ১৫০ ms, প্রতিটি অনুরোধে সার্ভারের কাজ ১০ ms, connection খুলতে TCP + TLS 1.3 = ২ RTT:
// 20 requests from one client to one server. How long until ALL responses are in?
// Simple model: TCP + TLS 1.3 setup = 2 RTT; each request/response = 1 RTT + server time.
// Ignored on purpose: bandwidth, slow start, packet loss, DNS (already cached).
const N = 20, SERVER_MS = 10, SETUP_RTT = 2, BROWSER_CONNS = 6;
function plans(rtt) {
const one = rtt + SERVER_MS; // one request on an open connection
return [
// (a) open a new connection for every request, one after another
["new connection per request", N * (SETUP_RTT * rtt + one)],
// (b) HTTP/1.1 keep-alive: one connection, requests one after another
["1 keep-alive connection", SETUP_RTT * rtt + N * one],
// (c) HTTP/1.1, 6 parallel keep-alive connections (setups happen in parallel)
["6 parallel connections", SETUP_RTT * rtt + Math.ceil(N / BROWSER_CONNS) * one],
// (d) HTTP/2: one connection, all 20 independent requests multiplexed at once
["HTTP/2 multiplexed", SETUP_RTT * rtt + one],
];
}
for (const rtt of [50, 150]) {
console.log(`--- RTT = ${rtt} ms, ${N} requests, server ${SERVER_MS} ms each ---`);
const p = plans(rtt), worst = p[0][1];
for (const [name, ms] of p)
console.log(name.padEnd(28) + (ms + " ms").padStart(9) +
("speed-up x" + (worst / ms).toFixed(1)).padStart(17));
console.log("handshakes done: " + N + " vs 1 vs " + BROWSER_CONNS + " vs 1");
}আউটপুট:
--- RTT = 50 ms, 20 requests, server 10 ms each ---
new connection per request 3200 ms speed-up x1.0
1 keep-alive connection 1300 ms speed-up x2.5
6 parallel connections 340 ms speed-up x9.4
HTTP/2 multiplexed 160 ms speed-up x20.0
handshakes done: 20 vs 1 vs 6 vs 1
--- RTT = 150 ms, 20 requests, server 10 ms each ---
new connection per request 9200 ms speed-up x1.0
1 keep-alive connection 3500 ms speed-up x2.6
6 parallel connections 940 ms speed-up x9.8
HTTP/2 multiplexed 460 ms speed-up x20.0
handshakes done: 20 vs 1 vs 6 vs 1
RTT ৫০ ms-এ প্রতিবার নতুন connection খুললে ৩,২০০ ms; একটি keep-alive connection-এ ১,৩০০ ms — শুধু handshake বাদ দিয়েই ২.৫ গুণ দ্রুত। ৬টি সমান্তরাল connection ৩৪০ ms (handshake ৬ বার), আর HTTP/2-এ এক connection-এ ২০টি একসাথে ১৬০ ms. RTT ১৫০-এ একই ক্রম: ৯,২০০ → ৩,৫০০ → ৯৪০ → ৪৬০ ms. শেষ দুটির শর্ত: অনুরোধগুলো একে অন্যের উত্তরের ওপর নির্ভর করে না। আগে login, তারপর তালিকা — এমন শিকলে multiplexing সাহায্য করে না; তখন উপায় round trip কমানো, যেমন এক অনুরোধে দরকারি সব আনার API (পর্ব ৮) বা BFF (পর্ব ১১)। মডেলটি bandwidth আর slow start উপেক্ষা করেছে।
Slow start — নতুন connection কেন ধীরে শুরু করে
TCP পথের ক্ষমতা জানে না, তাই নতুন connection অল্প ডেটা দিয়ে শুরু করে প্রতি RTT-তে পরিমাণ দ্বিগুণ করে — slow start; একবারে কতটা পথে রাখা যাবে, তার সীমা congestion window. শুরুর মান সাধারণত ১০টি segment, প্রায় ১৪.৬ kB (RFC 6928, ২০১৩; OS-ভেদে আলাদা)। Loss না হলে:
- প্রায় ১০০ kB-এর একটি উত্তর: ১৪.৬ + ২৯.২ + ৫৮.৪ kB — ৩ RTT.
- ১ MB-এর উত্তর: ৭ RTT. RTT ১৫০ ms হলে প্রায় ১.০৫ সেকেন্ড, অথচ ৫০ Mbps-এর লাইনে ১ MB পাঠাতে লাগার কথা মাত্র ১৬০ ms.
অর্থাৎ ছোট আর মাঝারি transfer প্রায়ই latency-তে বাঁধা: লাইন মোটা করলে লাভ সামান্য, RTT কমালে বা আগে থেকে চলা “উষ্ণ” connection ব্যবহার করলে লাভ বেশি (অনেক OS-এ অলস connection আবার slow start থেকে শুরু করে; setting সংস্করণভেদে আলাদা)। গভীরে: TCP congestion control.
Ephemeral port আর TIME_WAIT — বড় আকারে connection-এর সীমা
একটি TCP connection চেনা যায় চারটি জিনিসে: উৎসের IP ও port, আর গন্তব্যের IP ও port. Client নতুন connection খুললে OS একটি অস্থায়ী উৎস-port বেছে দেয় — ephemeral port; Linux-এ ডিফল্ট পরিসর সাধারণত 32768–60999, অর্থাৎ ২৮,২৩২টি। Connection বন্ধের পর যে পক্ষ আগে বন্ধ করে, সে কিছুক্ষণ TIME_WAIT অবস্থায় থাকে (Linux-এ ৬০ সেকেন্ড), যাতে পথে দেরিতে আসা পুরোনো packet নতুন connection-এ ঢুকে না পড়ে।
এবার একটি reverse proxy ভাবুন, যার উৎস IP একটি, আর যে প্রতিটি অনুরোধে একই backend-এর (একই IP:port) সাথে নতুন connection খুলে নিজেই বন্ধ করে। প্রতিটি port ৬০ সেকেন্ড আটকে থাকলে টেকসই হার সর্বোচ্চ ২৮,২৩২ ÷ ৬০ ≈ প্রতি সেকেন্ডে ৪৭০টি নতুন connection; বেশি চাইলে “port নেই” ধরনের error. আসল সমাধান connection reuse — keep-alive আর pool. তারপর চার-ঠিকানার জোড়া বাড়ানো (বেশি backend IP বা proxy-র বেশি উৎস IP), আর শেষে সাবধানে OS-এর setting. পুরোনো “সমাধান” tcp_tw_recycle NAT-এর পেছনের client-দের connection ভাঙত; Linux 4.12-এ সেটি সরিয়েই ফেলা হয়েছে। খুঁটিনাটি: TCP সংযোগ পর্ব।
Pool-এর স্বাস্থ্যবিধি: চারটি সীমা রাখুন — সর্বোচ্চ সংখ্যা (backend-এর নিজের সীমার ভেতরে), অলস connection কতক্ষণ থাকবে, connection-এর সর্বোচ্চ বয়স (যাতে DNS-এর বদল আর নতুন সার্ভার চোখে পড়ে), আর connection পেতে অপেক্ষার timeout. দীর্ঘজীবী connection নতুন সার্ভার যোগ হলেও পুরোনো সার্ভারে আটকে থেকে ভার অসমান করে — প্রতিকার পর্ব ১৪-এ।
৬ · HTTP-এর তিন প্রজন্ম — HTTP/1.1, HTTP/2, HTTP/3 আর head-of-line blocking
HTTP-এর ভাষা একই থেকেছে — method, path, header, status code (HTTP পর্বে) — কিন্তু নিচে তার খাম তিনবার বদলেছে। নকশার দিক থেকে মূল প্রশ্ন একটাই: একটি connection-এ একসাথে কতগুলো অনুরোধ চলে, আর একটি আটকালে বাকিদের কী হয়?
- HTTP/1.1: এক connection-এ একবারে একটি অনুরোধ-উত্তর; পরেরটি আগেরটির শেষের অপেক্ষায় — application স্তরের head-of-line blocking (pipelining প্রায় কোথাও চালু রাখা হয়নি)। তাই ব্রাউজার একটি সার্ভারে সাধারণত ছয়টির মতো connection খোলে — বেশি handshake, বেশি resource.
- HTTP/2 (RFC 7540, ২০১৫; হালনাগাদ RFC 9113, ২০২২): এক TCP connection-এ অনেক stream পালাক্রমে — multiplexing, সাথে header সংকোচন। কিন্তু নিচের TCP একটিই byte-সারি: একটি packet হারালে পরের সব ডেটা, অন্য stream-এর হলেও, অপেক্ষা করে।
- HTTP/3 (RFC 9114, ২০২২): চলে QUIC-এর ওপর, QUIC চলে UDP-র ওপর। QUIC নিজেই stream চেনে, তাই হারানো packet শুধু নিজের stream থামায়; সাথে ১-RTT বা 0-RTT handshake আর connection migration — Wi-Fi থেকে মোবাইল ডেটায় গেলেও connection ID দিয়ে একই connection চলে।
পাইকারি আড়ত থেকে তিনটি খুচরা দোকানে মাল যাচ্ছে। HTTP/1.1-এ এক ট্রাকে এক দোকানের মাল — প্রথমটি শেষ না হলে পরের ট্রাক ছাড়ে না। HTTP/2-এ এক ট্রাকে তিন দোকানের বস্তা, কিন্তু নামাতে হবে ঠিক ক্রমিক নম্বরে; মাঝের একটি বস্তা পড়ে গেলে সেটি ফেরা পর্যন্ত কারও বস্তাই নামে না। HTTP/3-এ প্রতিটি দোকানের আলাদা নম্বর-সারি — বস্তা হারালে শুধু সেই দোকান অপেক্ষা করে।
| তারে packet | |
| A (style.css) | |
| B (app.js) | |
| C (logo.png) | |
| Handshake |
- একটি পাতা, তিনটি ফাইল। style.css (A), app.js (B) আর logo.png (C), প্রতিটি তিনটি packet-এ। দেখব তিন প্রজন্মের HTTP এগুলো কীভাবে বয়ে নেয়, আর একটি packet হারালে কে আটকায়।
- HTTP/1.1: একবারে একটি। এক connection-এ আগে A, তারপর B, তারপর C. A ধীর হলে B আর C শুরুই হয় না। ব্রাউজার তাই কয়েকটি connection খোলে — প্রতিটির আলাদা handshake আর slow start.
- HTTP/2: এক connection-এ পালাক্রমে। তিনটি stream; তারে যায় A1 B1 C1 A2 B2 C2… — তিনটিই একসাথে এগোয়, handshake একবারই। Loss না থাকলে দারুণ।
- HTTP/2, A2 হারাল: সবাই থামল। TCP-র কাছে সব একটিই byte-সারি, প্রতিশ্রুতি “ঠিক ক্রমে দেব”। A2-র ফাঁক পূরণ না হওয়া পর্যন্ত B2, C2, A3, B3, C3 এসে গেলেও kernel-এর buffer-এ আটকে থাকে — TCP স্তরের head-of-line blocking.
- HTTP/3, একই loss: শুধু A থামল। QUIC জানে কোন packet কোন stream-এর, তাই B আর C সম্পূর্ণ হয়ে অ্যাপে চলে যায়; শুধু stream A প্রায় এক RTT অপেক্ষা করে। Packet-ধরে হিসাব: QUIC পর্বের অংশ ২.
- নকশার সিদ্ধান্ত। Loss কম এমন পথে (data centre-এর ভেতরে) HTTP/2 আর HTTP/3 প্রায় সমান; দুর্বল মোবাইল network বা ভিড়ের Wi-Fi-তে HTTP/3-এর লাভ স্পষ্ট। তবে UDP খোলা থাকতে হয়, তাই HTTP/2-তে ফেরার পথ সবসময় রাখুন।
HTTP/3 আছে কি না, ব্রাউজার জানে সার্ভারের উত্তর থেকে (alt-svc header, বা DNS-এর HTTPS record); প্রথমবার সাধারণত TCP-তে আসে, পরের connection-এ QUIC চেষ্টা করে, UDP আটকানো থাকলে TCP-তে ফেরে:
HTTP/2 200
content-type: text/html; charset=utf-8
cache-control: max-age=60
alt-svc: h3=":443"; ma=86400h3=":443" মানে UDP port 443-এ HTTP/3; ma=86400 মানে তথ্যটি এক দিন মনে রাখা যায়। কোন পথে সাধারণত কোন সংস্করণ:
| পথ | প্রচলিত পছন্দ | কেন |
|---|---|---|
| ব্রাউজার বা অ্যাপ → CDN edge বা load balancer | HTTP/2; যেখানে সম্ভব HTTP/3 | দূরের, loss-প্রবণ পথ; কম handshake, কম HOL |
| Edge বা proxy → origin | keep-alive-সহ HTTP/1.1 বা HTTP/2 | স্থির পথ; খোলা connection pool-ই মূল লাভ |
| Data centre-এর ভেতরে, service থেকে service | HTTP/2 (যেমন gRPC — পর্ব ৯) বা keep-alive-সহ HTTP/1.1 | Loss খুব কম; কম connection |
| সার্ভার থেকে client-এ ঘটনা পাঠানো | WebSocket, SSE, বা HTTP/2-3-এর stream | দীর্ঘজীবী connection — পর্ব ১০ |
অনেক নকশায় TLS শেষ হয় edge বা reverse proxy-তে, আর ভেতরে proxy নিজের connection pool দিয়ে কথা বলে — সেই সিদ্ধান্ত পর্ব ১১-এ (Reverse proxy, API gateway আর BFF).
আরও গভীরে: QUIC-এর জন্ম Google-এ, ২০১২–২০১৩ সাল নাগাদ Jim Roskind-এর নকশায়; বড় আকারের অভিজ্ঞতা প্রকাশিত হয় “The QUIC Transport Protocol: Design and Internet-Scale Deployment” (Langley ও সহকর্মীরা, SIGCOMM ২০১৭) paper-এ। IETF নকশাটি অনেকখানি নতুন করে গড়ে RFC 9000 (২০২১) হিসেবে মান করে, আর HTTP/3 আসে RFC 9114 (২০২২)-এ। Transport কেন UDP-র ওপর, user space-এ — তার কারণ মাঝের পুরোনো যন্ত্র, যারা অচেনা protocol দেখলে ভেঙে দেয় (“ossification”); বিস্তারিত Transport layer পর্বের অংশ ৭-এ।
৭ · UDP কখন — real-time media, DNS, game আর QUIC
UDP প্রায় কিছুই করে না, আর সেটাই তার শক্তি: handshake নেই, আবার পাঠানো নেই, ক্রম রক্ষা নেই — প্রতিটি datagram স্বাধীন বার্তা, একটি হারালে পরেরগুলো আটকায় না। দরকারি নিশ্চয়তা অ্যাপ নিজে বানায়।
ক্রিকেটের সরাসরি রেডিও ধারাভাষ্যে একটি বাক্য শোনা না গেলে ধারাভাষ্যকার সেটি আবার বলেন না — পরের বলের কথা বলেন, কারণ দেরিতে আসা পুরোনো খবর অর্থহীন। Live voice-video-তে packet loss-এর জবাবও তাই: বাদ দিয়ে এগোনো, দরকারে ফাঁক ঢেকে দেওয়া।
নকশাকারেরা UDP বেছে নেন সাধারণত:
- Real-time voice আর video-তে: দেরিতে আসা packet হারানো packet-এরই সমান। WebRTC-র মতো ব্যবস্থার media সাধারণত UDP-তে; প্রাপক jitter ঢাকতে ছোট buffer রাখে।
- Online game আর live অবস্থানে: সর্বশেষ অবস্থাই আসল; পুরোনো আপডেট আবার পাঠানোর মানে নেই।
- DNS-এ: ছোট প্রশ্ন, ছোট উত্তর — connection খোলার খরচ উত্তরের চেয়েও বড় হতো। বড় উত্তরে DNS TCP-তেও চলে।
- QUIC আর HTTP/3-এ: UDP শুধু পাতলা খাম; নির্ভরযোগ্যতা, ক্রম আর গতি-নিয়ন্ত্রণ QUIC নিজে বানায়, তাই OS বা মাঝের যন্ত্র না বদলেই নতুন transport চালু করা গেছে।
বিনিময়ে দাম: congestion control নিজে বানাতে হয়, নইলে ভিড়ে সবার network ভোগে; NAT আর firewall অলস UDP-র কথোপকথন কয়েক দশ সেকেন্ড থেকে কয়েক মিনিটে ভুলে যায় (যন্ত্রভেদে আলাদা), তাই নিয়মিত keepalive লাগে; কিছু network UDP আটকায়, তাই TCP-তে ফেরার পথ লাগে। আর উত্তর প্রশ্নের চেয়ে অনেক বড় হলে, ঠিকানা যাচাই ছাড়া সেবাটি অন্যকে ডোবানোর (amplification) কাজে অপব্যবহৃত হতে পারে — প্রতিরক্ষা হলো যাচাইয়ের আগে ছোট উত্তর (QUIC-এ প্রাপ্ত byte-এর তিন গুণের বেশি নয়) আর rate limit (পর্ব ৪৯)।
| প্রয়োজন | TCP (+ TLS) | UDP, নিজের নিয়মে | QUIC |
|---|---|---|---|
| সব byte ঠিক ক্রমে, কিছু হারানো চলবে না (লেনদেন, ফাইল) | ✔ প্রচলিত, প্রায় সবখানে চলে | ✘ সব নিজে বানাতে হবে | ✔ (HTTP/3) |
| দেরিতে এলে ডেটা অর্থহীন (ভয়েস, ভিডিও কল, game) | ✘ আবার পাঠানো আর HOL ক্ষতি করে | ✔ | আংশিক — datagram extension-এ (RFC 9221) সম্ভব, প্রয়োগভেদে আলাদা |
| অনেক ছোট স্বাধীন অনুরোধ, দুর্বল ও বদলাতে থাকা মোবাইল network | চলে, কিন্তু loss-এ HOL আর network বদলে নতুন connection | কঠিন | ✔ stream-স্বাধীন, connection migration |
| UDP আটকানো network | ✔ | ✘ | ✘ — TCP-তে ফেরার পথ লাগে |
Real-time নকশা: পর্ব ১০; case study পর্ব ৫৫, ৫৮ আর ৫৯. ভেতরটা: UDP, Transport layer, Real-time আর streaming.
৮ · দূরত্বের হিসাব — আলোর গতি, region আর CDN
RTT সবচেয়ে কম কত হতে পারে? Fibre-এর কাচের প্রতিসরাঙ্ক প্রায় ১.৪৭, তাই আলোর গতি ≈ ৩,০০,০০০ ÷ ১.৪৭ ≈ ২,০৪,০০০ km/s; হিসাবে ধরা হয় ২,০০,০০০ km/s — এক দিকে প্রতি ২০০ km-এ ১ ms. d km দূরত্বে round trip:
এটি propagation delay-এর সীমা, কোনো কোড একে কমায় না (পর্ব ৩)। দূরত্ব নেওয়া হলো great-circle distance — শহরের কেন্দ্র থেকে কেন্দ্র, মোটামুটি, গোল করা:
// Light in optical fibre travels at about 200,000 km/s (about 2/3 of its speed in vacuum).
// A round trip over d km therefore takes AT LEAST 2*d/200000 s = d/100 ms.
// Distances below are APPROXIMATE great-circle values (straight over the globe);
// real cables are longer and routers add delay, so measured RTTs are higher.
const V_FIBRE = 200000; // km per second
const pairs = [
["Dhaka-Chattogram", 210], ["Dhaka-Kolkata", 250], ["Dhaka-Mumbai", 1900],
["Dhaka-Singapore", 2900], ["Dhaka-Tokyo", 4900], ["Dhaka-Frankfurt", 7400],
["Dhaka-London", 8000], ["Dhaka-US West", 12400], ["Dhaka-US East", 12900],
];
const minRtt = (km) => 2 * km / V_FIBRE * 1000; // milliseconds
const f = (x) => x.toFixed(0);
console.log("route km min RTT rough real new HTTPS (3 RTT)");
for (const [name, km] of pairs) {
const m = minRtt(km);
console.log(name.padEnd(17) + String(km).padStart(6) + (m.toFixed(1) + " ms").padStart(10) +
("~" + f(1.5 * m) + "-" + f(2.5 * m) + " ms").padStart(13) + (">= " + f(3 * m) + " ms").padStart(14));
}
// "rough real" = 1.5x to 2.5x the minimum: an ASSUMED rule of thumb, not a measurement.
// Turn it around: how far away may the server be for a TTFB budget (DNS, server time ignored)?
for (const budget of [100, 300]) {
const rtt = budget / 3; // new TCP + TLS 1.3 connection = 3 RTT
const best = rtt * V_FIBRE / 2 / 1000; // km, if the path were perfect fibre
console.log(`TTFB budget ${budget} ms -> RTT <= ${rtt.toFixed(1)} ms -> server within ` +
`${best.toFixed(0)} km (best case), ~${(best / 2).toFixed(0)} km if real RTT = 2x min`);
}আউটপুট:
route km min RTT rough real new HTTPS (3 RTT)
Dhaka-Chattogram 210 2.1 ms ~3-5 ms >= 6 ms
Dhaka-Kolkata 250 2.5 ms ~4-6 ms >= 8 ms
Dhaka-Mumbai 1900 19.0 ms ~29-48 ms >= 57 ms
Dhaka-Singapore 2900 29.0 ms ~44-73 ms >= 87 ms
Dhaka-Tokyo 4900 49.0 ms ~74-123 ms >= 147 ms
Dhaka-Frankfurt 7400 74.0 ms ~111-185 ms >= 222 ms
Dhaka-London 8000 80.0 ms ~120-200 ms >= 240 ms
Dhaka-US West 12400 124.0 ms ~186-310 ms >= 372 ms
Dhaka-US East 12900 129.0 ms ~194-323 ms >= 387 ms
TTFB budget 100 ms -> RTT <= 33.3 ms -> server within 3333 km (best case), ~1667 km if real RTT = 2x min
TTFB budget 300 ms -> RTT <= 100.0 ms -> server within 10000 km (best case), ~5000 km if real RTT = 2x min
ঢাকা–সিঙ্গাপুর প্রায় ২,৯০০ km, তাই RTT অন্তত ২৯ ms; ঢাকা–US East প্রায় ১২,৯০০ km, তাই অন্তত ১২৯ ms, আর নতুন HTTPS connection-এ প্রথম byte অন্তত ৩৮৭ ms পরে — সার্ভার কিছু না করলেও। “rough real” কলাম ধরে-নেওয়া থাম্ব-রুল, মাপা সংখ্যা নয়: cable উপকূল ঘুরে যায়, traffic দূরের hub হয়ে যায়, router-এ অপেক্ষা যোগ হয়। ছোট দূরত্বে (ঢাকা–চট্টগ্রাম ২.১ ms) গুণকটি অর্থহীন — Wi-Fi বা মোবাইলের রেডিও অংশই কয়েক থেকে কয়েক দশ ms যোগ করতে পারে। শেষ দুই লাইন: TTFB-র বাজেট ১০০ ms হলে সার্ভার আদর্শ অবস্থায় ৩,৩৩৩ km-এর মধ্যে, বাস্তবে মোটামুটি ১,৬৬৭ km-এর মধ্যে থাকতে হবে — ঢাকার ব্যবহারকারীর জন্য US East কোনোভাবেই পারে না।
তাহলে মোট সময় কমানোর হাতল দুটি — অংশ ১-এর প্রথম নিয়মের দুই গুণক:
- RTT কমানো, মানে কাছে যাওয়া: static ফাইল, ছবি, ভিডিও আর cache-যোগ্য উত্তর আসুক কাছের CDN edge থেকে (পর্ব ১৭); TLS-ও তখন edge-এ শেষ হয়, আর edge দূরের origin-এর সাথে আগে থেকে খোলা connection-এ কথা বলে। ব্যবহারকারী বহু মহাদেশে থাকলে সার্ভারও একাধিক region-এ (পর্ব ৫১)।
- Round trip কমানো: connection reuse, TLS 1.3 আর QUIC, HTTP/2; আর API-তে নির্ভরশীল অনুরোধের শিকল এড়ানো — দূরের client-কে একবার ডাকুন, বাকি ডাকাডাকি হোক data centre-এর ভেতরে।
Region পেরোনো পরপর call বিষের মতো। App সিঙ্গাপুরে, database US East-এ — প্রতিটি query ধরা যাক ২৫০ ms; পাতায় পরপর ১০টি query মানে শুধু অপেক্ষাতেই ২.৫ সেকেন্ড। ঘন ঘন কথা বলা অংশ (app আর তার database) এক region-এ; region পেরোবে শুধু অ্যাসিঙ্ক্রোনাস replication বা কম ঘন কাজ (পর্ব ২২, ৫১)।
Bandwidth বনাম latency — bandwidth-delay product
ট্রেনে বগি বাড়ালে বেশি যাত্রী যায় — bandwidth বাড়ে; কিন্তু চট্টগ্রাম পৌঁছানোর সময় কমে না — latency একই। পথ পুরো ব্যবহার করতে একসাথে কতটা ডেটা পথে থাকতে হয়, তা bandwidth-delay product (BDP) = bandwidth × RTT: 1 Gbps আর RTT ২০০ ms-এ ২৫ MB. উল্টো দিকে, window মাত্র ৬৪ KB (৬৫,৫৩৫ byte) হলে RTT ২০০ ms-এ throughput সর্বোচ্চ প্রায় ২.৬ Mbps — লাইন যত মোটাই হোক। দূরের region-এ বড় backup পাঠানোর নকশায় এটি জরুরি; বিস্তারিত Delay, loss আর throughput (অংশ ৮) পর্বে।
৯ · Data centre-এর ভেতর আর বাইরের ঠিকানা — VPC, NAT, CGNAT আর IPv6
Cloud-এ সার্ভার সাধারণত থাকে একটি আলাদা করা private network-এ — অনেক প্রদানকারীর ভাষায় VPC. সাধারণ ছক:
- Public অংশে শুধু সামনের দরজা — load balancer বা API gateway (পর্ব ১১)। App আর database থাকে private subnet-এ, private IP-তে (যেমন 10.0.0.0/8, RFC 1918), যা internet থেকে সরাসরি পৌঁছানো যায় না।
- বাইরে যাওয়ার আলাদা পথ — private সার্ভার বাইরের API ডাকে NAT gateway দিয়ে; firewall-নিয়মে (অনেক cloud-এ security group) বাঁধা থাকে কে কার সাথে কথা বলবে (পর্ব ৫২)।
- ভেতরের দূরত্ব — একই data centre-এ RTT প্রায় ০.১–০.৫ ms; একই region-এর আলাদা availability zone-এ সাধারণত কয়েক মিলিসেকেন্ডের কম; region পেরোলে কয়েক দশ থেকে কয়েকশো ms. Zone বা region পেরোনো আর বাইরে যাওয়া ডেটার (egress) দাম প্রায়ই আলাদা — প্রদানকারীর পাতায় মিলিয়ে নিন।
বিস্তারিত: Cloud আর container নেটওয়ার্কিং.
সার্ভার কেন অনেকের একই IP দেখে — proxy, NAT আর CGNAT
প্রথম কারণ আপনার নিজের proxy: load balancer বা CDN-এর পেছনে TCP connection আসে proxy থেকে। আসল IP proxy একটি header-এ লেখে (X-Forwarded-For, বা মানসম্মত Forwarded, RFC 7239) বা PROXY protocol দিয়ে জানায়; header জাল করা যায়, তাই শুধু নিজের proxy-র লেখা অংশটুকু বিশ্বাস করুন। দ্বিতীয় কারণ ব্যবহারকারীর দিকের NAT: বাসার router-এর পেছনে পরিবারের সবাই একটি public IP ভাগ করেন, আর মোবাইল ও অনেক broadband সেবাদাতা বড় আকারে করে — CGNAT — যেখানে বহু গ্রাহক একই IP ভাগ করতে পারেন (মাঝের ঠিকানার পরিসর 100.64.0.0/10, RFC 6598).
নকশায় এর তিনটি ফল। এক, শুধু IP দেখে rate limit বা block করলে একজনের দোষে অনেকে আটকান — যেখানে সম্ভব account, token বা device ধরে সীমা দিন (পর্ব ৪৯)। দুই, log-এ IP-র সাথে উৎস port আর সঠিক সময় রাখুন (RFC 6302-এর পরামর্শ)। তিন, NAT অলস connection-এর ঘর মুছে ফেলে, তাই দীর্ঘজীবী connection নিয়মিত ছোট heartbeat পাঠায় (পর্ব ১০)। বিস্তারিত: NAT আর private ঠিকানা.
IPv6 — একটি জরুরি নোট
IPv6-এর ১২৮ bit ঠিকানায় প্রতিটি যন্ত্র নিজস্ব public ঠিকানা পেতে পারে, তাই নীতিগতভাবে NAT লাগে না (firewall লাগে)। নকশায় চারটি কাজ: সামনের দরজায় IPv4 আর IPv6 দুটিই রাখুন (DNS-এ A আর AAAA record); client-এরা Happy Eyeballs (RFC 8305) কৌশলে দুই পথ প্রায় একসাথে চেষ্টা করে বলে একটি ভাঙা পথ লুকিয়ে থাকতে পারে — দুটোই আলাদা করে monitor করুন; database-এ IP-র ঘর চওড়া রাখুন (IPv4-এর ১৫ অক্ষরের জায়গায় IPv6-এ ৩৯, কিছু রূপে ৪৫ অক্ষর, বা binary-তে ১৬ byte); আর একজন গ্রাহক সাধারণত পুরো একটি ঠিকানা-ব্লক পান (প্রায়ই /64 বা বড়), তাই rate limit prefix ধরে ভাবুন। বিস্তারিত: IPv6.
পরীক্ষা ও ইন্টারভিউতে — বিশ্ববিদ্যালয়, চাকরি বা system design ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন আসতে পারে:
- নতুন HTTPS connection-এ প্রথম byte আসতে কত RTT? TCP ১ + TLS 1.3 ১ + অনুরোধ ১ = ৩ (TLS 1.2-এ ৪, QUIC-এ ২), সাথে DNS আর সার্ভারের সময়।
- DNS failover ধীর কেন? Resolver TTL পর্যন্ত পুরোনো উত্তর রাখে; সর্বোচ্চ সময় ≈ ধরা পড়া + বদল + TTL — প্রতিকার মাঝারি TTL, anycast বা global load balancer.
- HTTP/2 আর HTTP/3-এর মূল পার্থক্য? HTTP/2-এর সব stream এক TCP-তে, একটি loss সবাইকে থামায়; HTTP/3-এর QUIC-এ stream স্বাধীন, সাথে connection migration.
- ১০,০০০ km দূরে সর্বনিম্ন RTT? ২ × ১০,০০০ ÷ ২,০০,০০০ = ০.১ সেকেন্ড = ১০০ ms.
- Proxy-তে ephemeral port কেন ফুরায়? প্রতিটি নতুন connection একটি port নেয়, যা বন্ধের পর TIME_WAIT-এ আটকে থাকে; সমাধান keep-alive আর pool.
১০ · AI-এর যুগে — networking-এর হিসাবে AI-কে যাচাই
“অ্যাপ ধীর, কী করব?” — AI প্রায়ই সাথে সাথে বলে “Redis বসান, Kafka যোগ করুন, microservice-এ ভাগ করুন”। অথচ সমস্যা প্রায়ই সরল: সার্ভার ভুল মহাদেশে, প্রতি অনুরোধে নতুন connection, বা পরপর দশটি API call. AI-এর সাধারণ ভুল:
| AI-এর ভুল | কেন ভুল | কীভাবে ধরবেন |
|---|---|---|
| “TLS-এ সবসময় ২ RTT লাগে” | TLS 1.3-এ ১ RTT, resumption-এ 0-RTT সম্ভব; ২ RTT হলো TLS 1.2 | version জিজ্ঞেস করুন; অংশ ৪-এর টেবিল |
| “DNS বদলালেই সবাই সাথে সাথে নতুন সার্ভারে যাবে” | Resolver TTL পর্যন্ত cache রাখে; খোলা connection DNS জিজ্ঞেস করে না | ধরা পড়া + বদল + TTL হিসাব করুন |
| “0-RTT চালু করুন, সব অনুরোধ দ্রুত হবে” | Early data replay হতে পারে; টাকা পাঠানোর অনুরোধে বিপদ | শুধু idempotent অনুরোধে; বাকিগুলোতে ১-RTT |
| “ঢাকা থেকে US-এর সার্ভারে RTT ২০ ms” | আলোর গতিতে অসম্ভব — অন্তত প্রায় ১২৯ ms | d ÷ ১০০ ms সূত্রে নিজে হিসাব |
| “একটি সার্ভার সর্বোচ্চ ৬৫,৫৩৫টি connection নিতে পারে” | Port-এর সীমা প্রতিটি চার-ঠিকানার জোড়ার; সার্ভারের সীমা আসে memory আর setting থেকে | অংশ ৫-এর হিসাব, documentation আর load test |
| bit আর byte গুলিয়ে ফেলা: “100 Mbps-এ 100 MB এক সেকেন্ডে” | ১ byte = ৮ bit — উত্তর ৮ গুণ ভুল | প্রতিটি সংখ্যার পাশে একক লিখে আবার হিসাব |
| Round trip না গুনেই “Kafka, Redis আর microservice বসান” | সমস্যা দূরত্ব বা connection-এ হলে নতুন অংশ আরও hop যোগ করে | আগে মাপুন সময় কোথায় যায় (অংশ ৪) |
প্রতিটি অনুমান আর ধাপ খোলা রাখতে বলুন, যাতে নিজে মেলাতে পারেন:
AI-এর network-পরিকল্পনা হাতে পেলে — যাচাইয়ের চেকলিস্ট
Round trip গুনুন, আলোর গতি মেলান, ব্যর্থতার পথ ভাবুন।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। Protocol-এর খুঁটিনাটি নয়, নকশার সিদ্ধান্তের পেছনের কারণগুলোই আসল লক্ষ্য।
প্র ০১TLS 1.3 কীভাবে handshake ২ RTT থেকে ১ RTT-এ নামাল, আর 0-RTT কেন সব অনুরোধে খুলে দেওয়া হয় না?
TLS 1.2-এর পূর্ণ handshake-এ ২ RTT লাগত, কারণ client আগে জানতে চাইত সার্ভার কোন key-exchange পদ্ধতি নেবে, তারপর নিজের অংশ পাঠাত। TLS 1.3 (RFC 8446, আগস্ট ২০১৮) কাজটি উল্টে দেয়: client প্রথম বার্তাতেই সবচেয়ে প্রচলিত পদ্ধতিগুলোর জন্য নিজের key share অনুমান করে পাঠিয়ে দেয়। অনুমান মিললে — বাস্তবে প্রায় সবসময় মেলে — সার্ভার এক উত্তরেই নিজের অংশ, certificate আর Finished পাঠায়: ১ RTT. একই সাথে পুরোনো, দুর্বল অংশ বাদ যায়, যেমন সার্ভারের দীর্ঘমেয়াদি RSA key দিয়ে সরাসরি চাবি বিনিময়, ফলে নিরাপত্তাও বাড়ে।
মানটি চূড়ান্ত হতে প্রায় চার বছর আর ২৮টি খসড়া লেগেছিল। বড় বাধা ছিল মাঝখানের পুরোনো যন্ত্র, যারা অচেনা handshake দেখলে connection ভেঙে দিত; তাই TLS 1.3 বাইরে থেকে নিজেকে অনেকটা TLS 1.2-এর resumption-এর মতো দেখায় — “middlebox compatibility mode”.
0-RTT কেন সবখানে নয়? Early data এনক্রিপ্টেড থাকলেও তা নতুন handshake-এর এলোমেলো মানের সাথে বাঁধা নয়, তাই কেউ সেটি ধরে রেখে আবার পাঠালে সার্ভার একই অনুরোধ দ্বিতীয়বার পেতে পারে। পণ্যের পাতা দুবার পড়লে ক্ষতি নেই; “টাকা পাঠান” দুবার কার্যকর হলে বিপদ। মান নিজেই সতর্ক করে যে 0-RTT-এর ডেটা replay-ঝুঁকিসহ আসে। HTTP-র জন্য RFC 8470 (২০১৮) একটি পথ দেয়: সার্ভার ঝুঁকি নিতে না চাইলে status 425 (Too Early) দিয়ে client-কে বলে, handshake শেষে অনুরোধটি আবার পাঠাতে। একবার-ব্যবহারযোগ্য ticket বা সময়-জানালার মতো anti-replay কৌশল আছে, কিন্তু বহু সার্ভারে ছড়ানো ব্যবস্থায় পুরো নিশ্চয়তা দেওয়া কঠিন।
নকশার নিয়ম তাই সরল: early data শুধু safe আর idempotent অনুরোধে, যেমন পাবলিক তালিকা পড়া। লেনদেনের মতো কাজে স্বাভাবিক ১-RTT, আর সাথে idempotency key, যাতে কোনো কারণে অনুরোধ দুবার এলেও ফল একবারই হয় (পর্ব ৮ আর পর্ব ৩৪)।
মূল উপলব্ধি: গতি কেনা হয়েছে একটি নিশ্চয়তা ছেড়ে দিয়ে — 0-RTT চালু করবেন কি না, সেটি protocol-এর নয়, আপনার API-র idempotency-র প্রশ্ন।
প্র ০২DNS-এর TTL ১ সেকেন্ড করলেই কি failover প্রায় তাৎক্ষণিক হয়ে যায়?
প্রলোভনটি বোঝা যায়: সর্বোচ্চ failover-সময় ≈ ধরা পড়া + বদল + TTL, তাই TTL ছোট করলে সময়ও ছোট। কিন্তু চারটি বাস্তব বাধা আছে।
- সবাই TTL মানে না: কিছু resolver খুব ছোট TTL-কে নিজের ন্যূনতম মানে বাড়িয়ে নেয়, আর কিছু client, browser বা runtime নিজের ভেতরে আলাদা করে উত্তর রেখে দেয়। নিয়ম সংস্করণভেদে আলাদা, তাই অনুমান না করে মেপে দেখতে হয়।
- খোলা connection DNS জিজ্ঞেস করে না: keep-alive আর pool-এর connection পুরোনো IP-তেই থাকে, যতক্ষণ না ভাঙে বা বয়স ফুরায়।
- খরচ আর ভার: TTL ৩০০ থেকে ১ সেকেন্ডে নামালে জনপ্রিয় নামের জন্য authoritative-এ প্রশ্ন কয়েকশো গুণ পর্যন্ত বাড়তে পারে, আর প্রায় প্রতিটি নতুন connection-এর আগে DNS-এর দেরি যোগ হয়।
- নির্ভরতা বাড়ে: ছোট TTL মানে cache দ্রুত ফুরায়; DNS সেবাদাতা বিভ্রাটে পড়লে আপনার সেবা প্রায় সাথে সাথে অদৃশ্য।
শেষ বিষয়টির একটি বিখ্যাত উদাহরণ ২০১৬ সালের ২১ অক্টোবর। Dyn নামের একটি বড় managed DNS সেবাদাতার ওপর Mirai নামের একটি botnet-এর বিশাল DDoS আক্রমণে কয়েক ঘণ্টা ধরে অনেক জনপ্রিয় ওয়েবসাইট বহু ব্যবহারকারীর কাছে পৌঁছায়নি — সার্ভার সুস্থ ছিল, কিন্তু নাম আর ঠিকানায় রূপ নিচ্ছিল না। এরপর অনেক প্রতিষ্ঠান একাধিক DNS প্রদানকারী রাখার কথা গুরুত্ব দিয়ে ভাবতে শুরু করে। পরে মানেও একটি প্রতিরক্ষা যোগ হয়: authoritative নাগালে না থাকলে resolver মেয়াদোত্তীর্ণ উত্তর আরও কিছুক্ষণ দিতে পারে — “serve-stale” (RFC 8767, ২০২০)। লক্ষ করুন, এটি failover-এর উল্টো দিকে টানে: বিপদের সময় পুরোনো উত্তর ধরে রাখা।
ভালো নকশা তাই স্তরে স্তরে: স্বাভাবিক সময়ে মাঝারি TTL (৬০–৩০০ সেকেন্ড), migration-এর আগে আগেভাগে TTL কমানো, দ্রুত failover-এ স্থির anycast IP বা global load balancer, আর client-এ নিয়ন্ত্রিত retry (পর্ব ৪৮)। বিকলতা ধরতেই ৩০ সেকেন্ড লাগলে TTL ১ সেকেন্ডেও মোট সময় ৩০-এর নিচে নামবে না — দ্রুত detection প্রায়ই বেশি জরুরি।
মূল উপলব্ধি: TTL হলো দ্রুত বদল আর স্থিরতার মধ্যে একটি দর-কষাকষি; এক সেকেন্ডের TTL failover-কে তাৎক্ষণিক করে না, শুধু ঝুঁকিগুলো অন্য জায়গায় সরায়।
প্র ০৩Anycast কীভাবে একটি IP-কে পৃথিবীর শত জায়গায় বসায় — আর TCP-র জন্য তা কেন একটু ঝুঁকির?
Anycast routing-এর একটি সাধারণ নিয়ম কাজে লাগায়। Internet-এর বিভিন্ন network একে অন্যকে BGP দিয়ে জানায়, কোন ঠিকানা-ব্লক তাদের মাধ্যমে পৌঁছানো যায়। সাধারণত একটি ব্লক একটি জায়গা থেকেই ঘোষিত হয়। Anycast-এ একই ব্লক একসাথে অনেক শহর থেকে ঘোষণা করা হয়; প্রতিটি router নিজের হিসাবে সবচেয়ে ভালো পথটি বেছে নেয়। ফলে ঢাকার ব্যবহারকারীর packet যায় এক জায়গায়, লন্ডনের ব্যবহারকারীর আরেক জায়গায় — ঠিকানা কিন্তু একই।
সবচেয়ে পরিচিত প্রয়োগ DNS-এর root server. Root-এর পরিচয় মাত্র ১৩টি নামে (a থেকে m), পরিচালনা করে ১২টি প্রতিষ্ঠান; অথচ anycast-এর কারণে এদের instance পৃথিবীর এক হাজারেরও বেশি জায়গায় (সংখ্যা সময়ের সাথে বাড়ে)। DNS-এর জন্য anycast প্রায় আদর্শ: একটি প্রশ্ন, একটি উত্তর, সাধারণত একটি করে UDP packet — পরের প্রশ্ন অন্য জায়গায় গেলেও ক্ষতি নেই। একই কারণে বড় DDoS-এর ধাক্কাও অনেক জায়গায় ভাগ হয়ে যায়, কোনো একটি জায়গা একা ডোবে না — একটি স্বাভাবিক প্রতিরক্ষা।
TCP-র ঝুঁকি কোথায়? TCP connection-এর অবস্থা থাকে একটি নির্দিষ্ট সার্ভারে। Connection চলার সময় BGP-তে পথ বদলালে (কোনো link বিকল হলো, বা কোনো network নীতি বদলাল) পরের packet যেতে পারে অন্য শহরের সার্ভারে, যে এই connection চেনেই না — সে reset পাঠাবে, connection ভাঙবে। বাস্তবে এমন পথ বদল তুলনামূলক কম, আর বেশিরভাগ HTTP connection ছোট; তাই বড় CDN-গুলো TCP-তেও anycast সফলভাবে চালায়। তবু দীর্ঘ connection-এ (বড় download, WebSocket) client-কে আবার সংযোগের জন্য প্রস্তুত থাকতে হয়। QUIC-এর connection ID এখানে কিছুটা সাহায্য করতে পারে, কারণ connection চেনা হয় ID দিয়ে, শুধু ঠিকানা দিয়ে নয় (বাস্তবায়নভেদে আলাদা)।
আরেকটি সীমা: BGP-র “সবচেয়ে ভালো পথ” মানে network-নীতির হিসাবে ভালো, সবসময় সবচেয়ে কম latency নয়; আর ঘোষণা তুলে নিলে traffic সরতে সেকেন্ড থেকে কয়েক মিনিট লাগতে পারে (network-ভেদে আলাদা) — তবে কোনো TTL-এর অপেক্ষা নেই।
মূল উপলব্ধি: anycast DNS-এর TTL ছাড়াই কাছের আর সুস্থ জায়গায় পাঠায়; অবস্থাহীন প্রশ্ন-উত্তরে এটি সবচেয়ে ভালো খাটে, আর অবস্থাসহ connection-এ পথ বদলের ঝুঁকি মাথায় রাখতে হয়।
প্র ০৪আলোর গতি কি সত্যিই শেষ কথা? মানুষ কয়েক মিলিসেকেন্ড বাঁচাতে কী করেছে, আর নকশাকারের শিক্ষা কী?
শেয়ারবাজারের দ্রুত trading-এর জগৎ দেখায়, সীমাটি কতটা বাস্তব আর তার কাছে যেতে মানুষ কত দাম দেয়। প্রকাশিত প্রতিবেদন অনুযায়ী ২০১০ সালের দিকে Spread Networks নামের একটি কোম্পানি শিকাগো আর নিউ ইয়র্ক অঞ্চলের বাজারের মধ্যে প্রায় সোজা পথে নতুন fibre বসায়, যাতে আগের পথের তুলনায় round trip কয়েক মিলিসেকেন্ড কমে। কয়েক বছরের মধ্যেই microwave টাওয়ারের লিংক তাকে হারিয়ে দেয়। কারণ পদার্থবিদ্যা: বাতাসে বেতার তরঙ্গ চলে প্রায় শূন্যস্থানের আলোর গতিতে, আর fibre-এর কাচে আলো চলে তার প্রায় দুই-তৃতীয়াংশ গতিতে। Microwave-এর bandwidth অনেক কম, বৃষ্টিতে সমস্যাও হয় — তবু যেখানে প্রতিটি মিলিসেকেন্ডের দাম আছে, সেখানে latency জিতেছে bandwidth-এর বিরুদ্ধে।
গবেষণাগারে hollow-core fibre (ফাঁপা কেন্দ্রের fibre) নিয়েও কাজ চলছে, যেখানে আলো মূলত বাতাসের ভেতর দিয়ে চলে বলে গতি বাড়ে; ব্যাপক প্রয়োগ এখনো সীমিত। কিন্তু খেয়াল করুন, এগুলো সবই সীমার দিকে এগোনো, সীমা ভাঙা নয়। শূন্যস্থানে আলোর পূর্ণ গতিতেও ঢাকা–US East-এর round trip প্রায় ৮৬ ms-এর কম হবে না (২ × ১২,৯০০ ÷ ৩,০০,০০০ সেকেন্ড)। আর বাস্তবের Internet সোজা পথে চলে না — গবেষণায় বারবার দেখা গেছে, মাপা RTT প্রায়ই আলোর গতির তাত্ত্বিক হিসাবের কয়েক গুণ।
System designer-এর জন্য তিনটি শিক্ষা।
- দূরত্ব একটি নকশা-সিদ্ধান্ত: ব্যবহারকারী কোথায়, তা জেনে region আর CDN বাছুন; সস্তা region-এর সাশ্রয় latency-তে খেয়ে ফেলতে পারে।
- Round trip কমানোই সবচেয়ে বড় optimization: পরপর ১০টি call-কে একটিতে আনলে যা লাভ, কোনো দ্রুত hardware তা দেয় না।
- Strong consistency-র দাম দূরত্বে: একাধিক region-এ একসাথে লেখা নিশ্চিত করতে হলে প্রতিটি লেখায় region পেরোনো অন্তত একটি round trip লাগে। Google-এর Spanner (২০১২)-এর মতো ব্যবস্থাও আলোর গতি এড়াতে পারে না; এই দর-কষাকষি পর্ব ৪০-এর (CAP, PACELC আর consistency model).
মূল উপলব্ধি: আলোর গতির সাথে লড়াই করা যায় না — কাছে যান, আর কম বার যান।
প্র ০৫Connection কেন দামি — C10K সমস্যা থেকে আজকের connection pool পর্যন্ত কী শিখেছি?
১৯৯৯ সালে Dan Kegel একটি ওয়েব পাতায় প্রশ্ন তোলেন: একটি সার্ভার কি একসাথে দশ হাজার client সামলাতে পারবে? এর নাম হয়ে যায় C10K problem. তখনকার প্রচলিত নকশা ছিল প্রতিটি connection-এর জন্য একটি process বা thread. দশ হাজার thread মানে প্রতিটির নিজস্ব stack-এর memory, আর OS-এর অবিরাম এক thread থেকে আরেক thread-এ বদলের খরচ; তার ওপর select বা poll-এর মতো পুরোনো পদ্ধতিতে প্রতিবার সব connection একে একে দেখতে হতো।
সমাধান এল event-driven নকশায়: অল্প কয়েকটি thread, আর OS-এর দক্ষ খবর দেওয়ার ব্যবস্থা (Linux-এর epoll, BSD-র kqueue), যা শুধু যে connection-এ কিছু ঘটেছে সেটিই জানায়। ২০০৪ সালে প্রকাশিত Nginx এবং পরে ২০০৯ সালের Node.js এই ধারার পরিচিত উদাহরণ। আজ এক যন্ত্রে লাখো দীর্ঘজীবী connection রাখা অস্বাভাবিক নয়।
তবু connection আজও দামি, শুধু অন্য জায়গায়:
- Database: PostgreSQL প্রতিটি client connection-এর জন্য একটি আলাদা process চালায়। শত শত app server প্রত্যেকে বড় pool খুললে database-এর memory আর CPU connection সামলাতেই ফুরায়। তাই মাঝখানে PgBouncer-এর মতো connection pooler বসানো হয়, যা হাজারো client connection-কে অল্প কিছু database connection-এ মেলায়।
- Proxy: অংশ ৫-এর হিসাবে একটি উৎস IP থেকে একটি backend-এ প্রতি সেকেন্ডে প্রায় ৪৭০টির বেশি নতুন connection টেকসই নয়, যদি প্রতিবার নতুন connection খোলা হয়।
- Mobile: প্রতিটি নতুন TLS connection ব্যাটারি আর data খরচ করে, আর দুর্বল network-এ handshake-ই সবচেয়ে ধীর অংশ।
নকশার নিয়মগুলো তাই: connection reuse করুন (keep-alive, pool, HTTP/2); দীর্ঘজীবী connection-এর সার্ভার — chat বা notification (পর্ব ১০, পর্ব ৫৫) — event-driven মডেলে বানান; প্রতিটি pool-এর সীমা নিচের সিস্টেমের সীমা থেকে উল্টো হিসাব করুন (Little-এর সূত্র, পর্ব ৪); আর connection-সংখ্যা monitor করুন — হঠাৎ বেড়ে যাওয়া প্রায়ই কোনো ধীর dependency-র প্রথম লক্ষণ (পর্ব ১৮)।
মূল উপলব্ধি: সময়ের হিসাব হয় RTT-এ, resource-এর হিসাব connection-এ — ভালো নকশা দুটোই গোনে।
অনুশীলন
কাগজ-কলমে হিসাব করুন, তারপর উত্তর মেলান। শেষ প্রশ্নে আগে অনুমান, তারপর calculator চালিয়ে যাচাই।
-
Time to first byte হিসাব: একটি কাল্পনিক অনলাইন বাজারের অ্যাপ। ব্যবহারকারী চট্টগ্রামে, সার্ভার সিঙ্গাপুরে; ধরা যাক RTT ৬০ ms. নামটি কোনো cache-এ নেই — resolver পর্যন্ত আর সেখান থেকে authoritative মিলিয়ে DNS-এ ৫০ ms. সার্ভারের কাজ ৩০ ms. প্রতিটি ক্ষেত্রে TTFB কত? (ক) TCP + TLS 1.2, (খ) TCP + TLS 1.3, (গ) QUIC-এর নতুন connection, (ঘ) আগে খোলা connection-এ দ্বিতীয় অনুরোধ, (ঙ) পণ্যের তালিকা ঢাকার একটি CDN edge থেকে এলে — RTT ১৫ ms, cache hit-এ edge-এর কাজ ২ ms, TLS 1.3, DNS একই। কোন অংশটি সবচেয়ে বড়?
সূত্র: TTFB = DNS + (round trip-এর সংখ্যা × RTT) + সার্ভারের কাজ।
- (ক) ৫০ + ৪ × ৬০ + ৩০ = ৩২০ ms
- (খ) ৫০ + ৩ × ৬০ + ৩০ = ২৬০ ms
- (গ) ৫০ + ২ × ৬০ + ৩০ = ২০০ ms (QUIC 0-RTT হলে ৫০ + ৬০ + ৩০ = ১৪০ ms, তবে শুধু idempotent অনুরোধে)
- (ঘ) DNS আর handshake লাগে না: ৬০ + ৩০ = ৯০ ms
- (ঙ) ৫০ + ৩ × ১৫ + ২ = ৯৭ ms
(খ)-তে ২৬০-এর ১২০ ms handshake-এ, ৫০ ms DNS-এ — সার্ভারের কাজ মাত্র ৩০. (ঙ)-তে handshake নেমে ৪৫ ms, আর সবচেয়ে বড় অংশ এখন DNS — ৯৭-এর ৫০, প্রায় ৫২%; তাই পরের উন্নতি অ্যাপ খোলার সাথেই আগেভাগে নাম খোঁজা আর connection খুলে রাখা।
-
Failover-এর জন্য TTL বাছাই (নকশা আর সমালোচনা): একটি কাল্পনিক mobile banking সেবার প্রয়োজন: primary region বিকল হলে ২ মিনিটের মধ্যে অন্তত ৯৫% resolver দ্বিতীয় region-এর IP দেবে। Health check প্রতি ১০ সেকেন্ডে, পরপর ৩ বার ব্যর্থ হলে বিকল ধরা হয়; DNS সেবায় record বদলাতে ধরা যাক ১০ সেকেন্ড। (ক) সর্বোচ্চ কত TTL চলবে? Resolver-এর cache এলোমেলো সময়ে ভরা ধরুন। (খ) TTL ৩০০ থেকে আপনার মানে নামালে authoritative-এ ভার কত বাড়ে, যদি ২০,০০০টি সক্রিয় resolver থাকে? (গ) একজন সহকর্মী TTL ৫ সেকেন্ড চান — সমালোচনা করুন। (ঘ) শুধু TTL ছাড়া আর কী করবেন?
- (ক) ধরা পড়া ৩০ + বদল ১০ = ৪০ সেকেন্ড; বাকি থাকে ১২০ − ৪০ = ৮০ সেকেন্ড। বদলের τ সেকেন্ড পরে পুরোনো IP-তে থাকা অংশ 1 − τ/TTL. শর্ত: 1 − 80/TTL ≤ 0.05, অর্থাৎ TTL ≤ 80 ÷ 0.95 ≈ ৮৪.২ সেকেন্ড. ১০০% চাইলে TTL ≤ ৮০. গোল একটি মান ৬০ সেকেন্ড দুই শর্তই মেলায়, সাথে ২০ সেকেন্ডের headroom.
- (খ) প্রতিটি সক্রিয় resolver প্রতি TTL-এ মোটামুটি একবার জিজ্ঞেস করে: TTL ৩০০-এ ২০,০০০ ÷ ৩০০ ≈ সেকেন্ডে ৬৭টি প্রশ্ন, TTL ৬০-এ ≈ ৩৩৩টি — ৫ গুণ, কিন্তু managed DNS-এর জন্য সাধারণত সামান্য। ব্যবহারকারীর দিকে DNS miss একটু বেশি ঘন ঘন হবে।
- (গ) TTL ৫-এ ভার ২০,০০০ ÷ ৫ = সেকেন্ডে ৪,০০০টি প্রশ্ন, ৩০০-এর ৬০ গুণ; অনেক resolver এত ছোট TTL বাড়িয়ে নিতে পারে; DNS সেবাদাতার বিভ্রাটে cache প্রায় সাথে সাথে খালি; আর লাভ সামান্য — সর্বোচ্চ সময় ১০০ থেকে ৪৫ সেকেন্ড, কারণ ৪০ সেকেন্ড detection আর বদলেই যায়। বড় লাভ detection দ্রুত করায়।
- (ঘ) Pool-এ connection-এর সর্বোচ্চ বয়স, আর বিকল region-এর error পেলেই connection বন্ধ করে নতুন করে নাম খোঁজা; client-এ নিয়ন্ত্রিত retry; দ্রুততম পথে স্থির anycast IP বা global load balancer; আর নিয়মিত failover-এর মহড়া (পর্ব ৫১)।
-
TCP, UDP না QUIC — তিনটি পরিস্থিতি: প্রতিটির জন্য transport বেছে নিন আর কারণ দিন। (ক) একটি কাল্পনিক mobile banking অ্যাপে টাকা পাঠানোর API. (খ) একটি কাল্পনিক টেলিমেডিসিন অ্যাপে ডাক্তার-রোগীর live ভিডিও কল। (গ) একটি কাল্পনিক ride-sharing অ্যাপে চালকের ফোন প্রতি ৪ সেকেন্ডে অবস্থান পাঠায়, network দুর্বল আর প্রায়ই Wi-Fi ও মোবাইল ডেটার মধ্যে বদলায়।
- (ক) TCP + TLS (HTTP/2), যেখানে চলে সেখানে HTTP/3 আর HTTP/2-তে ফেরার পথ। প্রতিটি byte ঠিকঠাক আর নিশ্চিতভাবে পৌঁছাতে হবে; নিজের UDP protocol বানানো অকারণ ঝুঁকি। এই অনুরোধে 0-RTT কখনো নয় (replay); সাথে idempotency key, timeout আর নিরাপদ retry (পর্ব ৮, ৪৮)।
- (খ) UDP-ভিত্তিক real-time media (WebRTC-র মতো ব্যবস্থা)। দেরিতে আসা ফ্রেম অর্থহীন, তাই আবার পাঠানোর বদলে jitter buffer আর ফাঁক ঢাকার কৌশল। UDP আটকানো network-এ TCP বা TLS-এর ওপর relay-তে ফেরার পথ — মান কমবে, কল টিকবে। Appointment আর chat চলবে আলাদা HTTPS-এ।
- (গ) QUIC বা HTTP/3: connection migration-এ network বদলেও connection টেকে, এক stream-এর loss অন্যটিকে আটকায় না, আবার যুক্ত হতে কম round trip. বার্তায় সময়-চিহ্ন রাখুন, দেরিতে আসা পুরোনো অবস্থান বাদ। সহজ বিকল্প দীর্ঘজীবী WebSocket — চলে, তবে network বদলালে নতুন connection লাগে। নিজের UDP protocol-এ congestion control, এনক্রিপশন আর NAT keepalive নিজে বানাতে হয় — সাধারণত দরকার নেই (পর্ব ৫৮)।
-
আগে অনুমান, তারপর চালান: অংশ ৪-এর TTFB calculator-এ (ক) RTT-এর তালিকায়
80যোগ করলে (অন্য কিছু না বদলে) নতুন দুটি সারিতে কী ছাপা হবে? (খ) আগের তালিকাই রেখেDNS.miss50 থেকে 120 করলে RTT 150-এর miss সারি আর শেষ লাইনটি কেমন হবে?(ক) প্রতিটি ঘর = DNS + round trip × ৮০ + ২০. Hit-এ ৪, ৩, ২, ১ round trip: ৩৪০, ২৬০, ১৮০, ১০০; miss-এ প্রতিটিতে ৫০ বেশি: ৩৯০, ৩১০, ২৩০, ১৫০; reused connection দুটিতেই ৮০ + ২০ = ১০০. চালিয়ে পাওয়া নতুন দুটি সারি:
80 hit 340 260 180 100 100 80 miss 390 310 230 150 100(খ) RTT 150-এর miss সারি: ১২০ + ৬০০ + ২০ = ৭৪০, ১২০ + ৪৫০ + ২০ = ৫৯০, ৪৪০, ২৯০; reused connection-এ DNS নেই, তাই ১৭০ — বদলায় না। শেষ লাইনও বদলায় না, “saves 450 ms”, কারণ দুই পাশেই একই DNS সময় যোগ হয়ে বিয়োগে কেটে যায়:
150 miss 740 590 440 290 170 RTT 150, DNS miss: TLS 1.2 -> QUIC 0-RTT saves 450 ms = 3 round trips
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমএকটি নতুন HTTPS অনুরোধের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- 📖 DNS-এ নাম থেকে IP ঠিকানা খোঁজা
- 🤝 TCP-র SYN আর SYN-ACK — connection খোলা
- 🔐 TLS-এর ClientHello আর ServerHello — চাবি ঠিক করা
- 📨 এনক্রিপ্ট করা HTTP অনুরোধ পাঠানো
- ⚙️ সার্ভারে অনুরোধের কাজ
- 📄 উত্তরের প্রথম byte ব্যবহারকারীর কাছে পৌঁছানো
সার্ভার পর্যন্ত RTT ১০০ ms, নামের ঠিকানা আগেই cache-এ আছে, আর সার্ভারের কাজের সময় নগণ্য। TCP + TLS 1.3-এর একটি নতুন HTTPS connection-এ প্রথম অনুরোধের উত্তরের প্রথম byte আসতে মোটামুটি কত সময় লাগবে?
- ১০০ ms
- ২০০ ms
- ৩০০ ms
- ৪০০ ms
দুটি শহরের দূরত্ব প্রায় ৬,০০০ km. Optical fibre-এ আলোর গতি প্রায় ২,০০,০০০ km/s ধরলে তাদের মধ্যে round trip time (RTT)-এর তাত্ত্বিক সর্বনিম্ন মান কত?
- ৬০ ms
- ৩০ ms
- ৪০ ms
- ৬ ms
একটি DNS record-এর TTL ৩০০ সেকেন্ড। একটি resolver সকাল ৯:৫৮:০০-তে record-টির উত্তর এনে cache-এ রাখল। সকাল ১০:০০:০০-তে record বদলে নতুন IP বসানো হলো। Resolver TTL মেনে চললে সবচেয়ে দেরিতে কখন পর্যন্ত পুরোনো IP দিতে পারে?
- ১০:০০:০০ — বদলের সাথে সাথে নতুন IP
- ১০:০৩:০০
- ১০:০৫:০০
- যতক্ষণ না ব্যবহারকারী browser বন্ধ করেন
HTTP/2-এ একটি TCP connection-এর ভেতরে তিনটি ফাইল তিনটি stream-এ একসাথে আসছে। পথে প্রথম ফাইলের একটি packet হারাল। সাধারণত কী ঘটে?
- শুধু প্রথম ফাইলের stream থামে, বাকি দুটি অ্যাপে পৌঁছে যায়
- পুরো connection বন্ধ হয়ে নতুন করে খোলে
- হারানো অংশ বাদ দিয়েই ফাইল দেখানো হয়
- হারানো packet আবার না আসা পর্যন্ত তিনটি stream-এর পরের ডেটাই অ্যাপের কাছে আটকে থাকে
একটি সেবা TLS 1.3-এর 0-RTT (early data) চালু করতে চায়। নিচের কোন অনুরোধটি early data-তে নেওয়া সবচেয়ে নিরাপদ?
- POST — এক হিসাব থেকে আরেক হিসাবে টাকা পাঠানো
- POST — login করে নতুন session খোলা
- GET — পণ্যের পাবলিক তালিকা পড়া
- DELETE — ব্যবহারকারীর account মুছে ফেলা
একটি reverse proxy-র উৎস IP একটি। প্রতিটি অনুরোধে সে একই backend-এর একই IP:port-এ নতুন TCP connection খোলে আর নিজেই বন্ধ করে। Ephemeral port-এর পরিসর 32768–60999 (২৮,২৩২টি), আর বন্ধের পর প্রতিটি port TIME_WAIT-এ ৬০ সেকেন্ড আটকে থাকে। প্রতি সেকেন্ডে টেকসইভাবে সর্বোচ্চ মোটামুটি কতগুলো নতুন connection খোলা যাবে?
- প্রায় ২৮টি
- প্রায় ৪৭০টি
- প্রায় ২৮,২৩২টি
- প্রায় ১৬ লাখ ৯৩ হাজার
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Network-সময় ≈ round trip-এর সংখ্যা × RTT; connection-এর দাম CPU, memory, port আর মাঝের যন্ত্রের টেবিলে — তাই connection reuse করুন।
- নতুন HTTPS: TCP + TLS 1.3 = ৩ RTT প্রথম byte পর্যন্ত (TLS 1.2-এ ৪, QUIC-এ ২, 0-RTT-এ ১), সাথে DNS আর সার্ভারের সময়; 0-RTT শুধু idempotent অনুরোধে।
- DNS failover-এর সর্বোচ্চ সময় ≈ ধরা পড়া + বদল + TTL, গড়ে TTL/২ বাড়তি; খোলা connection DNS জিজ্ঞেস করে না, আর সবাই TTL মানে না।
- HTTP/1.1-এ এক connection-এ একবারে একটি, HTTP/2-এ multiplexing কিন্তু TCP-র HOL, HTTP/3-এ QUIC-এর স্বাধীন stream আর migration; UDP তখন, যখন দেরিতে আসা ডেটা অর্থহীন বা transport নিজে বানানো হচ্ছে।
- Fibre-এ RTT ≥ d ÷ ১০০ ms — কাছে যান (CDN, region), কম বার যান; ভেতরে private VPC, সামনে শুধু LB; CGNAT-এ এক IP মানে এক মানুষ নয়।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ০৮ · REST API নকশা — resource, status code, pagination, versioning আর idempotencyপরবর্তী পর্বConnection-এর ওপর API-র ভাষা কেমন হবে, আর retry কীভাবে নিরাপদ হয়।
- পর্ব ০৬ · একটি নকশা কীভাবে এগোয় — requirement থেকে API, data model আর deep diveআগের পর্বনকশার ধাপ — যেখানে আজকের তীরগুলো আঁকা হয়েছিল।
- সিস্টেম ডিজাইন · কোর্স হোম৬৬টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- Computer Networks · DNS — নাম থেকে ঠিকানা, resolver আর cachingগভীরে যানZone, delegation, record আর DNS বার্তার ভেতরটা।
- Computer Networks · QUIC আর আধুনিক transportগভীরে যান1-RTT আর 0-RTT handshake, stream আর connection migration — packet ধরে ধরে।
- Computer Networks · নেটওয়ার্ক পারফরম্যান্সপাশের ট্র্যাকBandwidth-delay product, tuning আর ঠিকভাবে মাপার পদ্ধতি।