คุณแสดงถึงการซิงค์แบบสองทิศทางใน REST api ได้ดีที่สุดอย่างไร


23

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

ตัวอย่าง:

ฉันมี API ที่แสดงรายการสิ่งที่ต้องทำ

รับ / โพสต์ / วาง / ลบ / ลอส / ฯลฯ

API นั้นสามารถอ้างอิงบริการสิ่งที่ต้องทำแบบรีโมต

GET / POST / PUT / DELETE / todo_services / ฯลฯ

ฉันสามารถจัดการ todos จากบริการระยะไกลผ่าน API ของฉันในฐานะตัวแทนผ่าน

GET / POST / PUT / DELETE / todo_services / abc123 / เป็นต้น

ฉันต้องการความสามารถในการซิงโครไนซ์แบบสองทิศทางระหว่างชุดของโทพอสในพื้นที่กับชุดรีโมทของ TODOS

ในรูปแบบ rpc เราสามารถทำได้

POST / todo_services / abc123 / sync /

แต่ในแนวคิด "คำกริยาไม่ดี" มีวิธีที่ดีกว่าในการเป็นตัวแทนของการกระทำนี้หรือไม่?


4
ฉันคิดว่าการออกแบบ API ที่ดีนั้นขึ้นอยู่กับความเข้าใจที่ชัดเจนของความหมายของการซิงค์ "การซิงค์" ของแหล่งข้อมูลสองแห่งมักจะเป็นปัญหาที่ซับซ้อนมากซึ่งง่ายเกินความจริง แต่ก็ยากที่จะคิดผ่านความหมายทั้งหมด ทำให้การซิงก์ "แบบสองทิศทาง" และในทันใดความยากลำบากก็จะสูงขึ้นมาก เริ่มต้นด้วยการคิดคำถามที่ยากมากที่เกิดขึ้น
Adam Crossland

ขวา - สมมติว่าอัลกอริทึมการซิงค์ได้รับการออกแบบและทำงานใน API "ระดับรหัส" - ฉันจะเปิดเผยสิ่งนี้ผ่าน REST ได้อย่างไร การซิงค์ทางเดียวดูเหมือนจะง่ายกว่ามากในการแสดง: ฉันGET /todo/1/กับPOSTมัน/todo_services/abc123/ แต่สำหรับทั้งสองวิธี - ฉันไม่ได้ใช้ชุดข้อมูลและวางลงในทรัพยากร ฉันเดาว่าฉันสามารถย้อนกลับไปที่การมี "todo syncronizations" เป็นทรัพยากรของตัวเอง POST /todo_synchronizations/ {"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now"}
Edward M Smith

เรายังคงมีปัญหารถเข็นก่อนม้า ประเด็นของฉันคือคุณไม่สามารถสันนิษฐานได้ว่าการซิงค์นั้นใช้งานได้และออกแบบ API การออกแบบ API จะถูกขับเคลื่อนด้วยความกังวลมากมายเกี่ยวกับวิธีการทำงานของอัลกอริธึมการซิงค์
Adam Crossland

นั่นอาจทำให้เกิดผลลัพธ์ที่มีประโยชน์: GET /todo_synchronizations/1=>{"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now","ran_at":"datetime","result":"success"}
Edward M Smith

2
ฉันเห็นด้วยกับ @Adam คุณรู้หรือไม่ว่าคุณจะใช้การซิงค์ของคุณอย่างไร คุณจัดการกับการเปลี่ยนแปลงอย่างไร คุณเพียงแค่มีสองชุดรายการที่คุณต้องการกระทบยอดหรือคุณมีบันทึกของการกระทำที่ทำให้ทั้งสองชุดแตกต่างกันตั้งแต่การซิงค์ครั้งสุดท้าย? เหตุผลที่ฉันถามคือมันอาจเป็นเรื่องยากที่จะตรวจจับการเพิ่มและลบ (โดยไม่คำนึงถึง REST) หากคุณมีฝั่งเซิร์ฟเวอร์วัตถุและไม่มีฝั่งไคลเอ็นต์คุณต้องถามตัวเองว่า "ไคลเอ็นต์ลบหรือสร้างเซิร์ฟเวอร์หรือไม่" เฉพาะเมื่อคุณรู้อย่างชัดเจนว่า "ทรัพยากร" ทำงานอย่างไรคุณสามารถแสดงได้อย่างถูกต้องใน REST
Raymond Saltrelli

