REST API에서 양방향 동기화를 가장 잘 표현하는 방법은 무엇입니까?


23

리소스가있는 웹 응용 프로그램이 있고 다른 유사한 리소스가있는 원격 응용 프로그램에 대한 참조가있는 시스템을 가정하면 '로컬'리소스를 '원격'리소스와 동기화하는 양방향 동기화 작업을 어떻게 표현합니까?

예:

할 일 목록을 나타내는 API가 있습니다.

GET / POST / PUT / DELETE / todos / 등

해당 API는 원격 TODO 서비스를 참조 할 수 있습니다.

GET / POST / PUT / DELETE / todo_services / 등

API를 통해 원격 서비스에서 할 일을 프록시로 프록시로 조작 할 수 있습니다

GET / POST / PUT / DELETE / todo_services / abc123 / 등

로컬 할 일 모음과 원격 TODOS 모음 사이에 양방향 동기화 기능을 원합니다.

rpc 종류의 방식으로 할 수 있습니다.

POST / todo_services / abc123 / sync /

그러나 "동사가 나쁘다"라는 생각에서이 행동을 표현하는 더 좋은 방법이 있습니까?


4
좋은 API 디자인은 동기화의 의미에 대한 구체적인 이해에 전적으로 달려 있다고 생각합니다 . 두 데이터 소스의 "동기화"는 일반적으로 지나치게 단순화하기는 쉽지만 모든 의미에서 생각하기가 매우 어려운 매우 복잡한 문제입니다. "양방향"동기화로 설정하면 갑자기 난이도가 훨씬 높아집니다. 나타나는 매우 어려운 질문들을 생각하면서 시작하십시오.
Adam Crossland

맞습니다-동기화 알고리즘이 "코드 수준"API에서 설계되고 기능한다고 가정합니다. REST를 통해이를 노출시키는 방법. 한 가지 방법은 동기화를 표현하기 위해 훨씬 더 쉬운 것 같다 : I GET /todo/1/POST그것을로 /todo_services/abc123/ 하지만, 2 방법 - 나는 두 자원의 잠재력 수정 실제로 결과를 가지고있어, 작업을 데이터 집합을 복용하고 자원에두고 있지 않다. 나는 "할 일 syncronizations"인 자원을 스스로 가지고 다시 떨어질 수도 있겠죠 POST /todo_synchronizations/ {"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now"}
에드워드 M 스미스

여전히 장바구니 문제가 있습니다. 내 요점은 동기화가 작동한다고 가정 할 수 없으며 API를 디자인한다는 것입니다. API의 디자인은 동기화 알고리즘의 작동 방식에 대한 수많은 우려에 의해 좌우됩니다.
Adam Crossland

즉, 잠재적으로 유용한 결과를 공개한다 GET /todo_synchronizations/1=>{"todos":["/todo/1/","/todo_services/abc123/1"],"schedule":"now","ran_at":"datetime","result":"success"}
에드워드 M 스미스

2
@Adam에 동의합니다. 동기화 구현 방법을 알고 있습니까? 변경 사항을 어떻게 처리합니까? 조정하려는 두 세트의 항목이 있거나 마지막 동기화 이후 두 세트가 분기 된 작업에 대한 로그가 있습니까? 내가 묻는 이유는 REST에 관계없이 추가 및 삭제를 감지하기가 까다로울 수 있기 때문입니다. 서버 측 오브젝트가 있고 클라이언트 측 오브젝트가없는 경우, "클라이언트가 오브젝트를 삭제 했습니까? 아니면 서버가 오브젝트를 작성 했습니까?" "리소스"의 작동 방식을 정확히 알고있는 경우에만 REST에서이를 정확하게 나타낼 수 있습니다.
Raymond Saltrelli

답변:


17

자원은 어디에서 무엇입니까?

REST는 상태를 유지하고 검색 가능한 방식으로 리소스를 처리하는 것입니다. 링크와 ID가 바람직하기 때문에 하이퍼 미디어 데이터 형식을 사용하는 것이 좋습니다 ( HATEOAS 원칙 참조 ).

