คำแนะนำวิธีบีบอัดคำขอ HTTP ของไคลเอ็นต์เว็บ
หากคุณพบว่าตัวเองอยู่ในสถานการณ์ที่คุณส่งเพย์โหลดคำขอ HTTP ขนาดใหญ่จากเว็บเบราว์เซอร์ไปยัง API ของคุณ คุณอาจทำผิดพลาดทางสถาปัตยกรรมหรือการออกแบบ กล่าวคือ เมื่อเร็วๆ นี้ทีมของเราอยู่ในสถานการณ์ที่การส่งคำขอขนาด 200–300KB เป็นประจำทำให้เราได้รับการแลกเปลี่ยนน้อยที่สุด
ด้วยเหตุนี้ เราจึงพบว่าเวลาในการโอนคำขอยาวนาน ต่างจากวิธีที่เบราว์เซอร์ขยายขนาดเนื้อหาการตอบสนอง HTTP โดยอัตโนมัติผ่านกลไก การเจรจาต่อรองเนื้อหา HTTP (โดยใช้ส่วนหัว Accept-Encoding
) เบราว์เซอร์ไม่ได้บีบอัดเนื้อหาคำขอของเราโดยอัตโนมัติ แน่นอนว่ามีกลไกที่คล้ายกันที่เราสามารถทำได้สำหรับกรณีนี้
เราผิด
การค้นหาสิ่งใดก็ตามที่เกี่ยวข้องกับการบีบอัดเนื้อหาคำขอฝั่งไคลเอ็นต์นั้น "ส่วนใหญ่" ไร้ผล เท่าที่เราต้องการหลีกเลี่ยงการ "โกนจามรี" ที่ Axiom Zen สัตว์ร้ายตัวนี้ก็ต้องตัดผม
การโกนขนจามรี คือสิ่งที่คุณทำเมื่อคุณทำงานเล็กๆ น้อยๆ ที่โง่เขลาและยุ่งวุ่นวายซึ่งไม่มีความสัมพันธ์ที่ชัดเจนกับสิ่งที่คุณควรจะทำ แต่ยังมีสิบสองสาย ความสัมพันธ์เชิงสาเหตุเชื่อมโยงสิ่งที่คุณกำลังทำกับงานเมตาเดิม
ก่อนที่เราจะใช้การบีบอัด GZIP ฝั่งไคลเอ็นต์เป็นโซลูชันของเรา เราได้สำรวจทางเลือกต่างๆ มากมาย:
Msgpack ดูมีแนวโน้มดี อย่างไรก็ตาม มันไม่มีประสิทธิภาพสำหรับคำขอจำนวนมากซึ่งเป็นปัญหาของเราอย่างแน่นอน นอกจากนี้ ดูเหมือนว่าจะมีความรู้สึกเชิงลบเล็กน้อยต่อ Msgpack จากนักพัฒนาบนเว็บไซต์ต่างๆ
gRPCนึกถึงตอนที่เราใช้มันเป็นโปรโตคอลการสื่อสารไมโครเซอร์วิสที่ประสบความสำเร็จ อย่างไรก็ตาม ยังไม่รองรับบนฝั่งเบราว์เซอร์ ดังนั้นเราจึงต้องดำเนินการต่อไป
ท้ายที่สุด JSONC แสดงให้เห็นศักยภาพ แต่จำเป็นต้องมีการเปลี่ยนแปลงโครงสร้างข้อมูลของเราโดยไม่สำคัญตามคำจำกัดความ และโครงการก็มีปัญหาที่เปิดอยู่มากมายเกี่ยวกับการเข้ารหัสแบบไปกลับบน GitHub เราตัดสินใจที่จะผ่าน
GZIP เป็น G6 ของเรา
เนื่องจากอัลกอริทึม GZIP มีมาระยะหนึ่งแล้ว เราจึงหวังว่าจะมีคนนำไปใช้ใน Javascript เรากล้าฝันว่ามันจะเป็น Javascript ที่สามารถทำงานในเบราว์เซอร์ได้เช่นกัน โชคดีที่การค้นหาของเราพาเราไปที่ หน้า pako npm และจากการทดสอบและเกณฑ์มาตรฐาน ดูเหมือนว่าเป็นเพียงแพ็คเกจที่เรากำลังมองหา
สำหรับการผสานรวมกับฐานโค้ดฝั่งไคลเอ็นต์ของคุณ หากคุณใช้ axios ซึ่งเป็นไลบรารีคำขอ Javascript HTTP ทั่วไป ทางออกที่ดีที่สุดของคุณน่าจะรวมเข้ากับตัวแปลงคำขอทั่วโลก:
โปรดสังเกตว่าเราส่งคำขอ GZIP ในขนาดที่กำหนดเท่านั้น การซิปข้อมูลจำนวนเล็กน้อยจะเพิ่มขนาดโดยรวม โดยที่ 1,024 ไบต์ถือเป็น "ตัวเลขมหัศจรรย์กึ่งกำหนดเอง" เราขอแนะนำให้เล่นซอเพื่อค้นหาสิ่งที่ดีที่สุดสำหรับคุณ
สำหรับฝ่ายรับ Axiom Zen มักจะเขียนโค้ดแบ็กเอนด์ใน Go (golang
) สิ่งนี้กลายเป็นการแสดงที่ยอดเยี่ยมถึงพลังและความสง่างามของอินเทอร์เฟซใน Go ดังที่เห็นในตัวอย่างของเล่นนี้:
สังเกตว่าฟังก์ชัน json.NewDecoder()
ไม่สนใจว่า io.Reader
จะถูกส่งไปอย่างไร
อีกสิ่งหนึ่งที่ควรทราบ (ไม่ได้แสดงไว้ที่นี่) ก็คือ หากคุณต้องการแชร์ทรัพยากรข้ามแหล่งที่มา (CORS) คุณจะต้องเพิ่มส่วนหัว Content-Encoding
ลงในรายการ Access-Control-Allow-Headers เมื่อจัดการก่อน คำขอ -flightOPTIONS
ผลลัพธ์
เราเห็นการลดขนาดลง 10 เท่า (ข้อมูล JSON ค่อนข้างซ้ำกันตามธรรมชาติ) โดยมีการลงโทษ CPU เล็กน้อยฝั่งไคลเอ็นต์ แม้ว่าแนวทางของเราอาจต้องมีการปรับแต่งจากฝั่งของคุณ แต่เราพอใจกับผลลัพธ์ที่ได้ ซึ่งจะเห็นได้ชัดเจนเป็นพิเศษเมื่อพูดคุยกับเซิร์ฟเวอร์ที่อยู่ห่างไกล
แจ้งให้เราทราบว่าคุณคิดอย่างไรเกี่ยวกับแนวทางของเราในความคิดเห็นด้านล่าง!
เขียนโดย Chris Scott และทีมวิศวกร Axiom Zen
เรียบเรียงโดย "Yasmine Nadery" และ "Bryce Bladon"
ดูเรื่องราวประเภทนี้เพิ่มเติมได้ใน บล็อกของ Axiom Zen