ЁЯПл The SchoolтА║ЁЯХ╕я╕П NetworkingтА║ЁЯПк рдзрдбрд╛ 11 тАФ Load balancers, proxies рдЖрдгрд┐ CDNs: рд╕реНрд╡рд╛рдЧрдд рдХрдХреНрд╖
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯПк рдзрдбрд╛ 11 тАФ Load balancers, proxies рдЖрдгрд┐ CDNs: рд╕реНрд╡рд╛рдЧрдд рдХрдХреНрд╖

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 11 ┬╖ рдкреБрдвреЗ: lesson-12-debugging


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ11. рдПрдХ рдирд╛рд╡, рдЕрдиреЗрдХ counters: рдкрд╛рд╣реБрдгреНрдпрд╛рдВрдирд╛ рд╡рд╛рдЯреВрди рджреЗрдгрд╛рд░рд╛, рдЖрд░реЛрдЧреНрдп рддрдкрд╛рд╕рдгрд╛рд░рд╛ рдЖрдгрд┐ рд╕реАрд▓ рдХреЗрд▓реЗрд▓рд╛ рд▓рдЦреЛрдЯрд╛ рддрд┐рдереЗрдЪ рдЙрдШрдбрдгрд╛рд░рд╛ desk тАФ рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ рд╢рд╣рд░рд╛рдд рд╕реВрдЪрдирд╛-рдлрд▓рдХрд╛рдЪреА рдПрдХ рдкреНрд░рдд.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рд╣рдЬрд╛рд░ рдкрд╛рд╣реБрдгреЗ "рдХрд╛рд░реНрдпрд╛рд▓рдп" рдорд╛рдЧрддрд╛рдд. рддреЗ рд╕рдЧрд│реЗ рдПрдХрд╛рдЪ desk рд╡рд░ рдЬрд╛рдК рд╢рдХрдд рдирд╛рд╣реАрдд. рдореНрд╣рдгреВрди рд╕рдореЛрд░ рдПрдХ рд╕реНрд╡рд╛рдЧрдд рдХрдХреНрд╖ рдЙрднрд╛ рдЕрд╕рддреЛ: рддреЛ рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд╣реБрдгреНрдпрд╛рд▓рд╛ рд░рд┐рдХрд╛рдореНрдпрд╛ counter рдХрдбреЗ рдкрд╛рдард╡рддреЛ, рдЖрдЬрд╛рд░реА рд░рдЬреЗрд╡рд░ рдЕрд╕рд▓реЗрд▓рд╛ counter рд╡рдЧрд│рддреЛ (health check), рдЖрдгрд┐ рд╕реАрд▓ рдХреЗрд▓реЗрд▓рд╛ рд▓рдЦреЛрдЯрд╛ рд╕реНрд╡рддрдГрдЪ рд╡рд╛рдЪреВ рд╢рдХрддреЛ рдореНрд╣рдгрдЬреЗ counters рдирд╛ рддреЗ рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧрдд рдирд╛рд╣реА. reverse proxy рдореНрд╣рдгрдЬреЗ рдереЛрдбреНрдпрд╛ рдЬрд╛рд╕реНрдд рд╢рд┐рд╖реНрдЯрд╛рдЪрд╛рд░рд╛рдВрдЪрд╛ рддреЛрдЪ desk: рддреЛ рдЪрд┐рдареНрдареА рдкреБрдиреНрд╣рд╛ рд▓рд┐рд╣реВ рд╢рдХрддреЛ, рдЙрддреНрддрд░ cache рдХрд░реВ рд╢рдХрддреЛ, рдХрд┐рдВрд╡рд╛ рдкрд╛рд╣реБрдгрд╛ рдЦрд░реЛрдЦрд░ рдХреБрдареВрди рдЖрд▓рд╛ рддреЗ рд╕рд╛рдВрдЧрдгрд╛рд░реА рдЯреАрдк рдЬреЛрдбреВ рд╢рдХрддреЛ. CDN рдореНрд╣рдгрдЬреЗ рдкреНрд░рддреНрдпреЗрдХ рд╢рд╣рд░рд╛рддрд▓рд╛, рд╕реВрдЪрдирд╛-рдлрд▓рдХрд╛рдЪреА рдкреНрд░рдд рдЕрд╕рд▓реЗрд▓рд╛ рд╕реНрд╡рд╛рдЧрдд рдХрдХреНрд╖ тАФ рд╡рд╛рдЪрдХрд╛рд▓рд╛ рддреНрдпрд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡рд╛рдд рдЬрд╡рд│рдЪреА рдкреНрд░рдд рдорд┐рд│рддреЗ.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart LR
  V["ЁЯСе visitors"] --> LB["ЁЯПк load balancer<br/>L4: ip:port ┬╖ L7: URL, headers<br/>TLS ends here ┬╖ health checks"]
  LB --> A["counter 1 тЬЕ"] ; LB --> B["counter 2 тЬЕ"] ; LB -.->|unhealthy| C["counter 3 тЭМ"]
  V --> CDN["ЁЯМН CDN edge<br/>static files by URL"]

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рд╕рдореЛрд░ desk рдЕрд╕рд▓реНрдпрд╛рд╢рд┐рд╡рд╛рдп horizontally scale рдХрд░рдгреЗ рдЕрд╢рдХреНрдп рдЖрд╣реЗ. рдЬрдЧрднрд░рд╛рддрд▓реНрдпрд╛ рдкреНрд░реЗрдХреНрд╖рдХрд╛рдВрд╕рд╛рдареА latency рдордзрд▓реЗ рдмрд╣реБрддреЗрдХ рдлрд╛рдпрджреЗ рдЬрд▓рдж servers рдордзреВрди рдирд╛рд╣реА, рддрд░ CDN рдордзреВрди рдпреЗрддрд╛рдд. рдЖрдгрд┐ рдмрд╣реБрддреЗрдХ "load balancer рдмрд┐рдШрдбрд▓рд╛ рдЖрд╣реЗ" рдореНрд╣рдгрдЬреЗ fail рд╣реЛрдгрд╛рд░рд╛ health check рдЕрд╕рддреЛ.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

