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

เซสชัน Rails ทำงานอย่างไร

จะเกิดอะไรขึ้นถ้าแอป Rails ของคุณไม่สามารถบอกได้ว่าใครเข้ามาเยี่ยมชม หากคุณไม่ทราบว่าบุคคลเดียวกันขอสองหน้าที่แตกต่างกัน? หากข้อมูลทั้งหมดที่คุณเก็บไว้หายไปทันทีที่คุณตอบกลับ?

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

session เป็นสถานที่ที่เหมาะที่จะใส่ข้อมูลประเภทนี้ ข้อมูลเล็กน้อยที่คุณต้องการเก็บไว้มากกว่าหนึ่งคำขอ

เซสชันใช้งานง่าย:

session[:current_user_id] = @user.id

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

เซสชันคืออะไร

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

คุณตั้งค่าข้อมูลบางส่วนได้ในการดำเนินการของผู้ควบคุม:

app/controllers/sessions_controller.rb
def create
  # ...
  session[:current_user_id] = @user.id
  # ...
end

และอ่านในอีกอันหนึ่ง:

app/controllers/users_controller.rb
def index
  current_user = User.find_by_id(session[:current_user_id])
  # ...
end

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

เมื่อคุณขอหน้าเว็บ เซิร์ฟเวอร์สามารถตั้งค่าคุกกี้เมื่อตอบกลับ:

~ jweiss$ curl -I https://www.google.com | grep Set-Cookie

Set-Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly

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

