Module 2: Network Fundamentals for Distributed Systems
Why Network Knowledge Matters
Every distributed system operation involves the network. Understanding how networks work is essential for:
- Debugging latency issues
- Designing resilient systems
- Making informed protocol choices
- Capacity planning
The OSI Model (Simplified for Engineers)
┌─────────────────────────────────────────────────────────────────┐ │ OSI MODEL (Practical View) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Layer 7: Application │ HTTP, gRPC, WebSocket │ │ ───────────────────────────────────────────────────────────── │ │ Layer 6: Presentation │ TLS/SSL, Compression │ │ ───────────────────────────────────────────────────────────── │ │ Layer 5: Session │ (Usually merged with L7) │ │ ───────────────────────────────────────────────────────────── │ │ Layer 4: Transport │ TCP, UDP │ │ ───────────────────────────────────────────────────────────── │ │ Layer 3: Network │ IP, ICMP │ │ ───────────────────────────────────────────────────────────── │ │ Layer 2: Data Link │ Ethernet, WiFi │ │ ───────────────────────────────────────────────────────────── │ │ Layer 1: Physical │ Cables, Radio waves │ │ │ │ For distributed systems, focus on: │ │ • Layer 4 (TCP/UDP): Reliability, ordering │ │ • Layer 7 (HTTP/gRPC): API protocols │ │ • TLS: Security │ │ │ └─────────────────────────────────────────────────────────────────┘
TCP Deep Dive
TCP (Transmission Control Protocol) provides reliable, ordered, connection-oriented communication.
Three-Way Handshake
┌─────────────────────────────────────────────────────────────────┐ │ TCP THREE-WAY HANDSHAKE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Client Server │ │ │ │ │ │ │ ──────── SYN (seq=x) ─────────────────► │ │ │ │ "I want to connect" │ │ │ │ │ │ │ │ ◄─────── SYN-ACK (seq=y, ack=x+1) ───── │ │ │ │ "OK, I acknowledge" │ │ │ │ │ │ │ │ ──────── ACK (ack=y+1) ─────────────────►│ │ │ │ "Great, let's talk" │ │ │ │ │ │ │ │ ══════════ Connection Established ═══════│ │ │ │ │ │ │ │ │ Cost: 1.5 RTT before first data byte │ │ Same datacenter: ~0.5ms × 1.5 = 0.75ms │ │ Cross-continent: ~150ms × 1.5 = 225ms │ │ │ │ Optimization: TCP Fast Open (TFO) │ │ - Sends data with SYN packet │ │ - Reduces handshake overhead for repeat connections │ │ │ └─────────────────────────────────────────────────────────────────┘
TCP Flow Control
┌─────────────────────────────────────────────────────────────────┐ │ TCP FLOW CONTROL │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Problem: Sender might overwhelm receiver │ │ │ │ Solution: Sliding Window │ │ │ │ Sender's View: │ │ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │10 │11 │12 │ │ │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ │ │ └─ACKed─┘└───────Can Send───────┘└───Cannot Send──┘ │ │ └─────Window Size──────┘ │ │ │ │ Receiver advertises window size in each ACK: │ │ "I can accept N more bytes" │ │ │ │ Window = 0: Sender must stop (receiver buffer full) │ │ │ │ Tuning for high-bandwidth links: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Default window: 64KB │ │ │ │ With window scaling: Up to 1GB │ │ │ │ │ │ │ │ Bandwidth × RTT = Required Window Size │ │ │ │ 10 Gbps × 100ms = 125 MB window needed! │ │ │ │ │ │ │ │ Linux: net.ipv4.tcp_window_scaling = 1 │ │ │ │ net.core.rmem_max = 16777216 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
TCP Congestion Control
┌─────────────────────────────────────────────────────────────────┐ │ TCP CONGESTION CONTROL │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Problem: Network might be congested (different from receiver) │ │ │ │ Congestion Window (cwnd) growth: │ │ │ │ cwnd│ │ │ │ ┌────────────────── │ │ │ ╱╲ │ Congestion │ │ │ ╱╲ ╱ ╲ │ Avoidance │ │ │ ╱╲ ╱ ╲╱ ╲│ (linear growth) │ │ │ ╱╲ ╱ ╲╱ │ │ │╱╲ ╱ ╲╱ │ │ │ ╲╱ Packet loss! │ │ │ Slow Start cwnd halved │ │ │ (exponential) │ │ │ └─────────────────────────────┴───────────────► time │ │ │ │ Algorithms: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Reno │ Classic, aggressive backoff │ │ │ │ CUBIC │ Linux default, better for high-BW links │ │ │ │ BBR │ Google's model-based, best for modern nets │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Impact on distributed systems: │ │ • New connections start slow (slow start) │ │ • Long-lived connections more efficient │ │ • Connection pooling matters! │ │ │ └─────────────────────────────────────────────────────────────────┘
TCP TIME_WAIT
┌─────────────────────────────────────────────────────────────────┐ │ TCP TIME_WAIT │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ When connection closes, port enters TIME_WAIT for 2×MSL │ │ (MSL = Maximum Segment Lifetime, typically 60 seconds) │ │ │ │ Why? To handle delayed packets from old connection │ │ │ │ Problem at scale: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 10,000 RPS × 120 seconds TIME_WAIT = 1.2M ports stuck! │ │ │ │ Only 65,535 ports available per IP │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Solutions: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 1. Connection pooling (reuse connections) │ │ │ │ 2. SO_REUSEADDR socket option │ │ │ │ 3. tcp_tw_reuse = 1 (Linux) │ │ │ │ 4. Multiple IP addresses for high-volume clients │ │ │ │ 5. Let server close connection (TIME_WAIT on server) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Monitoring: netstat -an | grep TIME_WAIT | wc -l │ │ │ └─────────────────────────────────────────────────────────────────┘
UDP: When TCP is Too Much
┌─────────────────────────────────────────────────────────────────┐ │ UDP │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ UDP = "Send and pray" │ │ │ │ Properties: │ │ • No connection setup (no handshake) │ │ • No guaranteed delivery │ │ • No ordering │ │ • No congestion control │ │ • Very low overhead (8 byte header vs 20+ for TCP) │ │ │ │ When to use UDP: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ • Real-time video/audio (late data is useless data) │ │ │ │ • Gaming (responsiveness > reliability) │ │ │ │ • DNS queries (simple request/response) │ │ │ │ • Service discovery (multicast) │ │ │ │ • When you'll build reliability yourself (QUIC) │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ UDP in distributed systems: │ │ • Gossip protocols often use UDP │ │ • Health checks (faster than TCP) │ │ • Metrics collection (statsd) │ │ • Log shipping (syslog) │ │ │ └─────────────────────────────────────────────────────────────────┘
HTTP Evolution
HTTP/1.1 Limitations
┌─────────────────────────────────────────────────────────────────┐ │ HTTP/1.1 PROBLEMS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Problem 1: Head-of-Line Blocking │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Connection 1: │ │ │ │ [Request 1]────────────────────[Response 1 (slow)] │ │ │ │ [Request 2] BLOCKED waiting... │ │ │ │ │ │ │ │ Requests must complete in order on each connection! │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Problem 2: One request per connection │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Browser workaround: Open 6 connections per host │ │ │ │ But: 6 TCP handshakes, 6 TLS handshakes, 6× memory │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Problem 3: Verbose headers │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Every request sends full headers (500-800 bytes) │ │ │ │ Including: cookies, user-agent, accept headers │ │ │ │ Same headers, every single request! │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Problem 4: Text-based protocol │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Parsing text is slower than parsing binary │ │ │ │ More bytes on the wire │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
HTTP/2: Multiplexing
┌─────────────────────────────────────────────────────────────────┐ │ HTTP/2 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Key Innovation: Streams over single connection │ │ │ │ HTTP/1.1: HTTP/2: │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────────────────────────┐ │ │ │Conn1│ │Conn2│ │Conn3│ │ Single Connection │ │ │ │ R1 │ │ R2 │ │ R3 │ │ ┌───┐┌───┐┌───┐┌───┐ │ │ │ └─────┘ └─────┘ └─────┘ │ │S1 ││S2 ││S3 ││S4 │ │ │ │ │ └───┘└───┘└───┘└───┘ │ │ │ 3 TCP connections │ Multiplexed streams │ │ │ 3 TLS handshakes └─────────────────────────┘ │ │ 1 TCP + 1 TLS │ │ │ │ Features: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ ✓ Binary framing (faster parsing) │ │ │ │ ✓ Header compression (HPACK) │ │ │ │ ✓ Stream prioritization │ │ │ │ ✓ Server push │ │ │ │ ✓ Flow control per stream │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Remaining problem: TCP head-of-line blocking │ │ If one TCP packet is lost, ALL streams wait for retransmit │ │ │ └─────────────────────────────────────────────────────────────────┘
HTTP/3: QUIC
┌─────────────────────────────────────────────────────────────────┐ │ HTTP/3 (QUIC) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ QUIC = UDP + reliability + encryption + multiplexing │ │ (Google, now IETF standard) │ │ │ │ TCP + TLS 1.3: QUIC: │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ TCP Handshake: 1 RTT│ │ │ │ │ │ TLS Handshake: 1 RTT│ │ Combined: 1 RTT │ │ │ │ ─────────────────── │ │ (0 RTT for repeat) │ │ │ │ Total: 2-3 RTT │ │ │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ │ │ Benefits: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ ✓ No TCP head-of-line blocking (loss affects 1 stream) │ │ │ │ ✓ Faster connection setup (1 RTT, 0 RTT for resumption)│ │ │ │ ✓ Connection migration (survives network switch) │ │ │ │ ✓ Built-in encryption (can't be stripped) │ │ │ │ ✓ Better congestion control │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Adoption: │ │ • Google: All Chrome-to-Google traffic │ │ • Cloudflare: 25%+ of traffic │ │ • Meta: Used for mobile apps │ │ │ │ When to use HTTP/3: │ │ • High latency networks (mobile, satellite) │ │ • Lossy networks │ │ • Connection migration needed (mobile users) │ │ │ └─────────────────────────────────────────────────────────────────┘
gRPC: High-Performance RPC
┌─────────────────────────────────────────────────────────────────┐ │ gRPC │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ gRPC = HTTP/2 + Protocol Buffers + Code Generation │ │ │ │ Stack: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Application (Your Code) │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ Generated Stubs (type-safe client/server) │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ gRPC Framework (serialization, framing) │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ HTTP/2 (multiplexing, flow control) │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ TLS (encryption) │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ TCP │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Four RPC patterns: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 1. Unary: Request → Response │ │ │ │ rpc GetUser(GetUserRequest) returns (User); │ │ │ │ │ │ │ │ 2. Server Streaming: Request → Stream of Responses │ │ │ │ rpc ListUsers(Filter) returns (stream User); │ │ │ │ │ │ │ │ 3. Client Streaming: Stream of Requests → Response │ │ │ │ rpc UploadFile(stream Chunk) returns (Status); │ │ │ │ │ │ │ │ 4. Bidirectional: Stream ↔ Stream │ │ │ │ rpc Chat(stream Msg) returns (stream Msg); │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
gRPC Example
// user.proto syntax = "proto3"; package user; service UserService { rpc GetUser(GetUserRequest) returns (User); rpc ListUsers(ListUsersRequest) returns (stream User); rpc CreateUser(CreateUserRequest) returns (User); } message GetUserRequest { string user_id = 1; } message User { string user_id = 1; string name = 2; string email = 3; int64 created_at = 4; } message ListUsersRequest { int32 page_size = 1; string page_token = 2; } message CreateUserRequest { string name = 1; string email = 2; }
gRPC vs REST
┌─────────────────────────────────────────────────────────────────┐ │ gRPC vs REST │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Feature │ gRPC │ REST │ │ ─────────────────┼───────────────────┼─────────────────────────│ │ Protocol │ HTTP/2 │ HTTP/1.1 or HTTP/2 │ │ Format │ Protobuf (binary) │ JSON (text) │ │ Schema │ Required (.proto) │ Optional (OpenAPI) │ │ Code gen │ Yes (multi-lang) │ Optional │ │ Streaming │ Built-in │ Not native │ │ Browser support │ Limited* │ Native │ │ Payload size │ Smaller │ Larger │ │ Debugging │ Harder │ Easier │ │ │ │ * grpc-web exists but adds complexity │ │ │ │ Choose gRPC when: │ │ • Internal microservices │ │ • High-performance required │ │ • Streaming needed │ │ • Strong typing valuable │ │ │ │ Choose REST when: │ │ • Public API │ │ • Browser clients │ │ • Simplicity preferred │ │ • Wide tooling ecosystem needed │ │ │ └─────────────────────────────────────────────────────────────────┘
Network Partitions
┌─────────────────────────────────────────────────────────────────┐ │ NETWORK PARTITIONS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ A network partition occurs when network failure splits │ │ nodes into groups that cannot communicate. │ │ │ │ Before partition: During partition: │ │ ┌─────────────────────┐ ┌─────────────────────┐ │ │ │ A ←──► B ←──► C │ │ A ←──► B ✗ C │ │ │ │ │ │ │ │ │ │ │ ║ │ │ │ │ │ ▼ ▼ ▼ │ │ ▼ ▼ ║ ▼ │ │ │ │ D ←──► E ←──► F │ │ D ←──► E ✗ F │ │ │ └─────────────────────┘ └─────────────────────┘ │ │ Partition 1 │ Partition 2 │ │ (A,B,D,E) │ (C,F) │ │ │ │ Types of partitions: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Complete: No communication possible │ │ │ │ Partial: Some paths work, others don't │ │ │ │ Asymmetric: A can reach B, but B can't reach A │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Real-world causes: │ │ • Switch/router failure │ │ • Misconfigured firewall │ │ • Network congestion (packets dropped) │ │ • Submarine cable damage │ │ • Cloud provider network issues │ │ │ └─────────────────────────────────────────────────────────────────┘
Handling Partitions
┌─────────────────────────────────────────────────────────────────┐ │ PARTITION HANDLING STRATEGIES │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Strategy 1: Majority Quorum (CP systems) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Only partition with majority continues accepting writes │ │ │ │ │ │ │ │ [A B C] | [D E] A,B,C have majority (3/5) │ │ │ │ ✓ writes │ ✗ readonly │ │ │ │ │ │ │ │ Used by: ZooKeeper, etcd, Consul │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Strategy 2: Accept All Writes (AP systems) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Both partitions accept writes, resolve conflicts later │ │ │ │ │ │ │ │ [A B C] | [D E] Both accept writes │ │ │ │ ✓ writes │ ✓ writes │ │ │ │ │ │ │ │ │ When partition heals: merge with conflict resolution │ │ │ │ │ │ │ │ Used by: Cassandra, DynamoDB, CouchDB │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Strategy 3: Designated Primary │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ Pre-assign which datacenter is primary │ │ │ │ │ │ │ │ [Primary] | [Secondary] │ │ │ │ ✓ writes │ ✗ writes, serve stale reads │ │ │ │ │ │ │ │ Simple but primary region is single point of failure │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
DNS: The Phone Book of the Internet
┌─────────────────────────────────────────────────────────────────┐ │ DNS RESOLUTION │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Client wants: api.example.com │ │ │ │ ┌─────────┐ ┌──────────────┐ │ │ │ Client │────►│ Local DNS │ (ISP or corporate) │ │ └─────────┘ │ Resolver │ │ │ └──────┬───────┘ │ │ │ Not in cache │ │ ▼ │ │ ┌──────────────┐ │ │ │ Root DNS │ "Ask .com servers" │ │ │ (.) │ │ │ └──────┬───────┘ │ │ ▼ │ │ ┌──────────────┐ │ │ │ TLD DNS │ "Ask example.com servers" │ │ │ (.com) │ │ │ └──────┬───────┘ │ │ ▼ │ │ ┌──────────────┐ │ │ │ Authoritative│ "api.example.com = 1.2.3.4" │ │ │ (example.com)│ │ │ └──────────────┘ │ │ │ │ DNS in distributed systems: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ • Service discovery (internal DNS for services) │ │ │ │ • Load balancing (multiple A records) │ │ │ │ • Failover (health-checked DNS) │ │ │ │ • Geo-routing (return nearest IP) │ │ │ │ │ │ │ │ Caveats: │ │ │ │ • TTL means changes propagate slowly │ │ │ │ • Clients may cache beyond TTL │ │ │ │ • Not suitable for rapid failover │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
TLS and mTLS
┌─────────────────────────────────────────────────────────────────┐ │ TLS HANDSHAKE │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ TLS 1.3 (current standard): │ │ │ │ Client Server │ │ │ │ │ │ │ ──── ClientHello + KeyShare ──────────►│ │ │ │ (supported ciphers, key material) │ │ │ │ │ │ │ │ ◄──── ServerHello + KeyShare ────────── │ │ │ │ Certificate │ │ │ │ CertificateVerify │ │ │ │ Finished │ │ │ │ │ │ │ │ ──── Finished ─────────────────────────►│ │ │ │ │ │ │ │ ═══════ Encrypted Data ═════════════════│ │ │ │ │ TLS 1.3 improvements: │ │ • 1-RTT handshake (vs 2-RTT in TLS 1.2) │ │ • 0-RTT resumption (for repeat connections) │ │ • Removed weak ciphers │ │ • Forward secrecy mandatory │ │ │ └─────────────────────────────────────────────────────────────────┘
mTLS (Mutual TLS)
┌─────────────────────────────────────────────────────────────────┐ │ MUTUAL TLS (mTLS) │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Regular TLS: Only server proves identity │ │ mTLS: Both client AND server prove identity │ │ │ │ Client Server │ │ │ │ │ │ │ ──── ClientHello ─────────────────────► │ │ │ │ │ │ │ │ ◄──── ServerCertificate ─────────────── │ │ │ │ (server proves identity) │ │ │ │ │ │ │ │ ──── ClientCertificate ────────────────►│ │ │ │ (client proves identity) │ │ │ │ │ │ │ │ ═══════ Encrypted + Authenticated ══════│ │ │ │ │ Use cases in distributed systems: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ • Service-to-service authentication │ │ │ │ • Zero trust networking │ │ │ │ • Service mesh (Istio, Linkerd) │ │ │ │ • Kubernetes pod-to-pod communication │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Certificate management: │ │ • Short-lived certificates (hours/days) │ │ • Automatic rotation │ │ • Certificate authority per environment │ │ │ └─────────────────────────────────────────────────────────────────┘
Linux Network Tuning
┌─────────────────────────────────────────────────────────────────┐ │ LINUX NETWORK TUNING PARAMETERS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ Connection handling: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ # Max connections waiting to be accepted │ │ │ │ net.core.somaxconn = 65535 │ │ │ │ │ │ │ │ # SYN backlog (incomplete connections) │ │ │ │ net.ipv4.tcp_max_syn_backlog = 65535 │ │ │ │ │ │ │ │ # Enable SYN cookies (DDoS protection) │ │ │ │ net.ipv4.tcp_syncookies = 1 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Buffer sizes: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ # Receive buffer │ │ │ │ net.core.rmem_max = 16777216 │ │ │ │ net.core.rmem_default = 1048576 │ │ │ │ │ │ │ │ # Send buffer │ │ │ │ net.core.wmem_max = 16777216 │ │ │ │ net.core.wmem_default = 1048576 │ │ │ │ │ │ │ │ # TCP buffers (min, default, max) │ │ │ │ net.ipv4.tcp_rmem = 4096 1048576 16777216 │ │ │ │ net.ipv4.tcp_wmem = 4096 1048576 16777216 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ TIME_WAIT handling: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ # Reuse TIME_WAIT sockets │ │ │ │ net.ipv4.tcp_tw_reuse = 1 │ │ │ │ │ │ │ │ # Max TIME_WAIT sockets │ │ │ │ net.ipv4.tcp_max_tw_buckets = 1440000 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ Keepalive: │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ net.ipv4.tcp_keepalive_time = 600 │ │ │ │ net.ipv4.tcp_keepalive_intvl = 60 │ │ │ │ net.ipv4.tcp_keepalive_probes = 3 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
Interview Questions
Conceptual Questions
-
Explain the TCP three-way handshake and its purpose.
- SYN → SYN-ACK → ACK
- Purpose: Establish connection, synchronize sequence numbers
- Cost: 1.5 RTT before data transfer
-
What is head-of-line blocking and how do HTTP/2 and HTTP/3 address it?
- HTTP/1.1: Requests queue on connection
- HTTP/2: Multiplexing, but TCP HOL blocking remains
- HTTP/3 (QUIC): Stream independence, loss affects only one stream
-
When would you choose gRPC over REST?
- Internal services, high performance needs
- Streaming required, strong typing valuable
- REST for public APIs, browser clients
-
What is a network partition? How do systems handle it?
- Network failure splits nodes into isolated groups
- CP systems: Majority quorum continues
- AP systems: All partitions accept writes, reconcile later
System Design Questions
-
Design a service-to-service authentication system.
- mTLS for mutual authentication
- Short-lived certificates with automatic rotation
- Service identity tied to certificates
- Certificate authority infrastructure
-
How would you optimize network performance for a latency-sensitive service?
- Connection pooling (avoid TCP handshake)
- HTTP/2 or gRPC (multiplexing)
- TCP tuning (buffers, keepalive)
- Geographic distribution
- Binary protocols (protobuf vs JSON)
Summary
┌─────────────────────────────────────────────────────────────────┐ │ MODULE 2: KEY TAKEAWAYS │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. TCP provides reliability but has costs: │ │ • Handshake latency │ │ • Head-of-line blocking │ │ • TIME_WAIT accumulation │ │ │ │ 2. HTTP evolution addresses real problems: │ │ • HTTP/2: Multiplexing, header compression │ │ • HTTP/3: UDP-based, no TCP HOL blocking │ │ │ │ 3. gRPC excels for internal services: │ │ • HTTP/2 + Protobuf + streaming │ │ • Type-safe, code generation │ │ │ │ 4. Network partitions are inevitable: │ │ • Design for partition tolerance │ │ • Choose CP or AP based on requirements │ │ │ │ 5. Security: TLS everywhere, mTLS for services │ │ │ │ 6. Tune Linux networking for high-scale │ │ │ └─────────────────────────────────────────────────────────────────┘
Next Module: Serialization and Data Exchange - JSON, Protocol Buffers, Avro, and choosing the right format.