desk рд╕рд╛рдареА рд╕реНрд╡рддрдГ рдЪрд╛рд▓рд╡рдгреНрдпрд╛рд╕рд╛рд░рдЦреЗ рдХрд╛рд╣реА рдирд╛рд╣реА; рддреБрдореНрд╣реА рдЖрдзреАрдЪ рдЪрд╛рд▓рд╡рд▓реЗрд▓реЗ рджреЛрди рд╡рд┐рднрд╛рдЧ рдореНрд╣рдгрдЬреЗ рддреЛ рдмреЛрд▓рдд рдЕрд╕рд▓реЗрд▓реЗ рджреЛрди protocols. рдХреЛрдгрддреНрдпрд╛рд╣реА рдореЛрдареНрдпрд╛ site рд╡рд┐рд░реБрджреНрдз curl -sI рдХреЗрд▓реНрдпрд╛рд╕ desk рдЪреНрдпрд╛ рдЦреБрдгрд╛ рджрд┐рд╕рддрд╛рдд: server: cloudflare, via, x-cache: HIT.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

curl -sI https://www.wikipedia.org | grep -iE 'server|via|x-cache|cf-ray|age'     # the desk's headers
curl -sI https://example.com -H 'X-Forwarded-For: 203.0.113.9' | head -1            # the note the proxy adds (harmless here)
python3 -m http.server 8081 & python3 -m http.server 8082 &                          # two counters; a one-line desk in front:
python3 - <<'EOF'
import http.server, urllib.request, itertools
up = itertools.cycle(["8081", "8082"])
class LB(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        p = next(up); r = urllib.request.urlopen(f"http://127.0.0.1:{p}{self.path}")
        self.send_response(200); self.send_header("X-Served-By", p); self.end_headers(); self.wfile.write(r.read()[:200])
print("desk on :8000 тЖТ 8081, 8082 round-robin"); http.server.HTTPServer(("127.0.0.1", 8000), LB).serve_forever()
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

Wikipedia CDN/proxy рдЪреЗ рдирд╛рд╡ рд╕рд╛рдВрдЧрдгрд╛рд░рд╛ server: header рдЖрдгрд┐ age рдХрд┐рдВрд╡рд╛ cache header рджреЗрдКрди рдЙрддреНрддрд░ рджреЗрддреЗ. рдкреБрдиреНрд╣рд╛ рдкреБрдиреНрд╣рд╛ curl -sI localhost:8000 рдХреЗрд▓реНрдпрд╛рд╡рд░ рддреБрдордЪрд╛ рдЦреЗрд│рдгреНрдпрд╛рддрд▓рд╛ desk X-Served-By: 8081 рдЖрдгрд┐ 8082 рдЖрд▓рдЯреВрди рдкрд╛рд▓рдЯреВрди рджреЗрддреЛ.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

load balancer рдореНрд╣рдгрдЬреЗ рдкреБрдвреЗ рдкрд╛рдард╡рдгрд╛рд░рд╛ рдПрдХ рд╕рд╛рдзрд╛ program; рддреНрдпрд╛рдЪреЗ рдореВрд▓реНрдп health checks, TLS termination рдЖрдгрд┐ routing rules рдордзреНрдпреЗ рдЖрд╣реЗ тАФ рдЖрдгрд┐ рддрд┐рдиреНрд╣реА рддреБрдореНрд╣рд╛рд▓рд╛ headers рдордзреНрдпреЗ рджрд┐рд╕рддрд╛рдд.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: ALB рд╡рд┐рд░реБрджреНрдз NLB, Ingress controllers, рд╕рдЧрд│реНрдпрд╛рд╕рдореЛрд░ Cloudflare тАФ TLS, WAF, rate limits рдЖрдгрд┐ canaries рдпрд╛ desk рд╡рд░рдЪ рд░рд╛рд╣рддрд╛рдд. API рд╢рд╛рд│реЗрдЪрд╛ gateway (рдзрдбрд╛ 12) рдореНрд╣рдгрдЬреЗ auth рдЬреЛрдбрд▓реЗрд▓рд╛ рд╣рд╛рдЪ desk.

тПня╕П рдкреБрдвреЗ

рдзрдбрд╛ 12 тАФ network рдЪреЗ debugging: рд╕рд╣рд╛ рдкрд╛рдпрд▒реНрдпрд╛рдВрдЪреА рд╢рд┐рдбреА рдЖрдгрд┐ рд╕рд╛рдзрдирдкреЗрдЯреА.

ЁЯПк Lesson 11 тАФ Load balancers, proxies & CDNs: the reception desk

ЁЯУН You are here: Lesson 11 of 12 ┬╖ Next: lesson-12-debugging


ЁЯУж What's in this branch

Lessons 01тАУ11. One name, many counters: the desk that spreads visitors, checks health and ends the sealed envelope тАФ and the copy of the notice board in every city.

ЁЯзТ Explain like I'm 5

A thousand visitors ask for "the office". They cannot all go to one desk. So a reception desk stands in front: it sends each visitor to a free counter, skips a counter that is off sick (health check), and can read the sealed envelope itself so the counters do not have to. A reverse proxy is the same desk with extra manners: it may rewrite the slip, cache the answer, or add a note saying where the visitor really came from. A CDN is a reception desk in every city with a copy of the notice board тАФ the reader gets the copy nearest them.

ЁЯЧ║я╕П Diagram

flowchart LR
  V["ЁЯСе visitors"] --> LB["ЁЯПк load balancer<br/>L4: ip:port ┬╖ L7: URL, headers<br/>TLS ends here ┬╖ health checks"]
  LB --> A["counter 1 тЬЕ"] ; LB --> B["counter 2 тЬЕ"] ; LB -.->|unhealthy| C["counter 3 тЭМ"]
  V --> CDN["ЁЯМН CDN edge<br/>static files by URL"]

тЭУ What

ЁЯдФ Why

Scaling horizontally is impossible without a desk in front. Most latency wins for a global audience come from a CDN, not from faster servers. And most "the load balancer is broken" is a failing health check.

ЁЯФз How (in this repo)

Nothing to run for the desk itself; the two sections you already ran are the two protocols it speaks. curl -sI against any big site shows the desk's fingerprints: server: cloudflare, via, x-cache: HIT.

ЁЯзк Try it

curl -sI https://www.wikipedia.org | grep -iE 'server|via|x-cache|cf-ray|age'     # the desk's headers
curl -sI https://example.com -H 'X-Forwarded-For: 203.0.113.9' | head -1            # the note the proxy adds (harmless here)
python3 -m http.server 8081 & python3 -m http.server 8082 &                          # two counters; a one-line desk in front:
python3 - <<'EOF'
import http.server, urllib.request, itertools
up = itertools.cycle(["8081", "8082"])
class LB(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        p = next(up); r = urllib.request.urlopen(f"http://127.0.0.1:{p}{self.path}")
        self.send_response(200); self.send_header("X-Served-By", p); self.end_headers(); self.wfile.write(r.read()[:200])
print("desk on :8000 тЖТ 8081, 8082 round-robin"); http.server.HTTPServer(("127.0.0.1", 8000), LB).serve_forever()
EOF

тЬЕ Verify тАФ what you should see

Wikipedia answers with a server: header naming a CDN/proxy and an age or cache header. Your toy desk alternates X-Served-By: 8081 and 8082 on repeated curl -sI localhost:8000.

ЁЯПБ What you just proved

A load balancer is an ordinary program that forwards; the value is in health checks, TLS termination and routing rules тАФ and you can see all three in headers.

тЪая╕П Common mistakes

ЁЯПн Why this matters in production: ALB vs NLB, Ingress controllers, Cloudflare in front of everything тАФ the desk is where TLS, WAF, rate limits and canaries live. The API school's gateway (lesson 12) is this desk with auth attached.

тПня╕П Next

Lesson 12 тАФ debugging the network: the six-rung ladder and the toolbox.

тЖР Previousfirewalls nat vpnNext тЖТdebugging

This page is the lesson's README from the lesson-11-load-balancers-cdn branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.