หน่วย 8 / 11

การจำกัดความเร็วและการจัดการข้อผิดพลาดที่ยืดหยุ่น

กำไร:

  • สามารถตีความขีดจำกัดความเร็ว (RPM/ITPM/OTPM) และข้อผิดพลาด 429
  • ใช้ Exponential Backoff และลองอีกครั้งโดย Retry-After
  • จัดประเภทและจัดการรหัสข้อผิดพลาด HTTP ทั่วไปอย่างถูกต้อง (400/401/429/500/529)

ในสภาพแวดล้อมการใช้งานจริง ไม่มี API ใดที่ตอบสนองได้อย่างสมบูรณ์แบบตลอดเวลา บางครั้งคุณส่งคำขอเร็วเกินไปและถึงขีดจำกัด บางครั้งเซิร์ฟเวอร์ไม่ว่างชั่วคราว บางครั้งคำขอของคุณผิดตั้งแต่ต้น สิ่งที่ทำให้การบูรณาการที่มั่นคงแตกต่างจากความพยายามของมือสมัครเล่นก็คือ มันสามารถจัดการกับสถานการณ์เหล่านี้ได้อย่างคาดการณ์และอัตโนมัติ ในหน่วยนี้ คุณจะได้เรียนรู้เกี่ยวกับขีดจำกัดอัตรา (RPM/ITPM/OTPM) ข้อผิดพลาด 429 ลองอีกครั้งโดยใช้ Exponential Backoff และการจัดประเภทรหัสข้อผิดพลาด HTTP ทั่วไปอย่างเหมาะสม เป้าหมาย: เพื่อสร้างโฟลว์ที่แข็งแกร่งจนผู้ใช้จะไม่มีวันสังเกตเห็น

การจำกัดความเร็วคืออะไร?

ผู้ให้บริการจะจำกัดปริมาณงานที่สวิตช์สามารถทำได้ในช่วงเวลาที่กำหนด การป้องกันนี้ ช่วยปกป้องทั้งโครงสร้างพื้นฐานและคุณจากต้นทุนระเบิดกะทันหัน ขีดจำกัดทั่วไปมีสามประเภท:

  • RPM (คำขอต่อนาที): จำนวนคำขอต่อนาที
  • ITPM (โทเค็นอินพุตต่อนาที): โทเค็นอินพุตที่สามารถประมวลผลต่อนาที
  • OTPM (โทเค็นเอาต์พุตต่อนาที): โทเค็นเอาต์พุตที่สามารถผลิตได้ต่อนาที

หากคุณใช้เกินขีดจำกัดใดๆ เหล่านี้ ผู้ให้บริการจะปฏิเสธคำขอและส่งกลับรหัสข้อผิดพลาด 429 โดยทั่วไปขีดจำกัดจะแตกต่างกันไปขึ้นอยู่กับระดับบัญชีของคุณ (ระดับ) และอาจเพิ่มขึ้นเมื่อเวลาผ่านไป

เคล็ดลับ: คุณสามารถดูเมื่อคุณเข้าใกล้ขีดจำกัดได้จากส่วนหัวการตอบกลับ ผู้ให้บริการส่วนใหญ่จะรายงานโควต้าที่เหลืออยู่ของคุณด้วยส่วนหัว เช่น x-ratelimit-remaining-* การตรวจสอบค่าเหล่านี้และควบคุมปริมาณการรับส่งข้อมูลด้านหน้าเป็นวิธีที่สมบูรณ์ที่สุดในการป้องกันปัญหาโดยไม่ได้รับ 429

429 และการกลับตัวแบบเอ็กซ์โปเนนเชียล

429 (ขีดจำกัดอัตรา) เป็นข้อผิดพลาดชั่วคราวและสามารถลองใหม่ได้ คำตอบที่ถูกต้องคือรอคำขอสักพักแล้วลองอีกครั้ง แต่การรอคอยอย่างต่อเนื่องนั้นไม่เพียงพอ หากทุกคนพยายามอีกครั้งในเวลาเดียวกัน จะถึงขีดจำกัดอีกครั้ง วิธีแก้ไขคือการถอยกลับแบบเอ็กซ์โพเนนเชียล: เพิ่มเวลารอแบบทวีคูณเมื่อพยายามล้มเหลวแต่ละครั้ง

