API Gateway คือ ประตูทางเข้าหลักของทุกบริการในสถาปัตยกรรม microservice มันรับหน้าที่ทำ authentication, จำกัดอัตราการเรียก (rate limiting), จัดเส้นทาง (routing), บันทึก log และแปลงรูปแบบคำขอ
ทั้งหมดนี้ดูเหมือนสมเหตุสมผล จนกระทั่ง traffic โตขึ้น 10 เท่า แล้ว CPU ของ gateway พุ่งไปแตะ 100% ทุกการเรียก API ที่เคยใช้เวลา 5 ms กลายเป็น 3 วินาที และเพราะทุก request ต้องวิ่งผ่าน gateway ทั้ง platform จึงล่มพร้อมกันทั้งระบบ
นี่คือ คอขวดที่พบบ่อยที่สุดและเป็น single point of failure ที่อันตรายที่สุดในระบบ microservice เพราะทุก request ต้องวิ่งผ่านมัน และงานทุกอย่างที่เป็น cross-cutting concern ก็ถูกยัดเข้าไปทำในนั้น เมื่อ gateway ช้าลง บริการปลายทางทุกตัวจึงได้รับผลกระทบพร้อมกันไปด้วย
ประเด็นสำคัญ คือ ปัญหานี้ไม่ได้เกิดจากบริการตัวใดตัวหนึ่ง แต่เกิดจากตัว gateway เองที่ทำงานหนักเกินไปต่อหนึ่ง request จน CPU ถูกใช้จนหมด และการแก้ที่ถูกต้องไม่ใช่การขยาย resource ให้ใหญ่ขึ้น (scale vertically) แต่ คือ การออกแบบใหม่ว่า gateway ควรทำอะไรบ้างและทำอย่างไร
บทความนี้จะเจาะลึกคอขวด 4 จุดหลักและแนวทางแก้ ที่นำไปใช้ได้โดยไม่ต้องเขียนระบบใหม่ทั้งหมด
เกิดอะไรขึ้นข้างในเมื่อ traffic โต 10 เท่า
สมมติแพลตฟอร์มมี microservice 50 ตัว traffic ทั้งหมดวิ่งผ่าน API Gateway และเพิ่งโตจาก 10,000 คำขอต่อวินาที (RPS) ไปเป็น 100,000 RPS ผลที่ตามมา คือ gateway รันที่ 100% CPU ทุกการเรียกใช้เวลา 2–3 วินาที ผู้ใช้เจอ timeout และบริการปลายทางรายงาน connection refused เพราะ connection pool ของ gateway ถูกใช้จนหมด ทีมงานพยายามเพิ่มจำนวน instant ของ gateway แต่ CPU ก็ยังคง 100% อยู่ดี
เมื่อไล่ดูว่า gateway ทำอะไรบ้างในแต่ละคำขอ จะพบว่ามีขั้นตอนดังนี้:
- แยกวิเคราะห์ JSON body (กิน CPU และหน่วยความจำ)
- ตรวจสอบ JWT (การยืนยันลายเซ็น RSA กิน CPU มาก ราว 0.5–1 ms/ครั้ง)
- เรียกไปยัง auth service (มี network round trip บวกเวลาประมวลผล)
- ตรวจ rate limit (เรียก Redis ทุกคำขอ)
- เขียน log แบบ synchronous (มี I/O อยู่บนเส้นทางคำขอ)
- แปลงคำขอ (จัดการ header และเขียน body ใหม่)
- สร้าง connection ใหม่ไปยังบริการปลายทาง (มี TCP บวก TLS handshake ทุกคำขอ)
- แปลงรูปแบบ response อีกรอบ

