ETag กับส่วนหัวหมดอายุ


359

ฉันได้ดูไปรอบ ๆ แต่ไม่สามารถคิดออกได้ว่าฉันควรใช้ทั้ง ETag และ Expires Header หรืออย่างใดอย่างหนึ่ง

สิ่งที่ฉันพยายามทำคือตรวจสอบให้แน่ใจว่าไฟล์แฟลชของฉัน (และรูปภาพอื่น ๆ และสิ่งที่ไม่เพียง แต่ได้รับการปรับปรุงเมื่อมีการเปลี่ยนแปลงไฟล์เหล่านั้น

ฉันไม่ต้องการทำอะไรเป็นพิเศษเช่นเปลี่ยนชื่อไฟล์หรือวางตัวอักษรแปลก ๆ ไว้ท้าย URL เพื่อไม่ให้แคช

นอกจากนี้ยังมีสิ่งใดบ้างที่ฉันต้องทำในตอนท้ายของสคริปต์ PHP ของฉันเพื่อสนับสนุนสิ่งนี้หรือเป็น Apache ทั้งหมดหรือไม่


คำตอบ:


677

พวกเขาแตกต่างกันเล็กน้อย - ETag ไม่มีข้อมูลใด ๆ ที่ลูกค้าสามารถใช้เพื่อพิจารณาว่าจะทำการร้องขอไฟล์นั้นอีกครั้งหรือไม่ในอนาคต หาก ETag เป็นทั้งหมดที่มีอยู่จะต้องทำการร้องขอเสมอ อย่างไรก็ตามเมื่อเซิร์ฟเวอร์อ่าน ETag จากการร้องขอของไคลเอนต์เซิร์ฟเวอร์สามารถกำหนดได้ว่าจะส่งไฟล์ (HTTP 200) หรือบอกให้ไคลเอนต์เพียงแค่ใช้สำเนาโลคัล (HTTP 304) ETag นั้นเป็นเพียงการตรวจสอบสำหรับไฟล์ที่เปลี่ยนความหมายเมื่อเนื้อหาของไฟล์เปลี่ยนไป

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

ดังนั้นสิ่งที่คุณต้องการทำจริงๆคือใช้ส่วนหัวทั้งสอง - ตั้งค่าส่วนหัว Expires ให้เป็นค่าที่เหมาะสมตามความถี่ที่เนื้อหาเปลี่ยนแปลง จากนั้นกำหนดค่า ETags ที่จะส่งเพื่อให้เมื่อไคลเอนต์ส่งคำขอไปยังเซิร์ฟเวอร์จะสามารถกำหนดได้ง่ายขึ้นว่าจะส่งไฟล์กลับหรือไม่

หมายเหตุสุดท้ายหนึ่งเกี่ยวกับ ETag - หากคุณใช้การตั้งค่าเซิร์ฟเวอร์ที่สมดุลกับเครื่องหลายเครื่องที่ใช้ Apache คุณอาจต้องการปิดการสร้าง ETag เนื่องจาก inodes ถูกใช้เป็นส่วนหนึ่งของอัลกอริทึมแฮช ETag ซึ่งจะแตกต่างกันระหว่างเซิร์ฟเวอร์ คุณสามารถกำหนดค่า Apache ให้ไม่ใช้ inodes เป็นส่วนหนึ่งของการคำนวณได้ แต่คุณต้องการตรวจสอบให้แน่ใจว่า timestamps ของไฟล์เหมือนกันทุกประการเพื่อให้แน่ใจว่า ETag ตัวเดียวกันจะถูกสร้างขึ้นสำหรับเซิร์ฟเวอร์ทั้งหมด


12
คุณควรตรวจสอบว่าคุณควรใช้การควบคุมแคชแทนการหมดอายุหรือไม่ ความเข้าใจของฉันคือการควบคุมแคชได้รับการแนะนำหลังจากหมดอายุและช่วยให้คุณควบคุมได้มากขึ้น ดูstackoverflow.com/questions/5799906/…
Luis Perez

6
เมื่อใช้ส่วนหัว Expires เป็นแนวปฏิบัติที่ดีในการเปลี่ยนชื่อไฟล์ทุกครั้งที่มีการเปลี่ยนแปลงทรัพยากรเนื่องจากไคลเอนต์จะไม่ร้องขอไฟล์อีกครั้งก่อนที่จะหมด โดยเฉพาะอย่างยิ่งถ้าคุณใช้ค่าในอนาคตไกลเป็นวันหมดอายุ
schnatterer

8
ให้บอกว่าเราจะใช้ทั้งสองอย่าง จะเกิดอะไรขึ้นเมื่อเวลาหมดอายุหมดอายุ แต่ไฟล์จะไม่เปลี่ยนแปลง (Etag เหมือนกัน)? เซิร์ฟเวอร์จะส่งคืน 304 และไฟล์จะแสดงจากแคชของเบราว์เซอร์ คำถามของฉันคือจะถูกสร้างใหม่เวลาหมดอายุในขณะนี้?
user345602

2
ระวังการตั้งค่า ETAG และส่วนหัว Expires ให้เป็นค่าที่ไม่ใช่ศูนย์ สิ่งนี้สามารถนำไปสู่สภาพการแข่งขัน ดูjakearchibald.com/2016/caching-best-practices
Weston

2
เป็นไปได้หรือไม่ที่จะบอกเซิร์ฟเวอร์ไม่ให้ใช้ inodes หรือ timestamps เลย? นอกจากนี้ทำไมพวกเขาจึงจำเป็นต้องใช้ ETags หากมันถูกใช้เพื่อแสดงเนื้อหาเท่านั้น
Seza

108

EtagและLast-modified header เป็นเครื่องมือตรวจสอบความถูกต้อง

พวกเขาช่วยเบราว์เซอร์และ / หรือแคช (reverse proxy) เพื่อทำความเข้าใจว่าไฟล์ / หน้ามีการเปลี่ยนแปลงแม้ว่าจะรักษาชื่อเดียวกัน

หมดอายุและแคชควบคุมจะให้ข้อมูลการฟื้นฟู

ซึ่งหมายความว่าพวกเขาแจ้งเบราว์เซอร์และย้อนกลับในระหว่างพร็อกซี่ถึงเวลาหรือนานเท่าใดพวกเขาอาจเก็บหน้า / ไฟล์ที่แคชของพวกเขา

ดังนั้นคำถามมักจะเป็นตัวตรวจสอบที่จะใช้ Etag หรือแก้ไขล่าสุดและส่วนหัวของข้อมูลที่รีเฟรชที่จะใช้หมดอายุหรือควบคุมแคช


31

ExpiresและCache-Controlเป็น "ส่วนหัวแคชที่แข็งแกร่ง"

Last-Modified และ ETagเป็น "ส่วนหัวแคชอ่อนแอ"

ก่อนตรวจสอบเบราว์เซอร์ Expires/Cache-Controlเพื่อพิจารณาว่าจะทำการร้องขอไปยังเซิร์ฟเวอร์หรือไม่

หากจำเป็นต้องทำการร้องขอมันจะส่งLast-Modified/ETagคำขอ HTTP หากEtagค่าของเอกสารตรงกับที่เซิร์ฟเวอร์จะส่งรหัส 304 แทน 200 และไม่มีเนื้อหา เบราว์เซอร์จะโหลดเนื้อหาจากแคช


1
คุณพบเอกสารใด ๆ ที่สนับสนุนพฤติกรรมการแคช "แข็งแรงและอ่อนแอ"? ฉันหาไม่เจอและเบราว์เซอร์ไคลเอ็นต์ของฉันให้ความสำคัญกับการปรับเปลี่ยนครั้งล่าสุดมากกว่าวันหมดอายุจริง ๆ แล้วซึ่งฉันไม่เข้าใจว่าทำไม
GMsoF

1
@GMsoF คุณอาจต้องการดูสิ่งนี้: tools.ietf.org/html/rfc7232#section-2.1
Medeiros

ดังนั้นหากฉันต้องการตรวจสอบให้แน่ใจว่าการเปลี่ยนแปลงของฉันถูกเผยแพร่ไปยังลูกค้าทันที แต่ยังคงได้รับประโยชน์จากการแคชบางอย่างฉันสามารถใช้ Last-Modified และ ETag ใช่มั้ย
Sebastien Lorber

นี่เป็นคำตอบที่กระชับที่สุดและยังชัดเจนสำหรับฉัน! ขอบคุณ
aderchox

18

โดยค่าเริ่มต้น Apache จะสร้าง Etag ตามหมายเลขไอโหนดของไฟล์วันที่แก้ไขล่าสุดและขนาดซึ่งควรจะดีพอที่จะทำสิ่งที่คุณต้องการ ฉันคิดว่ามันจะสร้างเป็นค่าเริ่มต้นด้วยส่วนหัว Last-Modified โดยยึดตามเวลาการแก้ไขครั้งล่าสุดของไฟล์บนดิสก์ซึ่งก็ดีพอที่จะทำสิ่งที่คุณต้องการ

คุณควรให้ Apache ส่งส่วนหัววันหมดอายุหนึ่งปีในอนาคต (ตามhttp://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21 ) เพื่อให้เบราว์เซอร์รู้ว่าเนื้อหานั้นคือ แคช ดูที่mod_expiresเพื่อกำหนดค่า


ดังนั้น ETag จะมีการปรับเปลี่ยนครั้งล่าสุดและส่วนหัวหมดอายุจะบอกว่าฉันต้องการให้แคชและเมื่อฉันอัปโหลดและเขียนทับไฟล์ของฉันมันจะถูกดึงลงไปที่แคชของผู้ใช้อีกครั้งมิฉะนั้นจะสร้าง 304 ใช่มั้ย
GeoffreyF67

Etag ขึ้นอยู่กับวิธีที่ซับซ้อนในวันที่แก้ไขล่าสุด แต่เมื่อคุณแก้ไขไฟล์ Etag จะเปลี่ยน จากนั้น Etag ที่ส่งมาจากเบราว์เซอร์ (สำหรับเวอร์ชันแคชของไฟล์) จะไม่ตรงกับ Etag ของไฟล์บนเซิร์ฟเวอร์และ Apache จะส่งไฟล์มากกว่าการตอบกลับ 304
David Z

6
ส่วนหัวที่หมดอายุหนึ่งปีจะไม่บอกลูกค้าว่าจะไม่ตรวจสอบเวอร์ชันใหม่เป็นเวลาหนึ่งปีใช่หรือไม่
John Bachir

@ จอห์น: ใช่ฉันเดาฉันคิดว่าเนื้อหาคงที่ไม่เคยเปลี่ยนแปลงเมื่อฉันเขียนว่า
David Z

2
@John Bachir: นั่นคือสิ่งที่พูดเกินจริงเบราว์เซอร์ แต่ดูเหมือนว่าเบราว์เซอร์จะโจมตีเซิร์ฟเวอร์อย่างน้อยก็เพื่อสอบถามรุ่นใหม่ ฉันเปิดคำถามอีกข้อเกี่ยวกับปัญหานี้: stackoverflow.com/questions/10048740/…
Marco Demaio

13

สรุปอื่น:

คุณต้องใช้ทั้งคู่ ETags เป็นข้อมูล "ฝั่งเซิร์ฟเวอร์" การหมดอายุเป็นแคช "ฝั่งไคลเอ็นต์"

  • ใช้ETagsยกเว้นในกรณีที่คุณมีเซิร์ฟเวอร์ที่ปรับสมดุลโหลด ปลอดภัยและจะแจ้งให้ลูกค้าทราบว่าควรได้รับไฟล์เซิร์ฟเวอร์เวอร์ชันใหม่ทุกครั้งที่คุณเปลี่ยนแปลงบางสิ่ง

  • ต้องหมดอายุด้วยความระมัดระวังราวกับว่าคุณกำหนดวันหมดอายุไว้ในอนาคต แต่ต้องการเปลี่ยนหนึ่งในไฟล์ทันที (เช่นไฟล์ JS) ผู้ใช้บางคนอาจไม่ได้รับการแก้ไขจนกว่าจะถึงเวลาอันยาวนาน!


2
ในกรณีที่สถานการณ์หมดอายุคุณจะต้องเปลี่ยนชื่อ js ของคุณและเปลี่ยนเป็น HTML และหวังว่าคุณจะไม่ได้ตั้งค่าไฟล์ HTML นั้นหมดอายุ 1 ปีเช่นกัน
EralpB

1

สิ่งหนึ่งที่เพิ่มเติมที่ผมอยากจะพูดถึงว่าบางคำตอบอาจจะพลาดเป็นข้อเสียที่จะมีทั้งสองETagsและExpires/Cache-controlในส่วนหัวของคุณ

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

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในบล็อกโพสต์ที่ยอดเยี่ยมนี้โดย Kyle Simpson: http://calendar.perfplanet.com/2010/bloated-request-response-headers/


1

ในมุมมองของฉันด้วย Expire Header เซิร์ฟเวอร์สามารถบอกลูกค้าได้ว่าข้อมูลของฉันจะค้างเมื่อใช้ Etag เซิร์ฟเวอร์จะตรวจสอบค่า etag สำหรับคำขอของลูกค้าแต่ละครั้ง


0

ETag ใช้เพื่อตรวจสอบว่าทรัพยากรควรใช้สำเนาหรือไม่ และหมดอายุส่วนหัวเช่นการควบคุมแคชจะบอกลูกค้าว่าก่อนที่จะมีการแคชนานหลายทศวรรษลูกค้าควรดึงทรัพยากรในท้องถิ่น

ในเว็บไซต์ที่ทันสมัยมักจะมีไฟล์ชื่อแฮชเช่น app.98a3cf23.jsเพื่อให้เป็นวิธีปฏิบัติที่ดีในการใช้ Expires Header นอกจากนี้ยังช่วยลดค่าใช้จ่ายของเครือข่าย

หวังว่ามันจะช่วย;)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.