# การทดลองลอจิกย้อนกลับแบบเอ็กซ์โปเนนเชียล 1 → 429 → รอ 1 วินาที การทดลอง 2 → 429 → รอ 2 วินาที การทดลอง 3 → 429 → รอ 4 วินาที การทดลอง 4 → 429 → รอ 8 วินาที (+ "กระวนกระวายใจแบบสุ่มเล็กน้อย")... ยอมแพ้และรายงานหลังจากการทดลอง N มากที่สุด

การเพิ่มความสุ่มเล็กน้อย (กระวนกระวายใจ) เพื่อป้องกันคำขอขัดแย้งกันเมื่อพยายามลองอีกครั้งในเวลาเดียวกัน นอกจากนี้ การตอบกลับ 429 มักมีส่วนหัว "ลองใหม่หลังจาก": "ลองอีกครั้งในอีกไม่กี่วินาทีนี้" การเคารพชื่อนี้มีความแม่นยำมากกว่าการรอคอยอย่างสุ่มสี่สุ่มห้า

ข้อควรระวัง: เมื่อคุณได้รับ 429 "การบังคับโดยการส่งคำขอเพิ่มเติม" จะทำให้สถานการณ์แย่ลง ขีดจำกัดยังคงถูกเติมเต็มและไม่มีคำขอใดที่ผ่าน การตอบสนองที่ถูกต้องคือการถอย ไม่ใช่การเร่งความเร็ว ข่าวดี: SDK ที่เป็นทางการส่วนใหญ่จะลองข้อผิดพลาด 429 และเซิร์ฟเวอร์อีกครั้งโดยอัตโนมัติพร้อมแบ็คออฟ — ใช้ลักษณะการทำงานของ SDK นี้ก่อนทำการติดตั้งด้วยตนเอง

การจำแนกรหัสข้อผิดพลาด HTTP

ความผิดพลาดทุกครั้งไม่เหมือนกัน ความแตกต่างที่สำคัญ: สามารถลองใหม่ได้หรือไม่ หรือเป็นปัญหาเกี่ยวกับคำขอ/ข้อมูลประจำตัว

รหัส

ความหมาย

สามารถลองอีกครั้งได้หรือไม่?

การตอบสนองที่ถูกต้อง

400

คำขอไม่ถูกต้อง (ข้อผิดพลาดด้านรูปแบบ/พารามิเตอร์)

ไม่

แก้ไขคำขอ; อย่าส่งเหมือนเดิมอีก

401

ข้อผิดพลาดในการตรวจสอบสิทธิ์ (คีย์ไม่ถูกต้อง/หายไป)

ไม่

แก้ไขคีย์/ชื่อเรื่อง

403

ไม่มีการอนุญาต (ไม่มีการเข้าถึงโมเดล/ฟีเจอร์)

ไม่

ตรวจสอบสิทธิ์/ขอบเขต

404

ไม่พบ (ID โมเดล/จุดสิ้นสุดไม่ถูกต้อง)

ไม่

รหัสรุ่น/ที่อยู่ที่ถูกต้อง

429

เกินขีดจำกัดความเร็ว

ใช่

ถอยกลับ + ลองใหม่ภายหลัง

500

ข้อผิดพลาดของเซิร์ฟเวอร์

ใช่

ลองอีกครั้งด้วยการถอย

529

เซิร์ฟเวอร์โอเวอร์โหลด

ใช่

ลองอีกครั้งด้วยการถอย

กฎทอง: 429, 500 และ 529 เป็นแบบชั่วคราว จะมีการลองอีกครั้งด้วยการถอนเงิน 400, 401, 403, 404 เป็นปัญหาการร้องขอ/ข้อมูลประจำตัว การลองอีกครั้งไม่ได้ช่วยแก้ปัญหา และเป็นการสิ้นเปลืองความพยายาม รหัสของคุณต้องแยกความแตกต่างระหว่างสองกลุ่มนี้