...
> GET / HTTP/1.1
> User-Agent: curl/7.37.1
> Host: www.google.com
> Accept: */*
> Cookie: NID=67=J2xeyegolV0SSneukSOANOCoeuDQs7G1FDAK2j-nVyaoejz-4K6aouUQtyp5B_rK3Z7G-EwTIzDm7XQ3_ZUVNnFmlGfIHMAnZQNd4kM89VLzCsM0fZnr_N8-idASAfBEdS; expires=Wed, 16-Sep-2015 05:44:42 GMT; path=/; domain=.google.com; HttpOnly
...

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

สิ่งนี้เกี่ยวข้องกับเซสชันอย่างไร

ดังนั้น คุณมีคุกกี้ คุณใส่ข้อมูลในคำขอหนึ่งครั้ง และคุณจะได้รับข้อมูลเดียวกันในครั้งต่อไป เซสชันนั้นกับเซสชันต่างกันอย่างไร

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

แต่คุกกี้ไม่ใช่คำตอบที่ถูกต้องเสมอไปสำหรับข้อมูลเซสชัน:

  • คุณสามารถเก็บข้อมูลได้ประมาณ 4kb ในคุกกี้

    นี่คือ โดยปกติ เพียงพอ แต่บางครั้งก็ไม่

  • คุกกี้จะถูกส่งไปพร้อมกับทุกคำขอของคุณ

    คุกกี้ขนาดใหญ่หมายถึงคำขอและการตอบกลับที่ใหญ่กว่า ซึ่งหมายถึงเว็บไซต์ที่ช้ากว่า

  • หากคุณเปิดเผย secret_key_base . ของคุณโดยไม่ได้ตั้งใจ ผู้ใช้ของคุณสามารถเปลี่ยนข้อมูลที่คุณใส่ไว้ในคุกกี้ได้

    เมื่อสิ่งนี้รวมถึงสิ่งต่าง ๆ เช่น current_user_id ทุกคนสามารถเป็นผู้ใช้ใดก็ได้ที่พวกเขาต้องการ!

  • การจัดเก็บข้อมูลผิดประเภทภายในคุกกี้อาจไม่ปลอดภัย

หากคุณระมัดระวัง สิ่งเหล่านี้ไม่ใช่ปัญหาใหญ่

แต่เมื่อคุณไม่สามารถจัดเก็บข้อมูลเซสชันของคุณไว้ในคุกกี้ได้ด้วยเหตุผลข้อใดข้อหนึ่งเหล่านี้ Rails มีที่อื่นอีกสองสามแห่งที่จะเก็บเซสชันของคุณ:

ร้านเซสชันทางเลือก

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

หากคุณกำลังติดตามเซสชันของคุณด้วย ActiveRecord:

  1. เมื่อคุณเรียก session[:current_user_id] = 1 ในแอปของคุณ และไม่มีเซสชันอยู่แล้ว:

  2. Rails จะสร้างบันทึกใหม่ใน session . ของคุณ ตารางที่มีรหัสเซสชันแบบสุ่ม (เช่น 09497d46978bf6f32265fefb5cc52264 )

  3. มันจะเก็บ {current_user_id: 1} (เข้ารหัส Base64) ใน data แอตทริบิวต์ของระเบียนนั้น

  4. และจะส่งคืน ID เซสชันที่สร้างขึ้น 09497d46978bf6f32265fefb5cc52264 ไปยังเบราว์เซอร์โดยใช้ Set-Cookie .

ครั้งต่อไปที่คุณขอหน้า

  1. เบราว์เซอร์ส่งคุกกี้เดียวกันนั้นไปยังแอปของคุณ โดยใช้ Cookie: ส่วนหัว

    (เช่นนี้:Cookie: _my_app_session=09497d46978bf6f32265fefb5cc52264;
    path=/; HttpOnly )

  2. เมื่อคุณเรียก session[:current_user_id] :

  3. แอปของคุณดึงรหัสเซสชันออกจากคุกกี้ และค้นหาบันทึกใน session ตาราง

  4. จากนั้นจะส่งกลับ current_user_id ออกจาก data แอตทริบิวต์ของระเบียนนั้น

ไม่ว่าคุณจะจัดเก็บเซสชันในฐานข้อมูล ใน Memcached ใน Redis หรือที่ใดก็ตาม ส่วนใหญ่จะทำตามขั้นตอนเดียวกันนี้ คุกกี้ของคุณ เท่านั้น มี ID เซสชัน และแอป Rails ของคุณจะค้นหาข้อมูลในที่เก็บเซสชันของคุณโดยใช้ ID นั้น

เมื่อใช้งานได้ การจัดเก็บเซสชันของคุณในคุกกี้เป็นวิธีที่ง่ายที่สุด ไม่จำเป็นต้องมีโครงสร้างพื้นฐานหรือการตั้งค่าเพิ่มเติม

แต่ถ้าคุณต้องการย้ายมากกว่าที่เก็บเซสชันคุกกี้ คุณมีสองตัวเลือก:

จัดเก็บเซสชันในฐานข้อมูล หรือเก็บไว้ในแคชของคุณ

การจัดเก็บเซสชันในแคช

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

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

แต่ยังไม่สมบูรณ์แบบ:

  • หากคุณสนใจที่จะเก็บเซสชันเก่าไว้จริงๆ คุณอาจไม่ต้องการ ต้องการ ให้ถูกไล่ออกจากแคช

  • เซสชันและข้อมูลแคชของคุณจะต่อสู้เพื่อพื้นที่ หากคุณมีหน่วยความจำไม่เพียงพอ คุณอาจประสบปัญหาแคชจำนวนมากและเซสชันที่หมดอายุก่อนกำหนด

  • หากคุณจำเป็นต้องรีเซ็ตแคชของคุณ (สมมติว่าคุณอัปเกรด Rails แล้วและข้อมูลที่แคชไว้เก่าของคุณไม่แม่นยำอีกต่อไป) ไม่มีทางที่จะทำเช่นนั้นได้โดยไม่ทำให้ทุกคนหมดอายุ เซสชัน

อย่างไรก็ตาม นี่คือวิธีที่เราจัดเก็บข้อมูลเซสชันที่ Avvo และมันใช้ได้ผลดีสำหรับเราจนถึงตอนนี้

การจัดเก็บเซสชันในฐานข้อมูล

ถ้าคุณต้องการเก็บข้อมูลเซสชันของคุณไว้จนกว่าจะหมดอายุอย่างถูกต้อง คุณอาจต้องการเก็บไว้ในฐานข้อมูลบางประเภท ไม่ว่าจะเป็น Redis, ActiveRecord หรืออย่างอื่น

แต่การจัดเก็บเซสชันฐานข้อมูลก็มีข้อเสียเช่นกัน:

  • ด้วยที่เก็บฐานข้อมูลบางแห่ง เซสชันของคุณจะไม่ถูกล้างโดยอัตโนมัติ

    ดังนั้น คุณจะต้องผ่านและล้างเซสชันที่หมดอายุด้วยตัวเอง

  • คุณต้องรู้ว่าฐานข้อมูลของคุณจะมีการทำงานอย่างไรเมื่อมีข้อมูลเซสชันเต็ม

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

  • คุณต้องระมัดระวังมากขึ้นเกี่ยวกับการสร้างข้อมูลเซสชัน มิฉะนั้นคุณจะเติมฐานข้อมูลของคุณด้วยเซสชันที่ไม่มีประโยชน์

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

ปัญหาเหล่านี้ส่วนใหญ่ค่อนข้างหายาก แต่คุณก็ควรระวังให้ดี

แล้วคุณควรจัดเก็บเซสชันอย่างไร

หากคุณค่อนข้างแน่ใจว่าคุณจะไม่พบกับข้อจำกัดใดๆ ของร้านคุกกี้ ให้ใช้มัน ไม่ต้องตั้งค่าอะไรมาก และไม่ยุ่งยากในการบำรุงรักษา

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

แต่แล้วคุณล่ะ? วิธีจัดเก็บ ของคุณ เซสชั่น? แสดงความคิดเห็นและแจ้งให้เราทราบ!

และหากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการทำงานภายในของ Ruby and Rails ให้ดูที่บทความนี้:อัญมณีทำงานอย่างไร หรือหากคุณสนใจเกี่ยวกับวิธีการทำงานของเว็บมากกว่า ให้ลองดูเว็บเซิร์ฟเวอร์เทียบกับเซิร์ฟเวอร์แอป