สมมติว่าเว็บไซต์ห้องสมุดแก้ไขเวลาเปิดทำการของวันนี้แล้ว แต่เบราว์เซอร์ยังแสดงเวลาเดิม สาเหตุอาจเป็นได้หลายอย่าง เช่น เนื้อหาที่เซิร์ฟเวอร์ต้นทางยังไม่เปลี่ยน เบราว์เซอร์ใช้สำเนาที่จัดเก็บไว้ หรือแคชตัวกลางส่งสำเนาเก่ามาให้ การกดโหลดซ้ำหลายครั้งเพียงอย่างเดียวยังแยกสาเหตุเหล่านี้ไม่ได้
แคช HTTP จัดเก็บการตอบกลับและนำกลับมาใช้เมื่อเป็นไปตามเงื่อนไขที่กำหนด บทความนี้เชื่อมโยง Cache-Control, ETag และ 304 ผ่านตัวอย่างเวลาเปิดทำการที่เผยแพร่สู่สาธารณะ ลำดับการรับส่งถูกทำให้ง่ายขึ้นและค่าต่าง ๆ เป็นค่าที่สมมติขึ้น ไม่ใช่ผลการวัดจากบริการจริง จุดมุ่งหมายคืออธิบายเงื่อนไขที่อนุญาตให้นำกลับมาใช้ เพื่อให้การตรวจปัญหาไม่จบลงเพียงการล้างแคชทั้งหมด
1. แยกการจัดเก็บ การตรวจสอบ และการแบ่งปันสำเนา
เมื่ออ่านนโยบายแคช ให้ถามสามข้อว่า จัดเก็บการตอบกลับได้หรือไม่ ใช้สำเนาที่จัดเก็บไว้ได้ทันทีหรือไม่ และแบ่งปันสำเนานั้นให้ผู้ใช้อื่นได้หรือไม่ การอนุญาตให้จัดเก็บไม่ได้แปลว่าใช้ซ้ำได้เสมอ และการตรวจการอัปเดตก็ไม่ได้ให้สิทธิ์แบ่งปันโดยอัตโนมัติ RFC 9111 แยกบทบาทของคำสั่งเหล่านี้ คำอธิบายต่อไปนี้กล่าวถึงคำสั่งในการตอบกลับที่ไม่มีอาร์กิวเมนต์ระบุชื่อฟิลด์
| คำถาม | คำสั่งในการตอบกลับ | ความแตกต่างที่ต้องจำ |
|---|---|---|
| จัดเก็บการตอบกลับไว้ใช้ในภายหลังได้หรือไม่ | no-store | ห้ามจัดเก็บเพื่อนำกลับมาใช้ในภายหลัง |
| ใช้สำเนาที่จัดเก็บไว้โดยไม่ตรวจสอบได้หรือไม่ | no-cache | จัดเก็บได้ แต่ต้องตรวจสอบสำเร็จก่อนนำกลับมาใช้ |
| จัดเก็บในแคชที่ใช้ร่วมกันได้หรือไม่ | private | ห้ามจัดเก็บในแคชที่ใช้ร่วมกัน แต่ไม่ได้ห้ามจัดเก็บในแคชส่วนตัว |
สำหรับเวลาเปิดทำการสาธารณะที่เปลี่ยนบ่อยบน URL เดิม การตรวจสอบก่อนนำกลับมาใช้อาจเหมาะสม ส่วนหน้าที่มีข้อมูลเฉพาะของผู้ใช้แต่ละคนมีข้อพิจารณาเรื่องการแบ่งปันต่างออกไป private ไม่ใช่กลไกเข้าสู่ระบบหรือตรวจสิทธิ์เข้าถึง หากปะปนวัตถุประสงค์เหล่านี้ การตอบกลับอาจถูกส่งให้ผู้รับที่ไม่ถูกต้อง
เมื่อทำตารางนโยบาย ให้บันทึกเหตุผลด้วย เช่น เวลาเปิดทำการต้องตรวจการอัปเดตหรือไม่ โลโก้คงเดิมหรือไม่ และ URL เดียวกันส่งเนื้อหาเฉพาะบุคคลหรือไม่ นี่เป็นจุดเริ่มต้นในการจำแนก ไม่ใช่ชุดการตั้งค่าที่ครบถ้วนสำหรับทุกเว็บไซต์ และต้องแยกการจัดเก็บในเบราว์เซอร์ออกจาก CDN หรือแคชที่ใช้ร่วมกันด้วย
2. อย่าตีความ no-cache และ no-store จากชื่อเพียงอย่างเดียว
ชื่อ no-cache อาจทำให้เข้าใจผิดว่าห้ามจัดเก็บ แต่ no-cache ในการตอบกลับอนุญาตให้จัดเก็บ โดยต้องตรวจสอบก่อนใช้สำเนานั้นอีกครั้ง หากเซิร์ฟเวอร์ยืนยันว่าเนื้อหาไม่เปลี่ยน ก็ใช้เนื้อหาการตอบกลับที่จัดเก็บไว้ได้ ส่วน no-store ขอให้ไม่จัดเก็บการตอบกลับนี้ไว้ใช้ซ้ำ สิ่งที่จะจัดเก็บกับสิ่งที่ต้องตรวจสอบในคำขอถัดไปเป็นคนละเรื่อง จึงไม่ควรคาดว่าการตั้งค่าทั้งสองจะทำงานเหมือนกัน
สถานะ fresh หมายถึงนโยบายอนุญาตให้ใช้ซ้ำโดยไม่ต้องตรวจสอบเพิ่มเติม ไม่ได้ยืนยันว่าเนื้อหาที่ต้นทางยังไม่เปลี่ยน เมื่อใช้ max-age สำเนาที่ยังอยู่ในอายุที่กำหนดอาจถูกส่งต่อไป แม้ต้นทางจะแก้เนื้อหาแล้วก็ตาม จึงควรกำหนดก่อนว่ายอมรับความล่าช้าในการอัปเดตได้เท่าใด แล้วจึงเลือกส่วนหัว อย่าถือว่าอายุแคชที่ยาวเป็นคำตอบสำหรับทุกหน้า
ดังที่ คู่มือแคชของ MDN อธิบาย การเพิ่ม no-store ในการตอบกลับใหม่ไม่ได้ลบการตอบกลับเก่าของ URL เดียวกันที่จัดเก็บไว้อยู่แล้วโดยอัตโนมัติ หากสำเนาเก่ายัง fresh คำขออาจยังไปไม่ถึงการตอบกลับใหม่และส่วนหัวใหม่ด้วยซ้ำ no-store ไม่ใช่คำสั่งล้างแคชหรือวิธีคุ้มครองความเป็นส่วนตัวที่ครบถ้วน ต้องตรวจอายุเดิมและวิธีอัปเดตแคชที่ตนจัดการด้วย
3. ติดตาม ETag และ 304 เมื่อกลับมาเข้าชม
สมมติว่า URL ที่แต่งขึ้น /hours.json ระบุว่าห้องสมุดปิดเวลา 18:00 น. ตัวอย่าง HTTP/1.1 ต่อไปนี้ย่อให้สั้นและไม่ได้แสดงส่วนหัวทั้งหมดที่อาจจำเป็น hours-v1 เป็นตัวระบุรูปแบบเนื้อหาที่เซิร์ฟเวอร์กำหนด ไม่ใช่สูตรเกี่ยวกับเวลาหรือค่าแฮชของไฟล์จริง
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache
ETag: "hours-v1"
{"closes":"18:00"}
หลังจัดเก็บการตอบกลับนี้ เบราว์เซอร์อาจส่ง ETag ผ่าน If-None-Match เมื่อตรวจสอบซ้ำ หากตัวระบุนี้ตรงกับรูปแบบเนื้อหาที่เซิร์ฟเวอร์เลือกในขณะนั้นและเนื้อหาไม่เปลี่ยน เซิร์ฟเวอร์อาจตอบ 304 บล็อกต่อไปแสดงคำขอก่อนแล้วตามด้วยการตอบกลับอย่างย่อ ไม่มี JSON ใหม่ถูกส่งหลังการตอบกลับ 304
GET /hours.json HTTP/1.1
Host: library.example
If-None-Match: "hours-v1"
HTTP/1.1 304 Not Modified
Cache-Control: no-cache
ETag: "hours-v1"
ตาม คำอธิบาย ETag ของ MDN ไคลเอนต์จึงใช้เนื้อหาที่จัดเก็บไว้ได้ การตอบกลับ 304 ไม่มีเนื้อหา แต่การส่งคำขอและการตรวจสอบยังต้องสื่อสารผ่านเครือข่าย หากเปลี่ยนเวลาปิดเป็น 19:00 น. และรูปแบบเนื้อหาเปลี่ยน ผลที่คาดหวังคือ 200 พร้อมเนื้อหาและแท็กใหม่ no-cache ไม่ได้หมายความว่าทุกครั้งต้องได้ 304 หรือจะไม่มีการสอบถามฐานข้อมูลเลย
ดังนั้นต้องตรวจความสัมพันธ์ระหว่างเนื้อหากับแท็ก ไม่ใช่ดูเพียงรหัสสถานะ หากเนื้อหาเปลี่ยนแต่ยังใช้แท็กเดิม การตรวจสอบอาจตัดสินผิด หากเนื้อหาเดิมแต่แท็กเปลี่ยนตลอด ก็อาจส่งเนื้อหาซ้ำมากขึ้น ให้ตรวจวิธีที่เซิร์ฟเวอร์สร้างรูปแบบเนื้อหาและตัวระบุ การมี ETag เพียงอย่างเดียวยังยืนยันไม่ได้ว่าระบบทำงานถูกต้อง
4. แยกเอกสารที่เปลี่ยนจากไฟล์ทรัพยากรที่มีชื่อใหม่
เอกสารเวลาเปิดทำการที่อัปเดตบน URL เดิมต่างจากโลโก้หรือสคริปต์ที่เปลี่ยนชื่อไฟล์เมื่ออัปเดต หากเปลี่ยน logo.a1.png เป็น logo.b2.png เอกสารใหม่ต้องชี้ไปยัง URL ใหม่ การเขียนทับเนื้อหาเดิมทั้งที่ใส่ตัวระบุไว้ในชื่อไฟล์จะทำลายข้อตกลงระหว่างที่อยู่กับเนื้อหา
การอัปโหลดไฟล์ใหม่ไม่ได้ทำให้เบราว์เซอร์ขอไฟล์นั้นโดยอัตโนมัติ หาก HTML เก่ายังอ้างถึงโลโก้เก่า ก็อาจใช้ทรัพยากรเดิมต่อไป จึงต้องตรวจทั้งการอัปเดตเอกสารและส่วนหัวของทรัพยากร ความล่าช้าที่ยอมรับได้ของเนื้อหาแต่ละชนิดไม่จำเป็นต้องเท่ากัน อายุแคชจึงไม่จำเป็นต้องเหมือนกันทั้งหมด
ระหว่างนำรุ่นใหม่ขึ้นใช้งาน เอกสารเก่าและใหม่อาจอยู่พร้อมกัน เอกสารใหม่อาจผิดพลาดหากเผยแพร่ก่อนทรัพยากรพร้อม และเอกสารเก่าอาจเสียหากลบทรัพยากรเก่าเร็วเกินไป ต้องตรวจว่าทรัพยากรใหม่มีอยู่แล้วและทรัพยากรเก่ายังเข้าถึงได้ รูปแบบการตั้งชื่อไฟล์ไม่ได้แก้ปัญหาการนำขึ้นใช้งานหรือการย้อนรุ่นให้เอง
5. ใช้แผง Network ทดสอบข้อสันนิษฐาน
เริ่มจากสังเกตสภาวะพื้นฐานที่อนุญาตให้ใช้แคช บันทึก URL เต็มรวมพารามิเตอร์คิวรี รุ่นของเวลาเปิดทำการที่เห็น รหัสสถานะ If-None-Match ในคำขอ รวมถึง Cache-Control และ ETag ในการตอบกลับ ส่วนหัวคำขอและการตอบกลับแสดงเงื่อนไขของคนละฝ่าย แม้ชื่อเหมือนกันก็ต้องระบุว่าอยู่ฝั่งใด เอกสารแผง Network ของ Chrome อธิบายวิธีตรวจค่าในแท็บ Headers
| เงื่อนไขทดสอบ | สิ่งที่ต้องบันทึก | ข้อสรุปที่ควรหลีกเลี่ยง |
|---|---|---|
| กลับมาดูเวลาเปิดทำการที่ยังไม่แก้ไข | คำขอแบบมีเงื่อนไข รหัสสถานะ และเวลาที่แสดง | คิดว่า 304 หมายถึงไม่มีการสื่อสารผ่านเครือข่าย |
| แก้เวลาเปิดทำการที่ต้นทาง | เนื้อหาใหม่ แท็ก และ URL ที่ร้องขอจริง | คิดว่าบันทึกสำเร็จหมายถึงผู้ใช้ทุกคนได้ข้อมูลใหม่แล้ว |
| ปิดแคชเบราว์เซอร์ | ความต่างระหว่างการดาวน์โหลดครั้งแรกกับการเข้าชมซ้ำตามปกติ | ถือว่าผลนี้แทนความเร็วของการเข้าชมซ้ำทั่วไป |
| ย้อนกลับหน้าก่อน | มีคำขอใหม่หรือไม่ และหน้าจอใดถูกกู้คืน | คิดว่าการเห็นหน้าจอพิสูจน์ว่าได้ตรวจสอบ HTTP แล้ว |
การทดสอบขณะปิดแคชเป็นเงื่อนไขอีกแบบหนึ่ง ตัวเลือก Disable cache ของ Chrome มีผลขณะเปิด DevTools จึงต้องบันทึกทั้งการเปิดเครื่องมือและสถานะตัวเลือก การทดสอบดาวน์โหลดครั้งแรกไม่เหมือนการใช้ซ้ำตามปกติ หากลืมตัวเลือกนี้ การดาวน์โหลดใหม่ทุกครั้งอาจถูกเข้าใจผิดว่าแคชเสีย ให้เก็บเงื่อนไขไว้เปรียบเทียบหลังเปิดใช้แคชอีกครั้ง
เปลี่ยนทีละอย่าง เริ่มจากสังเกตการเข้าชมซ้ำโดยยังไม่แก้ไข แล้วเปลี่ยนข้อมูลเวลาเปิดทำการหนึ่งฟิลด์ หากเปลี่ยน URL การตั้งค่าเซิร์ฟเวอร์ และชื่อไฟล์พร้อมกัน จะแยกสาเหตุได้ยาก เมื่อได้ 200 หรือ 304 ไม่ตรงคาด ให้ดูการรับส่งที่เกิดขึ้นจริงก่อนเพิ่มการตั้งค่าอื่น
6. ตรวจที่จัดเก็บอื่นและเกณฑ์ว่างานเสร็จ
การปิดแคช HTTP ในเบราว์เซอร์ไม่ได้แปลว่าปิดแคช CDN หรือที่จัดเก็บอื่นของแอปด้วย ต้องแยกตรวจ service worker การเลือกสำเนาของตัวกลาง และข้อมูลที่แอปเก็บค้างไว้ แม้ URL เดียวกัน สำเนาก็ไม่ได้มาจากชั้นเดียวกันเสมอไป
การย้อนกลับหน้าก่อนต้องแยกจากการส่งคำขอ HTTP ใหม่เช่นกัน หน้าจอจากเซสชันก่อนอาจถูกกู้คืนโดยไม่มีการตรวจสอบซ้ำตามที่คาด แม้จะใช้ no-cache ก็ได้ จึงยังไม่ใช่หลักฐานว่าเซิร์ฟเวอร์ละเลยส่วนหัว ให้บันทึกคำขอที่เกิดขึ้นจริงในการนำทางใหม่ โหลดซ้ำ และย้อนกลับ
ความสำเร็จไม่ได้วัดจากอัตราที่พบข้อมูลในแคชเพียงอย่างเดียว ต้องมั่นใจว่าเนื้อหาที่ไม่เปลี่ยนถูกใช้ซ้ำอย่างถูกต้อง การเปลี่ยนแปลงมาถึงภายในเวลาที่กำหนด และแบ่งปันสำเนาให้ผู้รับที่ถูกต้อง บันทึกเวลาแก้ไข เวลาสังเกต เงื่อนไขทดสอบ และเนื้อหาจริงเพื่อทำซ้ำปัญหา หากเว็บไซต์เร็วขึ้นแต่แสดงเวลาเปิดทำการผิดนานเกินไป ก็ยังไม่ตรงความต้องการ
สำหรับบริการจริง ให้กำหนดนโยบายแยกตามการตอบกลับ พร้อมวิธีอัปเดตและย้อนรุ่น อย่านำการตั้งค่าของเนื้อหาสาธารณะไปใช้กับการตอบกลับส่วนบุคคลโดยตรง และอย่าถือว่าการตรวจสอบแคชเป็นการให้สิทธิ์เข้าถึง ส่วนหัวกำหนดกติกาการจัดเก็บและการใช้ซ้ำ การอธิบายได้ว่าเก็บอะไร ตรวจสอบอะไร และตอนนี้แสดงสำเนาจากที่ใด จะช่วยวินิจฉัยปัญหาได้ชัดขึ้น