ทีละขั้นตอน: การโทรที่ทนทาน

  1. ส่งคำขอ ถ้าสำเร็จก็ไปต่อ
  2. จำแนกรหัสข้อผิดพลาด สามารถลองอีกครั้งได้หรือไม่?
  3. หากลองได้ ให้ทำตามการลองใหม่ภายหลัง ใช้ Exponential Backoff + Jitter ลองในจำนวนที่จำกัด (เช่น สูงสุด 5 ครั้ง)
  4. หากไม่ได้ลอง: แก้ไข (รูปแบบ/คีย์) และหยุด อย่าทำซ้ำคำขอที่ผิดพลาดเดียวกันในลูป
  5. พิจารณายอมแพ้. หากยังไม่สำเร็จหลังจากพยายามแล้ว n ครั้ง ให้แสดงข้อความสุภาพแก่ผู้ใช้และบันทึกเหตุการณ์ (หน่วยการติดตาม 11)

# โทรที่แข็งแกร่ง pseudo-codedene = 0repeat: response = request_at() if response.success: return response ถ้า response.code ใน [429, 500, 529] แล้วลอง < 5: wait = retry_after ?? (2^ลองวินาที + กระวนกระวายใจ) นอน (รอ); ลอง += 1; git อีกครั้งหาก response.code ใน [400, 401, 403, 404]: save_error(response); ส่งคืน "คำขอต้องได้รับการแก้ไข" ส่งคืน "ข้อผิดพลาดถาวร โปรดลองในภายหลัง"

# ความคิดเห็นที่สุภาพต่อผู้ใช้ (เมื่อหมดความพยายามแล้ว) "ตอนนี้ฉันไม่ว่าง ฉันไม่สามารถดำเนินการตามคำขอของคุณได้ โปรดลองอีกครั้งในเร็วๆ นี้ ไม่เช่นนั้นฉันได้บันทึกคำขอของคุณแล้ว ฉันจะติดต่อกลับเมื่อพร้อม"

พรอมต์ที่อ่อนแอ / พรอมต์ที่รัดกุม (ที่นี่: การออกแบบข้อความแสดงข้อผิดพลาด)

# WEAK (แสดงข้อผิดพลาดดิบแก่ผู้ใช้) "ข้อผิดพลาด 429: rate_limit_error"

# แข็งแกร่ง (ใช้งานง่าย มั่นใจ แนะนำการดำเนินการ) "เกิดปัญหาขัดข้องชั่วคราวในระบบ เราได้รับคำขอของคุณอย่างปลอดภัยแล้วและกำลังพยายามอีกครั้งโดยอัตโนมัติ หากผลลัพธ์ไม่ปรากฏภายในไม่กี่วินาที คุณสามารถรีเฟรชหน้าได้"

การเปิดเผยข้อผิดพลาดทางเทคนิคแก่ผู้ใช้ปลายทางทั้งบ่อนทำลายความไว้วางใจและอาจเป็นช่องโหว่ด้านความปลอดภัย จัดหมวดหมู่ข้อผิดพลาดเป็นการภายในและให้ข้อความที่สงบและเน้นการดำเนินการแก่ผู้ใช้ เพียงเขียนรายละเอียดทางเทคนิคสำหรับบันทึก

มินิเคสสามอัน

กรณีที่ 1 — เรือชนด้วยเหตุระเบิดของการจราจร บอทบริการลูกค้าได้รับการเข้าชมเพิ่มขึ้น 429 รายการในวันรณรงค์ ไม่มีการลองโค้ดซ้ำ ทุกข้อผิดพลาดจะแสดงต่อผู้ใช้โดยตรงว่าเป็น "ข้อผิดพลาด" พวกเขาเพิ่มการย้อนกลับแบบเอกซ์โปเนนเชียล + ลองใหม่ภายหลัง ด้วยการรับส่งข้อมูลเดียวกัน คำขอที่ส่งผ่านล่าช้าหลายวินาที ผู้ใช้ไม่เห็นข้อผิดพลาดใดๆ