รวมแล้วที่ 100,000 RPS gateway กำลังทำงานราว 800,000 operations ต่อ วินาที แต่ละอย่างเพิ่ม latency เข้าไปทีละนิด เมื่อรวมกันจึงกลืน CPU จนหมด
คอขวดที่ 1: การทำ Authentication บนเส้นทางคำขอ
จุดเริ่มที่ควรแก้ คือ authentication เพราะการตรวจ JWT เป็น operation ที่กิน CPU มากที่สุดในบรรดางานทั้งหมดที่ gateway ทำ มี 3 แนวทางที่ช่วยยกภาระนี้ออกได้
- auth sidecar: ติดตั้ง auth proxy เป็น sidecar อยู่ข้าง gateway แต่ละ instant ให้ sidecar ตรวจ JWT ในเครื่องโดยใช้ public key ที่แคชไว้ ไม่ต้องเรียก network ไปหา AuthService วิธีนี้ลดเวลาตรวจ JWT จากราว 1ms เหลือประมาณ 0.05ms
- แยก auth gateway ออกมาเป็น tier ต่างหาก: โดยที่ tier แรกทำหน้าที่ตรวจ token เท่านั้น แล้วคืน context token ที่ลงลายเซ็นเป็น "pre-verified" ให้ ส่วน tier ที่ 2 (API gateway) ก็เชื่อ token นี้โดยไม่ต้องตรวจซ้ำ ทำให้ auth gateway ขยายขนาดได้อิสระจากส่วนอื่น
- แคชผลการ introspect token: เก็บผลการตรวจ token ไว้ ถ้า token เดิมถูกใช้ซ้ำภายใน 5 นาที ก็ข้ามการตรวจซ้ำได้เลย สำหรับ access token ที่มี TTL สั้น วิธีนี้จะได้ cache hit rate สูง
คอขวดที่ 2: ภาระการสร้าง Connection ใหม่ทุกคำขอ
คอขวดใหญ่อันดับ 2 คือ การจัดการ connection เพราะทุก request ที่ส่งไปยัง service ปลายทาง จะมีการสร้าง TCP connection ใหม่พร้อม TLS handshake ทุกครั้ง ซึ่งเป็นภาระที่หนักและซ้ำซ้อนโดยไม่จำเป็น
ทางแก้หลัก คือ connection pooling คือ เตรียม pool ของ HTTP connection ที่ pre-warmed ไว้ล่วงหน้าสำหรับบริการปลายทางแต่ละตัว ให้ request นำ connection กลับมาใช้ซ้ำแทนการสร้างใหม่ ขนาด pool ที่เหมาะสมจะอยู่ราว 20–50 connection ต่อ service ปลายทาง 1 ตัว ซึ่งช่วยตัดภาระ TCP บวก TLS ออกไปสำหรับ request ส่วนใหญ่
เสริมด้วย HTTP/2 multiplexing ที่ให้ connection เดียวรองรับหลายคำขอพร้อมกันบน stream แยกกัน จึงไม่มีภาระ connection ต่อ request อีก แถม HTTP/2 ยังรองรับการบีบอัด header และ server push และควรตั้ง keep-alive ให้ยาวพอ (เช่น 60 วินาที) เพื่อให้ใช้ connection ซ้ำได้มากที่สุด พร้อมเฝ้าดูอัตราการใช้ connection ซ้ำ (reuse ratio) โดยตั้งเป้าให้เกิน 99%
คอขวดที่ 3: การเขียน Log และ Analytics แบบ Synchronous
ตัวการที่ฉุดประสิทธิภาพแบบซ่อนอยู่ คือ การเขียน log แบบ synchronous เพราะมันวาง I/O ไว้บนเส้นทาง request โดยตรง ทุกคำขอต้องรอให้เขียน log เสร็จก่อน
ทางแก้ คือ ย้ายงานเขียน log, analytics และ audit trail ทั้งหมดออกจากเส้นทาง request ใช้ buffer ในหน่วยความจำเพื่อคิว log event ในระดับ microseconds แล้วให้ background worker ทำหน้าที่รวมกลุ่ม (batch) และส่ง log ออกแบบ asynchronous เพื่อไม่ให้คำขอต้องรอ I/O
คอขวดที่ 4: การออกแบบ Rate Limiting ให้มีประสิทธิภาพ
การทำ distributed rate limiting ด้วย Redis เป็นคอขวดที่พบบ่อย เพราะทุก request ต้องวิ่งไป-กลับ Redis หนึ่งรอบ ที่ 100,000 RPS นั่นหมายถึง Redis ต้องรับภาระ 100,000 ops/sec.
ทางแก้ คือ ใช้ hybrid token bucket ให้ gateway แต่ละอินสแตนซ์ถือ token bucket ในเครื่องของตัวเอง แล้วซิงก์กับ counter กลางบน Redis เป็นระยะ (ทุก 100ms แทนที่จะซิงก์ทุก request) วิธีนี้ลดภาระ Redis จาก 100,000 ops/sec. เหลือเพียงราว 10 ops/sec.
สถาปัตยกรรม Gateway ที่ปรับใหม่ทั้งหมด
เมื่อประกอบทางแก้ทั้งหมดเข้าด้วยกัน สถาปัตยกรรม gateway ที่ปรับแล้วจะมีองค์ประกอบหลักดังนี้

