REST จำกัด เฉพาะการควบคุมภาวะพร้อมกันในแง่ดีหรือไม่?


9

บริบท

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

ดังนั้นการควบคุมภาวะพร้อมกันในแง่ร้ายไม่เหมาะสมเพราะจะต้องมีการจัดเก็บเซิร์ฟเวอร์ที่ลูกค้าจะได้รับการล็อคทรัพยากร การควบคุมภาวะพร้อมกันในแง่ดีนั้นจะถูกนำมาใช้ด้วยความช่วยเหลือของEtagส่วนหัว (btw ตามที่ฉันถาม/programming/30080634/concurrency-in-a-rest-api )

ปัญหา

ปัญหาหลักที่เกิดขึ้นกับกลไกการควบคุมภาวะพร้อมกันในแง่ดีคือคุณอนุญาตให้ลูกค้าทุกคนทำการดำเนินการใด ๆ ได้ตลอดเวลา

และฉันต้องการหลีกเลี่ยงสิ่งนั้นโดยไม่ทำลายหลักการไร้สัญชาติของ REST ฉันหมายความว่าลูกค้าทั้งหมดไม่สามารถดำเนินการใด ๆ ได้ตลอดเวลา

คำถาม

ในใจของฉันมันเป็นไปได้ด้วยกลไกการควบคุมภาวะพร้อมกันแบบกึ่งมองโลกในแง่ดีเช่นนั้น:

  • ลูกค้าสามารถขอโทเค็น
  • สามารถสร้างโทเค็นเดียวเท่านั้นและมีระยะเวลาที่ จำกัด
  • หากต้องการดำเนินการกับทรัพยากร (เช่นPOSTหรือPUT ) ไคลเอ็นต์จะต้องให้โทเค็นนี้เป็นส่วนหนึ่งของเนื้อความ (หรือส่วนหัว?) ของคำขอ ลูกค้าที่ไม่มีโทเค็นไม่สามารถทำการดำเนินการเหล่านี้ได้

มันคล้ายกันมากกับการควบคุมภาวะพร้อมกันในแง่ดียกเว้นว่ามีลูกค้าเพียงรายเดียวเท่านั้นที่สามารถทำการดำเนินการบางอย่าง (ลูกค้าที่ได้รับโทเค็น) ... ตรงข้ามกับ "ลูกค้าทุกคนสามารถดำเนินการทั้งหมดได้"

กลไกนี้เข้ากันได้กับสไตล์สถาปัตยกรรม REST หรือไม่? มันทำลายข้อ จำกัด ใด ๆ หรือไม่? ฉันคิดว่าจะถาม SO แต่ดูเหมือนว่าจะเป็นคำถามระดับสูงที่เกี่ยวข้องกับการออกแบบซอฟต์แวร์


1
มันค่อนข้างง่ายจริง ๆ : คุณต้องสร้างแบบจำลองTransactionอย่างชัดเจนว่าเป็นทรัพยากร
Jörg W Mittag

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

1
อะไรคือความแตกต่าง? ในอีกด้านหนึ่งคุณใช้ Etag เพื่อตรวจสอบผู้ที่ได้รับอนุญาตให้อัปเดตเวอร์ชัน "ปัจจุบัน"; หากเกิดการขัดกันคุณต้องอัปเดตเวอร์ชันของคุณและทำการอัปเดตหลังจากนั้น ในอีกด้านหนึ่งคุณมีกลไก "ล็อค" ของคุณ: อนุญาตหนึ่งอันและคนอื่น ๆ ต้องรอ ฟังดูสวยเหมือนกัน ข้อเสียของวิธีการที่สอง: 2 คำขอ - 1 สำหรับล็อคและ 1 สำหรับการอัปเดต ในกรณีที่ดีที่สุดคุณมีการอัพเดตเพียงครั้งเดียวผ่าน Etag-approach
Thomas Junk

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

คำตอบ:


3

คุณไม่ควรล็อคทรัพยากรใด ๆ ในขณะที่รอการโต้ตอบจากผู้ใช้

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

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

คนส่วนใหญ่สามารถจัดการกับข้อความ "ขออภัยผู้ใช้รายอื่นเพิ่งสั่งส่วนนี้"


