ติ๊ก 650,000,000 ช่องทำเครื่องหมาย: รับมือกับความนิยมที่เกินคาด
วันที่ 26 มิถุนายน 2024 ได้เปิดตัวเว็บไซต์ One Million Checkboxes (OMCB)
- เว็บไซต์ที่มีช่องทำเครื่องหมายแบบโกลบอล 1 ล้านช่อง โดยเมื่อมีการติ๊กช่องใด การเปลี่ยนแปลงจะสะท้อนให้ผู้ใช้ทุกคนเห็นทันที
- หลังเปิดตัวเพียง 30 นาที มีผู้ใช้หลายพันคนช่วยกันติ๊กช่องทำเครื่องหมายไปแล้วหลายล้านครั้ง
- มีผู้ใช้ไหลเข้ามาจาก Hacker News, /r/InternetIsBeautiful, Mastodon, Twitter และที่อื่น ๆ
- ถูกนำเสนอใน Washington Post และ New York Times ด้วย
- วันแรกมีการติ๊กช่องทำเครื่องหมายมากกว่า 50 ล้านครั้ง
- ก่อนปิดเว็บไซต์ในอีก 2 สัปดาห์ถัดมา มีการติ๊กช่องทำเครื่องหมายรวมมากกว่า 650 ล้านครั้ง
สถาปัตยกรรมเดิม
- สถานะของช่องทำเครื่องหมายถูกเก็บเป็น 1 ล้านบิต (125KB)
- ฝั่งไคลเอนต์ใช้บิตเซ็ตเพื่อเรนเดอร์ช่องทำเครื่องหมาย และแจ้งสถานะการติ๊กไปยังเซิร์ฟเวอร์
- เซิร์ฟเวอร์ใช้ Redis อัปเดตบิตและบรอดแคสต์ไปยังไคลเอนต์ทั้งหมด
- ให้บริการคอนเทนต์แบบสแตติกผ่าน nginx และใช้เซิร์ฟเวอร์ Flask สำหรับจัดการสถานะบิตเซ็ตและการเชื่อมต่อ WebSocket
- Redis ทำหน้าที่ทั้งเก็บสถานะและเป็นคิวข้อความ
หลักการในการขยายระบบ
- จำกัดค่าใช้จ่าย: ขยายระบบแบบเซิร์ฟเวอร์เลสโดยคำนวณต้นทุนเชิงคณิตศาสตร์เพื่อไม่ให้ค่าใช้จ่ายพุ่งจนล้มละลาย
- ยอมรับวิธีแก้ระยะสั้น: สมมติว่าความนิยมของเว็บไซต์จะอยู่เพียงชั่วคราว จึงเลือกวิธีแก้ที่ทำได้เร็ว
- ใช้เทคโนโลยีที่เรียบง่ายและโฮสต์เองได้: เพิ่มเฉพาะสิ่งที่สามารถรันและดีบักบนเซิร์ฟเวอร์ของตัวเองได้
- ให้ความสนุกมาก่อน: ให้ความสำคัญกับความสนุกมากกว่าเงิน
- คงสภาพแบบโกลบอลไว้: เพื่อให้ผู้ใช้ทุกคนเห็นการเปลี่ยนแปลงได้ทันที
วันแรก: ความนิยมระเบิดขึ้นอย่างรวดเร็ว
- ภายใน 30 นาที ภาระบนเซิร์ฟเวอร์พุ่งสูงมาก
- สปินอัปเซิร์ฟเวอร์เพิ่มเพื่อกระจายโหลด
- นำการอัปเดตแบบแบตช์มาใช้เพื่อแก้ปัญหาการเชื่อมต่อ Redis
- อัปเกรดอินสแตนซ์ Redis แบบจัดการให้ของ Digital Ocean
ไม่มีแผนสำหรับทั้งคืน
- วางแผนระหว่างไปออกบูธเกม Pacman จดจำใบหน้าที่แคมป์ ITP
- พก iPad ไปด้วยเพื่อสปินอัปเซิร์ฟเวอร์
- พัฒนากติกาการตั้งชื่อเซิร์ฟเวอร์ไปพร้อมกับรัน worker VM จำนวน 8 เครื่อง
- ลดจำนวนโปรเซส Flask และเพิ่มขนาดแบตช์ของการอัปเดตเพื่อลดโหลด
ปัญหาแบนด์วิดท์
- ไม่ได้คำนึงถึงราคาค่าแบนด์วิดท์ของ Digital Ocean
- ลดความถี่ของสแนปช็อตสถานะ และลดขนาดของข้อมูลอัปเดต
- ใช้ยูทิลิตี
tc เพื่อจำกัดปริมาณข้อมูลที่ส่งต่อวินาที
วันที่สอง: ยังเติบโตต่อเนื่อง
- เว็บไซต์ล่มเพราะทำ input validation ไม่รัดกุมพอ
- เพิ่ม Redis replica เพื่อช่วยกระจายโหลด
- โปรเซส Flask ล่มต่อเนื่องจนต้องเขียนสคริปต์รีสตาร์ตอัตโนมัติ
ปัญหาอัปเดตเก่า
- เกิดปัญหาที่ไคลเอนต์นำอัปเดตเก่ามาใช้ ทำให้แสดงสถานะผิด
- เพิ่ม timestamp เพื่อรับประกันลำดับของอัปเดต
เขียนใหม่ด้วย Go
- ร่วมกับเพื่อนที่เป็นวิศวกรประสิทธิภาพ เขียนแบ็กเอนด์ใหม่ด้วย Go
- ประสิทธิภาพดีขึ้นอย่างมาก
- ป้องกันการโจมตี DDOS ผ่าน CloudFlare
การปิดเว็บไซต์
- เปลี่ยนให้ช่องทำเครื่องหมายเข้าสู่สถานะแช่แข็งหากไม่มีการยกเลิกการติ๊กอย่างรวดเร็วพอ
- ใช้ Redis จัดการสถานะแช่แข็ง
- ปิดเว็บไซต์หลังจากนั้น 2 สัปดาห์
สิ่งที่ได้เรียนรู้
- เป็นครั้งที่สองที่ได้ปล่อยเซิร์ฟเวอร์ที่มีแบ็กเอนด์ "จริง" สู่สาธารณะบนอินเทอร์เน็ต
- การเลือกวิธีแก้ระยะสั้นเป็นการตัดสินใจที่ดี
- ยืนยันอีกครั้งถึงพลังของ Redis และ nginx
- เห็นชัดว่าผู้คนโหยหาเว็บไซต์ที่ให้โต้ตอบกันแบบไม่ระบุตัวตน
สรุปโดย GN⁺
- บทความนี้เล่าถึงปัญหาทางเทคนิคและกระบวนการแก้ไขที่เกิดจากความนิยมเกินคาดของเว็บไซต์
- แสดงให้เห็นว่าแม้ใช้สถาปัตยกรรมเรียบง่ายที่อาศัย Redis และ nginx ก็ยังรองรับทราฟฟิกขนาดใหญ่ได้
- อธิบายวิธีแก้ปัญหาและทำให้เว็บไซต์เสถียรได้อย่างรวดเร็วด้วยแนวทางระยะสั้น
- ครอบคลุมความท้าทายทางเทคนิคหลายด้าน เช่น การเขียนใหม่ด้วย Go และการป้องกัน DDOS ผ่าน CloudFlare
- โครงการที่มีลักษณะคล้ายกันมี เช่น /r/Place ของ Reddit ซึ่งเป็นโปรเจกต์ความร่วมมือขนาดใหญ่
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ได้เรียนรู้บทเรียนและเกร็ดประวัติศาสตร์มากมาย
เป็นบทความที่ยอดเยี่ยมมาก! ขอแสดงความยินดีกับเว็บไซต์ด้วย แต่ตัวบทความเองคือส่วนที่ควรภูมิใจที่สุด
การสร้างเว็บนี้ภายในสองวันเป็นการตัดสินใจที่ดี
โปรเจกต์ที่เกี่ยวข้องเมื่อไม่นานมานี้:
เป็นโปรเจกต์ที่น่าสนุก
เป็นบทความที่ยอดเยี่ยมมาก — อยากรู้ว่ามีค่าใช้จ่ายเท่าไร
ยิ่งทำให้เชื่อว่าผู้คนโหยหาปฏิสัมพันธ์แบบนิรนามที่มีข้อจำกัด
ในฐานะมือใหม่ด้านแบ็กเอนด์ ฉันสงสัยว่ามีสถาปัตยกรรมทางเลือกที่เรียบง่ายกว่านี้สำหรับโปรเจกต์นี้ไหม
เจ๋งมาก!
สงสัยว่าเกมนี้ยังออนไลน์อยู่ไหม