따라서 문제는 자원 측면에서 동기화에 대해 어떻게 생각 하는가입니다.

양방향 동기화 란 무엇입니까? **

양방향 동기화는 프로세스가 끝날 때 모든 노드가 해당 자원을 관리하는 규칙에 따라 자원을 업데이트 할 수 있도록 노드 그래프에있는 자원을 업데이트하는 프로세스입니다. 일반적으로 이것은 모든 노드가 그래프 내에있는 것처럼 최신 버전의 리소스를 갖는 것으로 이해됩니다. 가장 간단한 경우 그래프는 로컬 및 원격의 두 노드로 구성됩니다. 로컬은 동기화를 시작합니다.

따라서 해결해야 할 주요 리소스는 트랜잭션 로그이므로 HTTP의 "items"컬렉션에 대해 동기화 프로세스는 다음과 같습니다.

1 단계-로컬에서 트랜잭션 로그 검색

노동 조합 지부: GET /remotehost/items/transactions?earliest=2000-01-01T12:34:56.789Z

원격 : 이와 유사한 필드를 포함하는 트랜잭션 로그를 포함하는 본문으로 200 OK .

  • itemId -공유 기본 키를 제공하는 UUID

  • updatedAt -데이터가 마지막으로 업데이트되었을 때 조정 된 포인트를 제공하는 타임 스탬프 (개정 내역이 필요하지 않다고 가정)

  • fingerprint- updateAt몇 초가 지나면 빠른 비교를 위해 데이터 내용의 SHA1 해시

  • itemURI -나중에 검색 할 수 있도록 항목에 대한 전체 URI

2 단계-로컬에서 원격 트랜잭션 로그와 자체 트랜잭션 로그 비교

동기화 방법에 대한 비즈니스 규칙을 적용한 것입니다. 일반적으로 itemId로컬 리소스를 식별 한 다음 지문을 비교합니다. 차이가 있으면 비교 updatedAt가 이루어집니다. 이것들이 호출하기에 너무 가까운 경우, 다른 노드 (아마도 더 중요 함)를 기반으로 당겨 지거나 다른 노드 (이 노드가 더 중요 함)로 푸시하도록 결정해야합니다. 원격 자원이 로컬로 존재하지 않으면 푸시 항목이 작성됩니다 (삽입 / 업데이트에 대한 실제 데이터가 포함됨). 원격 트랜잭션 로그에없는 로컬 리소스는 변경되지 않은 것으로 간주됩니다.

풀 요청은 원격 노드에 대해 수행되므로 데이터를 사용하여 로컬로 데이터가 존재합니다 itemURI. 나중에까지 로컬로 적용되지 않습니다.

3 단계-로컬 동기화 트랜잭션 로그를 원격으로 푸시

로컬 : PUT /remotehost/items/transactions 로컬 동기화 트랜잭션 로그를 포함하는 본문.

원격 노드 는 많은 오버 헤드가 발생할 가능성이있는 경우이를 동 기적으로 (작고 빠른 경우) 또는 비동기 적으로 ( 202 ACCEPTED 라고 생각 ) 처리 할 수 ​​있습니다. 동기 작업을 가정하면 성공 또는 실패에 따라 결과가 200 OK 또는 409 CONFLICT가 됩니다. 409 CONFLICT 의 경우 , 원격 노드에서 낙관적 잠금 실패가 있었기 때문에 프로세스를 다시 시작해야합니다 (다른 사람이 동기화 중에 데이터를 변경 함). 원격 업데이트는 자체 응용 프로그램 트랜잭션으로 처리됩니다.

4 단계-로컬 업데이트

2 단계에서 가져온 데이터는 응용 프로그램 트랜잭션에서 로컬로 적용됩니다.