คุณอธิบายมันอย่างดี แม้ว่าฉันจะไม่เชื่อมั่นอย่างเต็มที่ในประโยคแรกของคุณ: ในบางจุดคุณจะรับประกันได้ว่าไม่มีใครอื่นนอกจากคุณสามารถสั่งซื้อได้ แต่ประโยคสุดท้ายของคุณคือบทสรุปที่ดีใน 99% ของเวลาทั้งหมด
AilurusFulgens

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

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

1
@AilurusFulgens - คุณเพิ่มแอตทริบิวต์ LockedBy (และอาจเป็นเวลาประทับ LockedOn) ไปยังฐานข้อมูลของคุณ ในรหัสแอปพลิเคชันของคุณคุณตั้งชื่อผู้ใช้และเวลาเมื่อใดก็ตามที่ไคลเอนต์เริ่มการโต้ตอบการปรับปรุง คุณยกเลิกการตั้งค่าเมื่อไคลเอนต์เสร็จสิ้น - จากนั้นคุณต้องกำหนดกฎเกณฑ์ทางธุรกิจบางอย่างเพื่อแก้ไขข้อขัดแย้งและหมดเวลาเป็นต้น
James Anderson

2

การใช้โทเค็นเป็นเรื่องธรรมดาใน API โทเค็นเหล่านี้มักจะส่งเป็นส่วนหัวและมีวงจรชีวิตที่ชัดเจน คิดเช่น OAuth

REST APIs ไม่ว่าภาษาหรือกรอบการเขียนโปรแกรมของคุณจะเป็นอย่างไร

ฉันสามารถนึกถึงหลาย ๆ สถานการณ์ที่คุณต้องการ จำกัด การทำงานพร้อมกันสองสถานการณ์คือ:

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

  2. ผู้ใช้ขั้นสูงหรือผู้ดูแลระบบที่ดำเนินการพิเศษกับ API


จะทำอย่างไรในกรณีเหล่านี้?

  1. ใช้ธุรกรรมในฐานข้อมูลซิงเกิลล็อคและกลไกที่คล้ายกันเพื่อซิงโครไนซ์การเข้าถึงทรัพยากร

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

ฉันหวังว่านี่จะช่วยได้.


ใช่ฉันคาดหวังคำตอบเกี่ยวกับความคุ้นเคยของโทเค็นและกลไก OAuth แม้ว่าล่าสุดจะทุ่มเทให้กับการตรวจสอบ ฉันไม่เข้าใจประเด็นของคุณ 1. ส่วนที่ยุ่งยากในการจัดการกับการทำงานพร้อมกันใน REST API คือการรักษาข้อ จำกัด ของการไร้สัญชาติ ... หมายความว่าเซิร์ฟเวอร์ไม่ได้เก็บข้อมูลเกี่ยวกับลูกค้า สถานการณ์ของคุณ 2 เป็นสิ่งที่ฉันกำลังทำอยู่ในปัจจุบัน! :)
AilurusFulgens

ฉันตอบคำถามของคุณหรือไม่
Pablo Granados

ไม่ล่ะขอบคุณ. ฉันยกระดับคำตอบของคุณเพราะมันให้ภาพรวมที่ดีของปัญหา แต่น่าเสียดายที่ imo มันไม่ได้แก้ปัญหาจริงๆ
AilurusFulgens

0

เหลือเพียงอย่างเดียวดั้งเดิมเกินไปจริงๆ คุณสามารถเริ่มต้นด้วย REST แต่ในที่สุดแอปพลิเคชันที่สมบูรณ์ของคุณจะต้องใช้แบบสอบถามด้วยการเข้าร่วมและอัปเดตกับธุรกรรม นักพัฒนาซอฟต์แวร์ทุกคนที่พยายามเพิ่มสิ่งเหล่านี้ด้วยตนเองจะเกิดข้อผิดพลาดได้ง่ายและไม่สอดคล้องกัน โชคดีที่มีมาตรฐานใหม่ที่เรียกว่า OData ที่ทำเช่นนั้น มันอยู่ด้านบนของส่วนที่เหลือและให้ (1) ภาษาแบบสอบถามที่ช่วยให้การเข้าร่วมง่ายโดยใช้คุณสมบัติการนำทาง (โดยไม่ต้องเปิดเผยคีย์ต่างประเทศ) และ (2) การประมวลผลชุดที่มีชุดการเปลี่ยนแปลงอะตอม

ดูที่นี่สำหรับ (1) https://stackoverflow.com/a/3921423/471129และ

ดูที่นี่และ (2) https://stackoverflow.com/a/21939972/471129

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