คำตอบ:


17

ทรัพยากรอยู่ที่ไหนและอะไร

REST เป็นข้อมูลเกี่ยวกับการจัดการทรัพยากรในลักษณะไร้รัฐและสามารถค้นพบได้ ไม่จำเป็นต้องดำเนินการผ่าน HTTP และไม่จำเป็นต้องพึ่งพา JSON หรือ XML แม้ว่าจะแนะนำเป็นอย่างยิ่งว่ารูปแบบข้อมูลไฮเปอร์มีเดียใช้ (ดูหลักการHATEOAS ) เนื่องจากลิงค์และรหัสเป็นที่ต้องการ

ดังนั้นคำถามจะกลายเป็น: เราคิดอย่างไรเกี่ยวกับการซิงโครไนซ์ในแง่ของทรัพยากร?

การซิงค์แบบสองทิศทางคืออะไร **

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

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

ขั้นตอนที่ 1 - ท้องถิ่นดึงบันทึกการทำธุรกรรม

ท้องถิ่น: GET /remotehost/items/transactions?earliest=2000-01-01T12:34:56.789Z

ระยะไกล: 200 OKพร้อมเนื้อหาที่มีบันทึกธุรกรรมที่มีฟิลด์คล้ายกับนี้

  • itemId - UUID เพื่อระบุคีย์หลักที่แชร์

  • updatedAt - การประทับเวลาเพื่อให้จุดประสานเมื่อข้อมูลได้รับการปรับปรุงล่าสุด (สมมติว่าไม่จำเป็นต้องมีประวัติการแก้ไข)

  • fingerprint- แฮช SHA1 ของเนื้อหาของข้อมูลเพื่อการเปรียบเทียบอย่างรวดเร็วหากupdateAtไม่กี่วินาที

  • itemURI - URI แบบเต็มของรายการเพื่ออนุญาตให้เรียกใช้ได้ในภายหลัง

ขั้นตอนที่ 2 - ท้องถิ่นเปรียบเทียบบันทึกธุรกรรมระยะไกลกับของตัวเอง

นี่เป็นแอปพลิเคชันของกฎทางธุรกิจของวิธีการซิงค์ โดยทั่วไปแล้วitemIdจะระบุทรัพยากรในท้องถิ่นแล้วเปรียบเทียบลายนิ้วมือ หากมีความแตกต่างแล้วเปรียบเทียบการupdatedAtทำ หากสิ่งเหล่านี้ใกล้เกินไปที่จะเรียกการตัดสินใจจะต้องทำการดึงตามโหนดอื่น (อาจจะสำคัญกว่า) หรือกดไปที่โหนดอื่น (โหนดนี้สำคัญกว่า) หากทรัพยากรระยะไกลไม่ได้อยู่ภายในเครื่องจะมีการส่งรายการพุช (ซึ่งมีข้อมูลจริงสำหรับการแทรก / อัพเดท) ทรัพยากรท้องถิ่นใด ๆ ที่ไม่ปรากฏในบันทึกธุรกรรมระยะไกลจะถือว่าไม่มีการเปลี่ยนแปลง

itemURIขอดึงที่ทำกับโหนดระยะไกลเพื่อให้ข้อมูลที่มีอยู่ในท้องถิ่นโดยใช้ พวกเขาจะไม่นำไปใช้ในท้องถิ่นจนกระทั่งในภายหลัง

ขั้นตอนที่ 3 - ผลักดันบันทึกการทำธุรกรรมการซิงค์ท้องถิ่นไปยังระยะไกล

Local: PUT /remotehost/items/transactionsกับเนื้อหาที่มีบันทึกธุรกรรมการซิงค์ในเครื่อง

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

ขั้นตอนที่ 4 - อัปเดตภายในเครื่อง