위의 내용이 완벽하지는 않지만 (로컬 및 원격에서 문제가 발생할 수 있으며 로컬에서 원격 데이터를 가져 오는 것이 큰 PUT에 넣는 것보다 더 효율적인 경우가 있습니다) 양방향 동안 REST를 사용하는 방법을 보여줍니다 방향성 동기화 프로세스.


6

동기화 작업을 액세스 (GET) 또는 생성 (POST) 할 수있는 리소스로 생각합니다. 이를 염두에두고 API URL은 다음과 같습니다.

/todo_services/abc123/synchronization

(동사가 아님을 명확하게하기 위해 "동기화"가 아니라 "동기화"라고 부름)

그런 다음 수행하십시오.

POST /todo_services/abc123/synchronization

동기화를 시작합니다. 동기화 작업은 리소스이므로이 호출은 잠재적으로 작업 상태를 확인하는 데 사용할 수있는 ID를 반환 할 수 있습니다.

GET /todo_services/abc123/synchronization?id=12345

3
이 간단한 대답이 답입니다. 동사를 명사로
바꾸고 다음 단계로 넘어가십시오

5

이것은 어려운 문제입니다. REST가 동기화를 구현하기에 적합한 수준이라고 생각하지 않습니다. 강력한 동기화는 기본적으로 분산 트랜잭션이어야합니다. REST는 해당 작업을위한 도구가 아닙니다.

(가정 : "동기화"는 언제든지 어느 한 자원이 다른 자원과 독립적으로 변경 될 수 있음을 의미하며 업데이트를 잃지 않고 자원을 다시 정렬 할 수 있기를 원합니다.)

마스터의 데이터를 사용하여 슬레이브를 주기적으로 자신있게 복제 할 수 있도록 하나를 "마스터"및 다른 하나를 "슬레이브"로 만드는 것이 좋습니다.

독립적으로 변경되는 데이터 저장소를 절대적으로 지원해야하는 경우 Microsoft Sync Framework 를 고려할 수도 있습니다 . 이것은 REST를 통해 작동하지 않지만 무대 뒤에서 작동합니다.


5
"어려운 문제"에 +1 양방향 동기화는 진흙 속에 깊숙해질 때까지 얼마나 힘든지 깨닫지 못하는 것들 중 하나입니다.
Dan Ray

2

Apache CouchDB 는 REST, HTTP 및 JSON을 기반으로하는 데이터베이스입니다. 개발자는 HTTP를 통해 기본 CRUD 작업을 수행합니다. 또한 HTTP 메소드 만 사용하여 피어 투 피어 인 복제 메커니즘을 제공합니다.

이 복제를 제공하려면 CouchDB에 일부 CouchDB 관련 규칙이 있어야합니다. 이들 중 어느 것도 REST에 반대하지 않습니다. 각 문서 (데이터베이스 내의 REST 자원)에 개정 번호를 제공 합니다. 이것은 해당 문서의 JSON 표현의 일부이지만 ETag HTTP 헤더에도 있습니다. 각 데이터베이스 에는 데이터베이스 전체의 변경 사항추적 할 수있는 시퀀스 번호도 있습니다 .

들어 갈등 해결 , 그들은 단순히 충돌 해결 알고리즘을 제공하기 위해 데이터베이스를 사용하여 개발자로 떠나는 문서가 충돌이므로주의와 충돌 버전을 유지합니다.

CouchDB를 REST API로 사용하면 즉시 동기화를 제공하거나 자체 알고리즘을 만들기위한 시작점을 제공하기 위해 복제를 제공하는 방법을 살펴볼 수 있습니다.


저는 CouchDB를 좋아하며 그 다음 버전 인 CouchBase + SyncGateway입니다. +1
Leonid Usov

-1

간단한 이름 변경으로 "동사 불량"문제를 해결할 수 있습니다. "동기화"대신 "업데이트"를 사용하십시오.

동기화 프로세스는 실제로 마지막 동기화 이후에 수행 된 로컬 업데이트 목록을 전송하고 같은 시간에 서버에서 수행 된 업데이트 목록을 수신합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.