- Edge CDN แคช response ไว้ที่ขอบเครือข่าย API ที่มีการอ่านเป็นหลักมักได้ cache hit rate เกิน 70% ที่ระดับ CDN คำขอเหล่านี้จึงไม่มีวันวิ่งมาถึง gateway เลย
- Tier 1 (Auth Gateway) เป็น Tier stateless เฉพาะทาง ทำหน้าที่ตรวจ token อย่างเดียว โดยใช้ ECDSA แทน RSA (การตรวจ ECDSA เร็วกว่าราว 10 เท่าที่ระดับความปลอดภัยเท่ากัน) และมี LRU cache ในเครื่องสำหรับผลการตรวจ token
- Tier 2 (Lightweight Gateway) เมื่อยกภาระ auth ออกไปแล้ว gateway เหลือหน้าที่แค่จัดเส้นทาง, ทำ rate limit แบบ local และเขียน log แบบ async พร้อมใช้ connection pooling ร่วมกับ HTTP/2 เพื่อกำจัดภาระ connection ต่อคำขอ
- hybrid rate limiting ที่ให้ local token bucket ซิงก์กับ Redis ทุก 100ms ลดภาระ Redis ลงถึง 99.99%
- async logging ที่ใช้ buffer ในหน่วยความจำแล้ว flush เป็น batch จึงไม่มี I/O บนเส้นทางคำขอ
- request coalescing ที่ถ้ามีคำขอเดียวกัน (cache key เดียวกัน) กำลังทำงานอยู่ คำขอที่ตามมาจะรอผลลัพธ์ของคำขอแรกแทนที่จะเรียกซ้ำ
Metric ที่ต้องคอยดูสำหรับ Gateway
การออกแบบที่ดีต้องมาพร้อมการเฝ้าระวังที่ถูกจุด metric สำคัญมีดังนี้
- CPU ต่อคำขอ (Gateway CPU per request) คือ เมตริกสำคัญที่สุด วัดว่าใช้ CPU กี่ ms/req ถ้าตัวเลขนี้มีแนวโน้มสูงขึ้น แปลว่า มีฟีเจอร์ใหม่ถูกยัดเข้ามาใน gateway โดยไม่ได้คิดถึง cost ด้านประสิทธิภาพ
- อัตราการใช้ connection ซ้ำ (Connection reuse ratio) คือ สัดส่วนคำขอที่ใช้ connection เดิมซ้ำ ตั้งเป้าให้เกิน 99% ถ้าต่ำกว่า 90% แสดงว่า connection pooling ไม่ทำงานตามที่ควร
- Latency ของการตรวจ auth (p50, p99) ถ้ายกภาระ auth ออกไปแล้ว ตัวเลขนี้ควรต่ำกว่า 1 ms ถ้าเริ่มสูงขึ้น แปลว่า auth tier ต้องการการขยายขนาด
- Latency ของการซิงก์ rate limiter วัดเวลาที่ใช้ซิงก์กับ Redis ทุก 100ms ถ้าเกิน 10ms แสดงว่าตั้งช่วงการซิงก์ถี่เกินไป
- Cache hit ratio ในแต่ละ tier ทั้ง CDN, auth cache และ response cache ถ้าอัตรานี้ลดลงบ่งบอกว่ามีปัญหาการตั้งค่าแคช
- การแยกส่วน latency ของคำขอ (Request latency breakdown) ดูว่าเวลาถูกใช้ไปในแต่ละเฟสของ gateway เป็นเท่าไร ตั้งแต่การ parse, auth, rate limiting, routing, การเรียก services ปลายทาง ไปจนถึงการแปลง response เพื่อชี้ว่า phase ไหน คือ คอขวด
- อัตราข้อผิดพลาดแยกตาม services ปลายทาง (Gateway error rate by upstream) ดูว่า services ปลายทางตัวไหนทำให้ gateway เกิด error มากที่สุด เพราะ services ปลายทางที่มีปัญหาอาจทำให้ดูเหมือน gateway เป็นตัวต้นเหตุได้
บทสรุป
API Gateway คือ องค์ประกอบที่แบกภาระหนักที่สุดในสถาปัตยกรรม microservice เพราะทุก requests ต้องวิ่งผ่านมัน และงาน cross-cutting ทุกอย่างก็รันอยู่ในนั้น เมื่อมันล้ม ทั้ง platform จึงล้มตาม
คอขวด 4 จุดและทางแก้สรุปได้ คือ การตรวจ auth ที่กิน CPU แก้ด้วยการยกออกไปทำที่ sidecar หรือ tier แยก และ cache ผลลัพธ์, ลดภาระของ connection ต่อ request แก้ด้วย connection pooling และ HTTP/2, การเขียน log แบบ synchronous แก้ด้วยการทำ async ผ่าน buffer, และ rate limiting ที่พึ่ง redis ทุก request แก้ด้วย hybrid token bucket ที่ sync เป็นระยะ
กฎการออกแบบที่สำคัญที่สุด คือ gateway ควรทำงานบนเส้นทางคำขอให้น้อยที่สุดเท่าที่จะทำได้ ทุก ms ที่ใช้ไปใน gateway คือ ms ที่ผู้ใช้ทุกคนของทุก service ต้องจ่าย ดังนั้นให้ย้ายงานออกจากเส้นทางคำขอ cache อย่างจริงจัง connection pool ไว้ใช้ซ้ำ และห้ามทำ synchronous I/O ใน request handler ของ gateway เด็ดขาด