ข้อมูลที่ดึงในขั้นตอนที่ 2 จะถูกนำไปใช้ภายในเครื่องภายใต้ธุรกรรมแอปพลิเคชัน

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


6

ฉันจะพิจารณาการดำเนินการซิงโครไนซ์เป็นทรัพยากรที่สามารถเข้าถึงได้ (GET) หรือสร้างขึ้น (POST) เมื่อคำนึงถึงสิ่งนั้นแล้ว URL API อาจเป็น:

/todo_services/abc123/synchronization

(เรียกว่า "การซิงโครไนซ์" ไม่ใช่ "ซิงค์" เพื่อทำให้ชัดเจนว่าไม่ใช่คำกริยา)

จากนั้นทำ:

POST /todo_services/abc123/synchronization

เพื่อเริ่มต้นการประสาน เนื่องจากการดำเนินการซิงโครไนซ์เป็นทรัพยากรการโทรนี้อาจส่งคืน ID ที่สามารถใช้เพื่อตรวจสอบสถานะของการดำเนินการ:

GET /todo_services/abc123/synchronization?id=12345

3
คำตอบง่ายๆนี้คือคำตอบ เปลี่ยนคำกริยาของคุณให้เป็นคำนามและก้าวต่อไป ...
HDave

5

นี่เป็นปัญหาที่ยาก ฉันไม่เชื่อว่า REST เป็นระดับที่เหมาะสมในการใช้การซิงค์ การซิงค์ที่มีประสิทธิภาพจำเป็นต้องเป็นธุรกรรมแบบกระจาย REST ไม่ใช่เครื่องมือสำหรับงานนั้น

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

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

คุณอาจต้องการพิจารณาMicrosoft Sync Frameworkหากคุณต้องการสนับสนุนการเปลี่ยนแปลงที่เก็บข้อมูลอย่างอิสระ สิ่งนี้จะไม่ทำงานผ่าน REST แต่อยู่เบื้องหลัง


5
+1 สำหรับ "ปัญหาหนัก" การทำข้อมูลให้ตรงกันแบบสองทิศทางเป็นหนึ่งในสิ่งเหล่านั้นที่คุณไม่ทราบว่ามันยากเพียงใดจนกว่าคุณจะอยู่ลึกลงไปในโคลน
Dan Ray

2

Apache CouchDBเป็นฐานข้อมูลที่ใช้ REST, HTTP และ JSON นักพัฒนาทำการดำเนินการ CRUD ขั้นพื้นฐานผ่าน HTTP นอกจากนี้ยังมีกลไกการจำลองแบบซึ่งเป็นแบบ peer-to-peer โดยใช้วิธีการ HTTP เท่านั้น

เพื่อให้การจำลองแบบนี้ CouchDB จำเป็นต้องมีแบบแผนการเฉพาะ CouchDB สิ่งเหล่านี้ไม่ตรงข้ามกับ REST จะให้แต่ละเอกสาร (ซึ่งเป็นทรัพยากรที่มีส่วนที่เหลือภายในฐานข้อมูล) มีจำนวนการแก้ไข นี่เป็นส่วนหนึ่งของการแสดง JSON ของเอกสารนั้น แต่ยังอยู่ในส่วนหัวของ ETag HTTP แต่ละฐานข้อมูลยังมีหมายเลขลำดับที่อนุญาตให้ติดตามการเปลี่ยนแปลงฐานข้อมูลโดยรวม

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

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


ฉันรัก CouchDB และเป็นผู้สืบทอด CouchBase + SyncGateway +1
Leonid Usov

-1

คุณสามารถแก้ปัญหา "คำกริยาไม่ดี" ได้ด้วยการเปลี่ยนชื่ออย่างง่าย - ใช้ "อัปเดต" แทน "ซิงค์"

กระบวนการซิงค์กำลังส่งรายการอัปเดตท้องถิ่นที่ทำตั้งแต่การซิงค์ครั้งล่าสุดและรับรายการอัปเดตที่ทำบนเซิร์ฟเวอร์ในเวลาเดียวกัน

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