เรื่องราวการปรับปรุงความเร็วที่รับรู้ได้ด้วยการล็อก Vercel Functions ไว้ที่ Tokyo Region — การแก้ปัญหาการเดินทางไปกลับข้ามมหาสมุทรแปซิฟิก
- engineering
- nextjs
- performance
- vercel
สรุปบทความนี้
- สาเหตุที่แดชบอร์ดช้าคือ "Vercel Functions อยู่ที่สหรัฐอเมริกา ส่วนฐานข้อมูลอยู่ที่โตเกียว" ทำให้ต้องเดินทางข้ามมหาสมุทรแปซิฟิกทุกครั้ง
- สามารถตรวจสอบว่ารันอยู่ที่รีเจียนใดได้จากเฮดเดอร์การตอบกลับ
x-vercel-id- ด้วยการล็อกรีเจียนไว้ที่โตเกียวผ่าน
regionsในvercel.jsonและการทำคิวรีแบบขนาน จากการวัดผลภายในองค์กรพบว่าเวลาลดลงจากหลายวินาทีเหลือประมาณ 0.2 วินาที
นี่คือบันทึกการตรวจสอบความช้าที่รับรู้ได้จาก "การเปลี่ยนหน้าจอแดชบอร์ดใช้เวลาหลายวินาที" การหาสาเหตุที่แท้จริง และการปรับปรุงแก้ไข โดยแยกแยะปัญหาด้วยการวัดผลจริง ไม่ใช่การคาดเดา
อาการและการแยกแยะปัญหา
การเปลี่ยนหน้าจอใช้เวลาประมาณ 3 วินาที เมื่อแยกแยะก่อนว่าอะไรที่ช้ากว่ากันระหว่าง "การตอบสนองเริ่มต้นของเซิร์ฟเวอร์ (TTFB)" กับ "การดึงข้อมูลเนื้อหา" พบว่าการตอบสนองเริ่มต้นนั้นเร็ว แต่การดึงข้อมูลภายในหน้าเพจต่างหากที่ช้า
คิวรีแต่ละตัวเองบนฐานข้อมูลนั้นเร็วมาก ใช้เวลาเพียงไม่กี่มิลลิวินาที แต่โดยรวมกลับช้า จุดที่เราสงสัยคือสถานที่ที่รันโค้ด (รีเจียน)
สาเหตุที่ 1: การเดินทางไปกลับข้ามมหาสมุทรแปซิฟิก
เมื่อดูเฮดเดอร์การตอบกลับ x-vercel-id พบว่าฟังก์ชันถูกรันอยู่ที่รีเจียนฝั่งตะวันออกของสหรัฐอเมริกา (iad1) ในขณะที่ฐานข้อมูล (Supabase) อยู่ที่โตเกียว นั่นหมายความว่าทุกครั้งที่มีการคิวรี จะเกิดการเดินทางไปกลับระหว่างญี่ปุ่นกับสหรัฐอเมริกา
เฮดเดอร์มีลักษณะดังนี้ (ตัวอย่าง)
x-vercel-id: hnd1::iad1 ← 受け口は東京(hnd1)だが、実行は米国(iad1)
หากมีคิวรีหลายครั้ง ก็จะเกิดการเดินทางไปกลับข้ามมหาสมุทรแปซิฟิกทุกครั้ง ทำให้เวลาแฝง (latency) สะสมมากขึ้นเรื่อยๆ
สาเหตุที่ 2: การรอคิวรีแบบต่อเนื่อง (Serial)
อีกสาเหตุหนึ่งคือ หน้าโฮมดึงข้อมูลสรุปหลายรายการแบบต่อเนื่อง (ทีละรายการตามลำดับ) ทำให้ความล่าช้าจากการเดินทางไปกลับสะสมเพิ่มขึ้นตามจำนวนครั้งที่ทำ
มาตรการแก้ไข
ล็อกรีเจียนไว้ที่โตเกียว
เราเพิ่มการระบุรีเจียนใน vercel.json เพื่อให้ฟังก์ชันรันที่โตเกียว (hnd1)
{ "regions": ["hnd1"] }
ด้วยวิธีนี้ x-vercel-id จะกลายเป็น hnd1::hnd1 ทำให้ทั้งฟังก์ชันและฐานข้อมูลอยู่ที่โตเกียวทั้งคู่ ความล่าช้าจากการเดินทางไปกลับจึงหมดไป
ทำคิวรีแบบขนาน
เราเปลี่ยนการดึงข้อมูลสรุปที่เคยรอแบบต่อเนื่องให้เป็นแบบขนานด้วย Promise.all พร้อมทั้งรวมการดึงข้อมูลที่ซ้ำซ้อนให้เหลือเพียงครั้งเดียว
ผลลัพธ์
จากการวัดผลภายในองค์กร เวลาแสดงผลหน้าโฮมลดลงจากหลายวินาทีเหลือประมาณ 0.2 วินาที จุดสำคัญคือการทำให้กระบวนการเองเร็วขึ้นโดยไม่พึ่งพาแคช ข้อมูลที่แสดงยังคงเป็นข้อมูลล่าสุดอยู่เสมอ
บทเรียนที่ได้
- เมื่อเจอสถานการณ์ "คิวรีเร็ว แต่หน้าจอช้า" อย่ามองแค่ความเร็วของฐานข้อมูล ให้สงสัยระยะทางทางกายภาพระหว่างฟังก์ชันกับฐานข้อมูล (รีเจียน) ด้วย
x-vercel-idเป็นเบาะแสที่ตรวจสอบได้ง่ายและทรงพลังในการดูว่ารันอยู่ที่รีเจียนใด- ในสภาพแวดล้อมที่มีต้นทุนการเดินทางไปกลับสูง การรอแบบต่อเนื่องจะกลายเป็นปัญหาใหญ่ การทำงานแบบขนานจึงให้ผลลัพธ์ที่ดีมาก
สรุป
ต้นตอที่แท้จริงของความช้าที่รับรู้ได้คือการเดินทางไปกลับระหว่างสหรัฐอเมริกากับโตเกียว ด้วยมาตรการสองอย่างคือการล็อกรีเจียนและการทำงานแบบขนาน เราสามารถปรับปรุงความเร็วที่รับรู้ได้อย่างมากโดยไม่ต้องพึ่งแคชเลย หากคุณรู้สึกว่า SSR หรือแดชบอร์ดของคุณช้า ลองตรวจสอบความสัมพันธ์ระหว่างรีเจียนที่รันโค้ดกับตำแหน่งของฐานข้อมูลดูก่อน