กรณีที่ 2 — พยายามวนซ้ำ 400 ครั้ง การบูรณาการได้รับ 404 เนื่องจากรหัสโมเดลไม่ถูกต้อง แต่ถือว่าข้อผิดพลาดทั้งหมดเป็น "ชั่วคราว" และลองอีกครั้งในวงวนไม่สิ้นสุด บันทึกเริ่มบวมและมีการสร้างภาระที่ไม่จำเป็น พวกเขาเพิ่มการจำแนกข้อผิดพลาด: 404 ถือเป็นแบบถาวร การวนซ้ำหยุดทำงาน และรหัสโมเดลได้รับการแก้ไขแล้ว บทเรียน: อย่าลองผิดทุกครั้งอีกครั้ง

กรณีที่ 3 — การจัดการขีดจำกัดจากด้านหน้า งานการเพิ่มคุณค่าข้อมูลทำงานอย่างต่อเนื่องที่ขีดจำกัด 429 พวกเขาปฏิบัติตามส่วนหัวที่เหลืออยู่ของ x-ratelimit และควบคุมปริมาณการรับส่งข้อมูลตามโควต้า ดังนั้นพวกเขาจึงก้าวต่อไปอย่างมั่นคงต่ำกว่าขีดจำกัด โดยไม่ต้องใช้ 429 เลย งานสำเร็จลุล่วงได้อย่างคาดเดาได้และรวดเร็วยิ่งขึ้น

ข้อผิดพลาดทั่วไป

  • เพิ่มความเร็วใน 429: ทำให้สถานการณ์แย่ลง; เปลี่ยนไปล่าถอย
  • การลองใหม่แต่ละข้อผิดพลาด: 400/401/404 เป็นแบบถาวร การลองอีกครั้งเป็นการสิ้นเปลือง
  • การใช้การรอแบบคงที่: สร้างการชนกัน ใช้เอ็กซ์โปเนนเชียล + กระวนกระวายใจ
  • การละเว้น 'ลองใหม่หลังจาก': การปฏิบัติตามเวลาที่กำหนดโดยผู้ให้บริการจะแม่นยำที่สุด
  • เปิดเผยข้อผิดพลาดดิบแก่ผู้ใช้: ทำลายความไว้วางใจ สร้างช่องโหว่ จำแนกภายใน.
  • ลองใหม่ไม่จำกัด: ตั้งค่าขีดจำกัดบน (เช่น ลองใหม่ 5 ครั้ง) แล้วยอมแพ้อย่างสง่างาม

เจาะลึก: การเข้าคิว การทำงานพร้อมกัน และเซอร์กิตเบรกเกอร์

ความอดทนของความปรารถนาเดียวคือก้าวแรก วุฒิภาวะที่แท้จริงคือการจัดการคำขอจำนวนมากโดยไม่ถึงขีดจำกัด แนวคิดสามประการเข้ามามีบทบาทที่นี่

คิว: คุณวางคำขอไว้ในคิวเพื่อส่งคำขอเหล่านั้นในอัตราที่ควบคุมได้แทนที่จะส่งในทันที การเข้าคิวทำให้การรับส่งข้อมูลอย่างฉับพลันราบรื่นขึ้น: แม้ว่าคำขอ 1,000 รายการจะมาถึงในคราวเดียว คิวก็จะปล่อยคำขอเหล่านั้นในอัตราที่ต่ำกว่าขีดจำกัด ด้วยวิธีนี้คุณสามารถป้องกัน 429 ได้ คุณจึงไม่ต้องกังวลกับการแก้ไข

ขีดจำกัดการเกิดพร้อมกัน: คุณจำกัดจำนวนคำขอที่ "อยู่ในอากาศ" ในเวลาเดียวกัน คำขอแบบขนานไม่จำกัดเติมเต็มขีดจำกัด RPM และ TPM อย่างรวดเร็ว เพดานการทำงานพร้อมกันที่สมเหตุสมผล (เช่น ไม่เกิน 10 คำขอพร้อมกัน) จะรักษาขีดจำกัดและทำให้ระบบสามารถคาดเดาได้

