Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

การแคชฝั่งไคลเอ็นต์ใน Rails:คำขอ GET แบบมีเงื่อนไข

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

👋 และหากคุณต้องการอ่านเพิ่มเติมเกี่ยวกับประสิทธิภาพนอกแคช ยังมีอีกมากมายที่เราเขียนเกี่ยวกับประสิทธิภาพของ Ruby (on Rails) ให้ดูที่รายการตรวจสอบการตรวจสอบประสิทธิภาพของ Ruby

ส่วนหัว Etag และ Last-Modified

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

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

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

~ $ curl -I https://localhost:3000/products/1
HTTP/1.1 200 OK
...
ETag: W/"9462d76cc55aeb6249fa990e39231c7c"
Last-Modified: Wed, 25 Apr 2018 08:27:04 GMT
...

หากมีการตอบกลับซ้ำในภายหลัง เบราว์เซอร์จะค้นหาการตอบสนองที่มีอยู่ในแคชและใช้ Etag ที่เก็บไว้จากคำขอล่าสุดเป็น If-None-Match หัวข้อ. ส่วนหัวนี้จะบอกแอป Rails ของเราว่าเรามีเวอร์ชันนี้อยู่ในแคชแล้ว

หาก Etag จากคำขอตรงกับปัจจุบัน Rails จะส่ง 304 Not Modified การตอบสนองโดยไม่มีร่างกายตอบสนอง การดำเนินการนี้จะบอกให้เบราว์เซอร์ใช้เบราว์เซอร์จากแคชในเครื่องแทน

~ $ curl -i -H 'If-None-Match: W/"9462d76cc55aeb6249fa990e39231c7c"' https://localhost:3000/products/1
HTTP/1.1 304 Not Modified
...
ETag: W/"9462d76cc55aeb6249fa990e39231c7c"
Last-Modified: Wed, 25 Apr 2018 08:27:04 GMT
...

คำขอ GET แบบมีเงื่อนไขใน Rails

หากเราขอหน้าจากแอปพลิเคชัน Rails ในพื้นที่ เราจะเห็นว่า Rails เพิ่ม Etag สำหรับแต่ละคำขอโดยอัตโนมัติ หากเราขอหน้าเดียวกันสองครั้งติดต่อกัน เราจะเห็นการเปลี่ยนแปลง Etag สำหรับแต่ละคำขอ

แม้ว่า Rails จะสร้าง Etag สำหรับแต่ละคำขอโดยค่าเริ่มต้น แต่จะใช้ไดเจสต์ของเนื้อหาการตอบสนองทั้งหมดเพื่อสร้าง นี่หมายถึง <%= csrf_meta_tags %> ในเลย์เอาต์จะทิ้ง Etag ออก เนื่องจากเมตาแท็ก csrf-token เปลี่ยนแปลงสำหรับแต่ละคำขอ เนื่องจากนั่นเปลี่ยนเนื้อความสำหรับแต่ละคำขอ Etag จะใช้ไม่ได้และแคชในเครื่องถูกทำเครื่องหมายว่าเก่า

นอกจากนั้น Rails จะไม่ส่งคืน 304 Not Modified โดยค่าเริ่มต้น เนื่องจากแคชในเครื่องจะไม่ถูกทำเครื่องหมายว่าใหม่อย่างชัดแจ้งในคอนโทรลเลอร์ของเรา

fresh_when และ stale?

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

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

Rails มาพร้อมกับตัวช่วยที่ทำทุกอย่างเพื่อเรา เราสามารถกำหนด Etag และวันที่แก้ไขล่าสุดบนผลิตภัณฑ์ได้อย่างชัดเจนโดยใช้ fresh_when .

# app/views/products/show.html.erb
def show
  @product = Product.find(params[:id])
  fresh_when @product
end

หากคุณมี respond_to . ที่ชัดเจน บล็อก ใช้ stale? แทนที่จะเป็น fresh_when .

# app/views/products/show.html.erb
def show
  @product = Product.find(params[:id])
 
  if stale?(@product)
    respond_to do |format|
      format.html
    end
  end
end

ตอนนี้ การขอหน้าผลิตภัณฑ์หน้าใดหน้าหนึ่งจะแคชการตอบกลับในเครื่อง คำขอใดๆ ที่ตามมาในหน้าเดียวกันจะรวม Etag เพื่อบอก Rails ว่าเรามีการตอบสนองที่แคชไว้ ซึ่งจะถูกนำไปเปรียบเทียบกับ Etag ใหม่ หากตรงกัน Rails จะข้ามการแสดงผลหน้าและส่งคืน 304 Not Modified ทันที

หมายเหตุ :การรีเฟรชหน้าจะขอหน้าเวอร์ชันที่ไม่ได้แคชเสมอ หากต้องการทดสอบว่า GET แบบมีเงื่อนไขของคุณใช้งานได้หรือไม่ ให้ไปที่ลิงก์หรือใช้ปุ่มย้อนกลับแทน

คุณชอบบทความนี้และบทความก่อนหน้าในซีรีส์ AppSignal Academy อย่างไร เรามีบทความเพิ่มเติมเกี่ยวกับการแคชใน Rails เรียงกัน แต่โปรดอย่าลังเลที่จะแจ้งให้เราทราบว่าคุณต้องการให้เราเขียนเกี่ยวกับอะไร (เกี่ยวกับการแคชหรืออย่างอื่น) ต่อไป!