☕ 5-Min Tech Story #23

DNS Caching Trap: ทำไม JVM ถึงฝังใจกับ IP เก่าจนยอมยิงใส่หลุมศพชั่วกัลปวสาน?

⏱️ ใช้เวลาอ่านประมาณ: 4 นาที 20 วินาที

เที่ยงคืนวันเสาร์ ทีม DevOps ทำการย้ายฐานข้อมูลหลักจาก AWS ไป GCP หรือสลับ IP ของ Load Balancer ใหม่เอี่ยม

ทุกคนทดสอบด้วยคำสั่ง curl และ nslookup ผ่าน Terminal เครื่องตัวเอง... "เรียบร้อย ทุกคนเห็น IP ใหม่หมดแล้ว ปิดจ็อบ แยกย้ายไปนอนได้!"

แต่เช้าวันจันทร์ แอปพลิเคชัน Java / Kotlin บนเซิร์ฟเวอร์กลับพ่น ConnectException: Connection refused ออกมารัวๆ! พอเปิดดู Network Traffic ปรากฏว่า แอปของคุณยังดันทุรังยิง Request ไปหา IP เก่าที่ปิดเครื่องไปแล้วตั้งแต่สองวันก่อน!

🧟‍♂️ ความรักมั่นคงเกินเหตุของ Java InetAddress

ในโลกของระบบปฏิบัติการ (OS) หรือเว็บเบราว์เซอร์ เวลาถาม DNS ว่า api.partner.com มี IP อะไร ปลายทางจะแนบค่า TTL (Time-To-Live) มาด้วย เช่น 60 วินาที หมายความว่าผ่านไป 1 นาทีให้ถามใหม่อีกรอบ

แต่ในโลกของ Java Virtual Machine (JVM) ยุคดั้งเดิม... มันมีพฤติกรรมหลอนๆ ที่ซ่อนอยู่:

"ถ้าในเครื่องเปิด SecurityManager ไว้ (หรือคอนฟิกบางเวอร์ชันในอดีต) ค่าเริ่มต้นของ networkaddress.cache.ttl จะถูกตั้งไว้ที่ -1 (Forever / ตลอดกาล!)"

นั่นหมายความว่า ทันทีที่สตาร์ตแอปแล้วมันถาม DNS ได้ IP มาครั้งแรก... JVM จะจด IP นั้นใส่สมุดพกแล้ว ไม่มีวันถาม DNS ใหม่อีกเลยจนกว่าคุณจะสั่ง Restart กระบวนการของแอป! แม้ว่าปลายทางจะสลับ IP หนีไปแล้วเป็นสัปดาห์ก็ตาม

☁️ หายนะในยุค Cloud & AWS ALB

ในสถาปัตยกรรมคลาวด์ยุคปัจจุบัน เช่น AWS Application Load Balancer (ALB) หรือ Cloudflare IP ปลายทาง ไม่ได้นิ่งเป็นหิน

เมื่อมีทราฟฟิกกระชาก AWS จะทำการ Scale-out โหนด Load Balancer อัตโนมัติ ทำให้ DNS เปลี่ยน IP สลับไปมาทุกๆ ไม่กี่นาที:

🛡️ ท่าแก้เผ็ด: สั่งให้ JVM เลิกฝังใจ

ถ้าคุณรันไมโครเซอร์วิสบน Container / Kubernetes วิธีรอดชีวิตคือการสั่งให้ JVM อัปเดต DNS ทุกๆ 30 วินาทีเสมอ:

1. ตั้งผ่านไฟล์ java.security หรือใส่ในโค้ดตอนเริ่มแอป:

// ตั้งค่าให้แคช DNS ไม่เกิน 30 วินาที
java.security.Security.setProperty("networkaddress.cache.ttl", "30")

// ถ้าหา DNS ไม่เจอ ให้ลองใหม่ใน 10 วินาที (อย่าจำ Negative Cache นาน)
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "10")

2. หรือส่งผ่าน JVM Flags ตอนสั่ง java -jar:

-Dsun.net.inetaddr.ttl=30

💡 5-Min Takeaway

"ในโลกของ Cloud และ Distributed Network ไม่มีสิ่งใดคงอยู่ถาวร แม้กระทั่งคู่ IP Address" อย่าคิดว่าคำสั่ง curl ผ่านหน้าเครื่องตัวเองรอดแล้วบน Production จะรอดตาม ตรวจสอบค่า DNS Cache TTL ของระบบ Runtime เสมอ เพื่อให้มั่นใจว่าแอปของคุณจะพร้อมก้าวเดินตามเส้นทางใหม่ เมื่อโครงสร้างพื้นฐานเบื้องล่างเกิดการเปลี่ยนแปลง