เซอร์กิตเบรกเกอร์: หากผู้ให้บริการส่งคืน 500/529 อย่างต่อเนื่อง แทนที่จะพยายามทุกคำขออย่างไม่ลดละ คุณจะ "ทำลายวงจร" ชั่วขณะหนึ่งและทำให้คำขอล้มเหลวอย่างรวดเร็วโดยไม่เคยส่งเลย หลังจากรอสักครู่ ให้เปิดวงจรอีกครั้งแล้วลองอีกครั้ง รูปแบบนี้ป้องกันไม่ให้ระบบของคุณล่มในกรณีที่ผู้ให้บริการล้มเหลวชั่วคราว

เมื่อรวมกันแล้ว ทั้งสามอย่างนี้จะสร้างความยืดหยุ่นระดับระบบที่เหนือกว่าลอจิกการลองซ้ำของการโทรครั้งเดียว ในขนาดเล็ก การลองซ้ำอัตโนมัติของ SDK ก็เพียงพอแล้ว เมื่อขนาดเพิ่มขึ้น การเข้าคิว การทำงานพร้อมกัน และเซอร์กิตเบรกเกอร์ก็กลายเป็นสิ่งที่ขาดไม่ได้ ทั้งหมดมีเป้าหมายร่วมกัน นั่นคือ เพื่อสะท้อนปัญหาชั่วคราวให้กับผู้ใช้ ไม่ใช่เป็นการขัดข้อง แต่เป็นความล่าช้าที่มองไม่เห็นเพียงไม่กี่วินาที

โดยสรุป

429 ส่งคืนเมื่อเกินขีดจำกัดความเร็ว (RPM/ITPM/OTPM) นี่เป็นข้อผิดพลาดชั่วคราว และจะมีการลองอีกครั้งโดยใช้การลองใหม่หลังจากและ backoff เอ็กซ์โพเนนเชียล + กระวนกระวายใจ 500 และ 529 เป็นแบบชั่วคราวเช่นกัน 400/401/403/404 เป็นปัญหาเกี่ยวกับคำขอ/ข้อมูลประจำตัว และไม่สามารถแก้ไขได้ด้วยการลองอีกครั้ง โฟลว์ที่มีประสิทธิภาพจะแยกข้อผิดพลาดออกเป็นสองกลุ่มนี้ พยายามในจำนวนที่จำกัด ตรวจสอบขีดจำกัดจากด้านหน้า และแสดงข้อความที่สงบแก่ผู้ใช้

งานสมัคร

พิจารณาบูรณาการของคุณ (1) แสดงรายการรหัสข้อผิดพลาดที่คุณอาจพบ และแยกออกเป็น "ลองใหม่ได้ / ถาวร" (2) เขียนแผนการดึงกลับแบบเอ็กซ์โปเนนเชียลของคุณ (การระงับเริ่มต้น สัมประสิทธิ์ หมวก ความกระวนกระวายใจ) (3) ระบุวิธีการใช้ส่วนหัวการลองใหม่หลังจาก (4) เขียนข้อความสุภาพที่จะแสดงต่อผู้ใช้เมื่อหมดความพยายามอีกครั้ง

รายการตรวจสอบ

  • [ ] ฉันสามารถอธิบายขีดจำกัด RPM/ITPM/OTPM และ 429 ได้
  • [ ] ฉันสามารถใช้ตรรกะของการถอยแบบเอ็กซ์โพเนนเชียล + กระวนกระวายใจ + ลองใหม่อีกครั้ง
  • [ ] ฉันสามารถจำแนกรหัสข้อผิดพลาดเป็นแบบลองใหม่ได้/ถาวร
  • [ ] ฉันรู้ว่าเราไม่ควรลองผิดทุกครั้ง
  • [ ] แทนที่จะแสดงข้อผิดพลาดโดยตรง ฉันสามารถแสดงข้อความที่สงบและเน้นการดำเนินการแก่ผู้ใช้ได้