REST 거래?


147

REST에서 다음 유스 케이스를 어떻게 구현하는지 궁금합니다. 개념적 모델을 손상시키지 않고 할 수 있습니까?

단일 트랜잭션 범위 내에서 여러 리소스를 읽거나 업데이트하십시오. 예를 들어 Bob의 은행 계좌에서 John의 계좌로 $ 100를 이체하십시오.

내가 알 수있는 한, 이것을 구현하는 유일한 방법은 부정 행위입니다. John 또는 Bob과 연관된 자원에 POST하고 단일 트랜잭션을 사용하여 전체 조작을 수행 할 수 있습니다. 내가 아는 한, 이것은 실제로 개별 리소스에서 작동하는 대신 POST를 통해 RPC 호출을 터널링하기 때문에 REST 아키텍처를 손상시킵니다.

답변:


91

RESTful 쇼핑 바구니 시나리오를 고려하십시오. 쇼핑 바구니는 개념적으로 트랜잭션 래퍼입니다. 장바구니에 여러 항목을 추가 한 다음 주문을 처리하기 위해 해당 바구니를 제출하는 것과 같은 방식으로 Bob의 계정 항목을 트랜잭션 래퍼에 추가 한 다음 Bill의 계정 항목을 래퍼에 추가 할 수 있습니다. 모든 조각이 제자리에 있으면 모든 구성 요소 조각으로 트랜잭션 래퍼를 POST / PUT 할 수 있습니다.


18
TransferMoneyTransaction이 실용적인 은행 자원이 아닌 이유는 무엇입니까?
Darrel Miller

8
엔드 포인트가 명사를 참조하도록하려면 표준 GET, PUT, POST, DELETE 동사가 해당 명사에 대해 수행하는 것이 일반적으로 직관적입니다. RPC는 끝점 자체를 동사로 사용할 수 있으므로 HTTP 동사와 충돌 할 수 있으며 의도가 혼동됩니다.
Darrel Miller

10
예를 들어 엔드 포인트 UpdateXYZ에서 HTTP DELETE를 수행하면 어떻게됩니까? XYZ를 삭제합니까? 업데이트를 삭제합니까 아니면 업데이트 만 수행하고 HTTP 동사 삭제를 무시합니까? 동사를 끝점에서 제외하면 혼동을 제거 할 수 있습니다.
Darrel Miller

5
여러 서비스 간의 트랜잭션은 어떻습니까? 서비스가 암시 적 트랜잭션 컨테이너를 공개하지 않는 일련의 '관련되지 않은'변경을 수행하려는 경우는 어떻습니까? 또한 실제 데이터와 완전히 관련이없는 범용 트랜잭션으로 이동할 때 특정 트랜잭션 유형을 갖는 이유는 무엇입니까? 변화. 트랜잭션은 편안하게 일치하지 않을 수 있지만 요청 헤더에 트랜잭션 참조가 포함된다는 사실을 제외하고 나머지 호출과는 관련이없는 트랜잭션이 맨 위에 계층화되어야합니다.
meandmycode

4
@meandmycode 데이터베이스 트랜잭션은 REST 인터페이스 뒤에 계층화되어야합니다. 또는 비즈니스 트랜잭션 (데이터베이스 트랜잭션이 아닌)을 자체 자원으로 노출 한 다음 실패시 보상 조치를 수행해야합니다.
Darrel Miller

60

이 질문에 의해 답변되지 않은 몇 가지 중요한 사례가 있습니다. 검색어에 대해 Google에서 높은 순위를 가지고 있기 때문에 너무 나쁘다고 생각합니다. :-)

특히, 적절하게 좋은 방법은 다음과 같습니다. POST가 두 번 (중간에 일부 캐시가 걸려 있기 때문에) 두 번 전송하면 안됩니다.

이를 위해 트랜잭션을 객체로 만듭니다. 여기에는 이미 알고있는 모든 데이터가 포함될 수 있으며 트랜잭션을 보류 상태로 만듭니다.

POST /transfer/txn
{"source":"john's account", "destination":"bob's account", "amount":10}

{"id":"/transfer/txn/12345", "state":"pending", "source":...}

이 트랜잭션이 있으면 다음과 같이 커밋 할 수 있습니다.

PUT /transfer/txn/12345
{"id":"/transfer/txn/12345", "state":"committed", ...}

{"id":"/transfer/txn/12345", "state":"committed", ...}

이 시점에서 다중 풋은 중요하지 않습니다. txn의 GET조차도 현재 상태를 반환합니다. 특히, 두 번째 PUT은 첫 번째 PUT이 이미 적절한 상태에 있음을 감지하여 반환합니다. 또는 이미 "committed"상태에있는 후 "rolledback"상태로 전환하려고하면 오류 및 실제 커밋 된 트랜잭션 백.

단일 데이터베이스 또는 통합 된 트랜잭션 모니터가있는 데이터베이스와 통신하는 한이 메커니즘은 실제로 제대로 작동합니다. 트랜잭션에 대한 시간 제한을 추가로 도입 할 수도 있습니다. 원하는 경우 Expires 헤더를 사용하여 표현할 수도 있습니다.


흥미로운 토론! 초기 게시물을 한 단계로 수행해야한다고 덧붙이고 싶습니다. 나중에 추가 할 수 없습니다 (그런 다음 우리는 쇼핑 카트 영역에 있고 쇼핑 카트에는 최종 사용자에게 해를 끼치 지 않도록하기 위해 많은 수표와 잔액이 있습니다 (법률, 은행 송금도 포함되지 않음) ...
Erk

33

REST 용어에서 자원은 CRUD (create / read / update / delete) 동사로 수행 할 수있는 명사입니다. "송금"동사가 없기 때문에 CRUD로 처리 할 수있는 "트랜잭션"리소스를 정의해야합니다. 다음은 HTTP + POX의 예입니다. 첫 번째 단계는 것입니다 CREATE (HTTP POST 방법) 새로운 거래를 :

POST /transaction

이것은 "1234"와 URL "/ transaction / 1234"에 따라 트랜잭션 ID를 반환합니다. 이 POST를 여러 번 실행하면 여러 ID로 동일한 트랜잭션이 생성되지 않고 "대기 중"상태가 발생하지 않습니다. 또한 POST가 항상 dem 등원 (REST 요구 사항) 일 수는 없으므로 일반적으로 POST의 데이터를 최소화하는 것이 좋습니다.

트랜잭션 ID 생성을 클라이언트에 맡길 수 있습니다. 이 경우, 트랜잭션 "1234"를 작성하기 위해 POST / transaction / 1234를 POST하고 서버가 이미 존재하면 오류를 리턴합니다. 오류 응답에서 서버는 현재 사용되지 않은 ID를 적절한 URL로 반환 할 수 있습니다. GET은 절대로 서버 상태를 변경해서는 안되며 새 ID를 작성 / 예약하면 서버 상태가 변경되므로 GET 메소드를 사용하여 서버에 새 ID를 쿼리하는 것은 좋지 않습니다.

다음 으로 모든 데이터로 트랜잭션을 UPDATE (PUT HTTP 메소드)하여 암시 적으로 커밋합니다.

PUT /transaction/1234
<transaction>
  <from>/account/john</from>
  <to>/account/bob</to>
  <amount>100</amount>
</transaction>

ID가 "1234"인 트랜잭션이 이전에 PUT 인 경우 서버는 오류 응답을 제공하고 그렇지 않으면 확인 응답 및 완료된 트랜잭션을 볼 수있는 URL을 제공합니다.

주의 : / account / john에서 "john"은 John의 고유 계정 번호 여야합니다.


4
REST와 CRUD를 동일시하는 것은 심각한 실수입니다. POST는 CREATE를 의미 할 필요는 없습니다.

12
심각한 실수? PUT과 POST 사이에 차이점이 있지만 CRUD에 대한 느슨한 매핑이 있습니다. "진실하게"?
테드 존슨

3
예, 진심 으로요 CRUD는 데이터 스토리지를 구성하는 방법입니다. REST는 애플리케이션 데이터 흐름을 구성하는 방법입니다. REST에서 CRUD를 수행 할 수 있지만 CRUD에서 REST를 수행 할 수 없습니다. 그것들은 동등하지 않습니다.
Jon Watte

20

훌륭한 질문은 REST는 주로 데이터베이스와 유사한 예제로 설명되며 무언가가 저장, 업데이트, 검색, 삭제됩니다. 서버가 어떤 식 으로든 데이터를 처리해야하는이 예제와 같은 몇 가지 예가 있습니다. Roy Fielding은 그의 논문에 어떤 것도 포함하지 않았다고 생각합니다.

그러나 그는 다음 상태로 링크가 이동하는 상태 머신으로서의 "표현 상태 이전"에 대해 이야기합니다. 이러한 방식으로 문서 (표현)는 서버가 수행하지 않고 클라이언트 상태를 추적합니다. 이런 식으로 클라이언트 상태는 없으며 현재 연결되어있는 상태 만 나타냅니다.

나는 이것에 대해 생각하고 있었고, 서버가 당신을 위해 무언가를 처리하게하고, 업로드 할 때 서버가 자동으로 관련 리소스를 생성하고 링크를 제공한다는 것이 합리적입니다. 자동으로 만들 필요는 없습니다. 링크를 알려줄 수 있으며, 링크를 만들 때만 따라야하는 경우에만 게으른 생성입니다. 또한 새로운 관련 리소스 를 만드는 링크도 제공합니다 . 관련 리소스는 동일한 URI를 갖지만 더 길어집니다 (접미사 추가). 예를 들면 다음과 같습니다.

  1. 모든 정보 가 포함 된 거래 개념을 업로드 ( POST )합니다 . 이것은 RPC 호출과 비슷하지만 실제로 "제안 된 트랜잭션 리소스"를 생성하고 있습니다. 예 : URI : /transaction 결함으로 인해 각각 다른 URI를 가진 여러 리소스가 생성됩니다.
  2. 서버의 응답은 생성 된 리소스의 URI를 나타냅니다. 여기에는 새로운 "커밋 된 트랜잭션 리소스" 의 관련 리소스를 만들기위한 링크 ( URI )가 포함됩니다 . 다른 관련 리소스는 제안 된 거래를 삭제하는 링크입니다. 상태 머신의 상태는 클라이언트가 따를 수 있습니다. 논리적으로 이들은 클라이언트가 제공 한 정보를 넘어 서버에서 생성 된 리소스의 일부입니다. 예를 들어 URI를 : /transaction/1234/proposed, /transaction/1234/committed
  3. 당신 POST 링크의 정보는 다음의 제품에 은 "커밋 된 트랜잭션 자원"을 만들 서버의 상태 (두 계정의 잔액) **을 변경, 해당 자원을 만듭니다. 기본적으로이 리소스는 한 번만 만들 수 있으며 업데이트 할 수 없습니다. 따라서 많은 트랜잭션을 커밋하는 결함이 발생할 수 없습니다.
  4. 이 두 가지 리소스를 가져와 상태를 확인할 수 있습니다. POST가 다른 자원을 변경할 수 있다고 가정하면, 제안은 이제 "committed"(또는 아마도 사용 가능하지 않은) 플래그로 표시됩니다.

이것은 웹 페이지의 작동 방식과 유사하며 최종 웹 페이지에 "이 작업을 수행 하시겠습니까?"라는 메시지가 표시됩니다. 최종 웹 페이지 자체는 거래 상태를 나타내며 다음 상태로 이동하는 링크가 포함되어 있습니다. 금융 거래뿐만 아니라; 또한 (예) 위키 백과에서 미리보기를하고 커밋하십시오. REST의 차이점은 상태 시퀀스의 각 단계에는 명시 적 이름 (URI)이 있다는 것입니다.

실제 거래 / 판매에서는 거래 단계 (제안서, 구매 주문서, 영수증 등)마다 다른 실제 문서가 종종 있습니다. 정착 등 주택 구입에 훨씬 더

OTOH 이것은 의미론을 가지고 노는 것 같습니다. "동사 (RPC 호출) 대신 명사 (URI)를 사용하기 때문에"동사를 명사로 변환하는 명목 화가 불편합니다. 즉, 동사 "이 트랜잭션을 커밋"대신 명사 "커밋 된 트랜잭션 리소스"입니다. 명 목화의 한 가지 장점은 다른 방법으로 (예 : 세션 상태 유지와 같이, "이"트랜잭션이 무엇인지 알 수 있음) 이름을 지정하지 않고 이름으로 리소스를 참조 할 수 있다는 것입니다.

그러나 중요한 질문은이 접근법의 장점은 무엇입니까? 즉,이 REST 스타일은 RPC 스타일보다 어떤면에서 더 좋습니까? 웹 페이지에 유용한 기술이 저장 / 검색 / 업데이트 / 삭제를 넘어 정보 처리에도 도움이됩니까? REST의 주요 이점은 확장 성이라고 생각합니다. 그것의 한 측면은 클라이언트 상태를 명시 적으로 유지할 필요가 없습니다 (그러나 리소스의 URI에 암시 적으로 만들고 다음 상태는 그 표현의 링크로 암시합니다). 그런 의미에서 도움이됩니다. 아마도 이것이 레이어링 / 파이프 라이닝에도 도움이됩니까? OTOH는 한 명의 사용자 만 특정 거래를 볼 수 있으므로 캐싱하는 데 이점이 없으므로 다른 사용자가 읽을 수 있으므로 http의 큰 승리입니다.


"클라이언트의 상태를 유지할 필요가없는"이 확장성에 어떻게 도움이되는지 설명해 주시겠습니까? 어떤 종류의 확장 성? 어떤 의미에서 확장 성?
jhegedus

11

여기서 논의 내용을 요약 해보면 REST가 많은 API에 적합하지 않다는 것이 분명합니다. 특히 클라이언트와 서버의 상호 작용이 본질적으로 비 완전한 트랜잭션과 마찬가지로 상태 저장 상태 인 경우에는 더욱 그렇습니다. 문제에 맞지 않는 몇 가지 원칙을 따르기 위해 클라이언트와 서버 모두에게 제안 된 모든 후프를 뛰어 넘는 이유는 무엇입니까? 더 나은 원칙은 클라이언트에게 응용 프로그램을 작성하는 가장 쉽고 가장 자연스럽고 생산적인 방법을 제공하는 것입니다.

요약하면, 실제로 애플리케이션에서 많은 트랜잭션 (인스턴스가 아닌 유형)을 수행하는 경우 RESTful API를 작성하지 않아야합니다.


9
그렇습니다. 그러나 분산 마이크로 서비스 아키텍처의 경우 대안은 무엇입니까?
Vitamon

11

나는 10 년 동안이 주제에서 멀어졌다. 돌아와서, 나는 당신이 구글 휴식 + 신뢰할 때 과학으로 위장하는 종교를 믿을 수 없습니다. 혼란은 신화입니다.

이 광범위한 질문을 세 가지로 나눌 것입니다.

  • 다운 스트림 서비스. 귀하가 개발하는 모든 웹 서비스에는 귀하가 사용하는 다운 스트림 서비스가 있으며 해당 트랜잭션 구문을 선택해야합니다. 이 모든 것을 서비스 사용자로부터 숨기고 작업의 모든 부분이 그룹으로 성공 또는 실패했는지 확인한 다음이 결과를 사용자에게 반환해야합니다.
  • 당신의 서비스. 고객은 웹 서비스 호출에 대한 명확한 결과를 원하며 실질적인 자원에 대해 POST, PUT 또는 DELETE 요청을 직접 수행하는 일반적인 REST 패턴은 이러한 확실성을 제공하는 가난하고 쉽게 개선되는 방법으로 저를 공격합니다. 안정성에 관심이있는 경우 작업 요청을 식별해야합니다. 이 ID는 클라이언트에서 생성 된 guid이거나 서버의 관계형 DB에서 시드 값일 수 있습니다. 서버 생성 ID의 경우 '사전 비행'요청-응답을 사용하여 조치의 ID를 교환하십시오. 이 요청이 실패하거나 절반 만 성공해도 아무런 문제가 없으면 클라이언트는 요청을 반복합니다. 사용하지 않은 ID는 해를 끼치 지 않습니다.

    이것은 모든 후속 요청이 완전히 dem 등원이되도록하기 때문에 중요합니다. n 번 반복 될 경우 동일한 결과를 리턴하고 더 이상 아무것도 발생하지 않는다는 의미입니다. 서버는 조치 ID에 대한 모든 응답을 저장하고 동일한 요청이 표시되면 동일한 응답을 재생합니다. 이 Google 문서 에는 패턴의 완전한 처리가 있습니다. 이 문서는 REST 원칙을 널리 따르는 구현을 제안합니다 (!). 전문가들은 반드시 그것이 다른 사람들을 어떻게 위반하는지 알려줄 것입니다. 이 패턴은 다운 스트림 트랜잭션과 관계없이 웹 서비스에 대한 안전하지 않은 호출에 유용하게 사용할 수 있습니다.
  • 업스트림 서비스로 제어되는 "트랜잭션"에 서비스 통합 웹 서비스의 맥락에서, 전체 ACID 트랜잭션은 노력 일반적으로 가치가없는 것으로 간주되지만 제공하여 서비스의 크게 도움 소비자는 취소 및 / 또는 확인 응답에서 확인 링크, 따라서 달성 할 수있는 보상에 의해 거래를 .

귀하의 요구 사항은 기본입니다. 사람들이 귀하의 솔루션이 정결하지 않다고 말하지 못하게하십시오. 문제를 얼마나 잘, 그리고 얼마나 간단하게 해결하는지에 따라 아키텍처를 판단하십시오.


9

"트랜잭션 ID"유형의 tx 관리를 롤링해야합니다. 따라서 4 번의 호출이됩니다.

http://service/transaction (some sort of tx request)
http://service/bankaccount/bob (give tx id)
http://service/bankaccount/john (give tx id)
http://service/transaction (request to commit)

DB (로드 밸런싱 된 경우) 또는 메모리 등에 작업 저장을 처리 한 다음 커밋, 롤백, 시간 초과를 처리해야합니다.

실제로 공원에서 편안한 하루가 아닙니다.


4
나는 이것이 특히 좋은 예라고 생각하지 않습니다. 트랜잭션 작성 ( "보류 중"상태의 트랜잭션 작성) 및 트랜잭션 커밋 (커밋되지 않은 경우 커밋하고 자원을 커밋 또는 롤백 상태로 이동)의 두 단계 만 필요합니다.
Jon Watte

2

이 경우이 상황에서 REST의 순수한 이론을 깨는 것이 전적으로 수용 가능하다고 생각합니다. 어쨌든 REST에 실제로 필요한 경우 비즈니스 사례에서 종속 객체를 만질 수 없다고 말하는 것은 없다고 생각합니다.

실제로 데이터베이스를 활용하여 사용자 지정 트랜잭션 관리자를 만들 때 얻을 수있는 추가 비용은 가치가 없다고 생각합니다.


2

우선 돈을 송금하는 것은 단일 자원 통화로는 할 수없는 일입니다. 당신이하고 싶은 행동은 돈을 보내는 것입니다. 따라서 송금 자 계정에 송금 리소스를 추가하십시오.

POST: accounts/alice, new Transfer {target:"BOB", abmount:100, currency:"CHF"}.

끝난. 당신은 이것이 원자 적이어야하는 거래라는 것을 알 필요가 없습니다. 당신은 일명 돈을 이체합니다. A에서 B로 송금


그러나 드문 경우이지만 일반적인 해결책은 다음과 같습니다.

정의 된 컨텍스트에서 많은 자원을 포함하는 매우 복잡한 작업을 수행하려는 경우 실제로 장벽 (비즈니스와 구현 지식에 대한 장벽)을 넘어서는 많은 제한이 있으므로 상태를 이전해야합니다. REST는 상태가 없어야하므로 클라이언트는 상태를 이전해야합니다.

상태를 전송하면 클라이언트에서 내부 정보를 숨겨야합니다. 고객은 구현에 필요한 내부 정보 만 알아야하며 비즈니스 측면에서 관련된 정보는 가지고 있지 않습니다. 이러한 정보에 비즈니스 가치가없는 경우 상태를 암호화해야하며 토큰, 패스 또는 이와 유사한 은유를 사용해야합니다.

이런 식으로 내부 상태를 전달할 수 있고 암호화를 사용하고 시스템에 서명하면 여전히 안전하고 건전 할 수 있습니다. 클라이언트가 상태 정보를 전달하는 이유에 대한 올바른 추상화를 찾는 것은 설계 및 아키텍처에 달려 있습니다.


실제 솔루션 :

REST는 HTTP를 말하고 HTTP는 쿠키 사용 개념과 함께 제공됩니다. 사람들이 REST API와 여러 리소스 또는 요청에 걸친 워크 플로 및 상호 작용에 대해 이야기 할 때 이러한 쿠키는 종종 잊혀집니다.

HTTP 쿠키에 대해 Wikipedia에 작성된 내용을 기억하십시오.

쿠키는 웹 사이트가 상태 저장 정보 (예 : 장바구니의 항목)를 기억하거나 사용자의 탐색 활동 (특정 단추 클릭, 로그인 또는 사용자가 방문한 페이지 기록 포함)을 기록 할 수있는 신뢰할 수있는 메커니즘으로 설계되었습니다. 몇 달 또는 몇 년 전으로 돌아 왔습니다.

따라서 기본적으로 상태를 전달해야하는 경우 쿠키를 사용하십시오. 정확히 같은 이유로 설계되었으며 HTTP이므로 설계에 따라 REST와 호환됩니다. :).


더 나은 솔루션 :

여러 요청과 관련된 워크 플로를 수행하는 클라이언트에 대해 이야기하는 경우 일반적으로 프로토콜에 대해 이야기합니다. 모든 형태의 프로토콜에는 B를 수행하기 전에 단계 A를 수행하는 것과 같이 각 잠재적 단계에 대한 사전 조건 세트가 제공됩니다.

이것은 자연 스럽지만 클라이언트에 프로토콜을 노출 시키면 모든 것이 더 복잡해집니다. 그것을 피하기 위해 현실 세계에서 복잡한 상호 작용과 일을해야 할 때 우리가하는 일을 생각하십시오 .... 우리는 에이전트를 사용합니다.

상담원 은유를 사용하여 필요한 모든 단계를 수행하고 실제 할당 / 명령을 목록에 저장할 수있는 리소스를 제공 할 수 있습니다 (에이전트 또는 '대행사'에서 POST를 사용할 수 있음).

복잡한 예 :

집을 사다 :

당신은 당신의 신용도 (경찰 기록을 제공하는 것과 같이)를 증명하고, 재정적 세부 사항을 보장해야하며, 변호사와 자금을 저장하는 신뢰할 수있는 제 3자를 사용하여 실제 집을 사야하고, 집이 당신의 소유이고 구매 기록을 세금 기록 등에 추가하십시오 (예를 들어, 일부 단계가 잘못되었거나 기타 일 수 있음).

이 단계는 완료하는 데 며칠이 걸릴 수 있으며 일부는 병렬로 수행 될 수 있습니다.

이렇게하려면 에이전트에게 다음과 같은 작업 구매 집을 제공하십시오.

POST: agency.com/ { task: "buy house", target:"link:toHouse", credibilities:"IamMe"}.

끝난. 대행사는이 작업의 상태를보고 추적하는 데 사용할 수있는 참조를 반송하며 나머지는 대행사의 에이전트가 자동으로 수행합니다.

예를 들어 버그 추적기를 생각해보십시오. 기본적으로 버그를보고하고 버그 ID를 사용하여 진행 상황을 확인할 수 있습니다. 서비스를 사용하여이 자원의 변경 사항을 청취 할 수도 있습니다. 미션 완료


1

REST에서 서버 측 트랜잭션을 사용해서는 안됩니다.

REST 제약 중 하나 :

무국적

클라이언트-서버 통신은 요청 사이에 서버에 클라이언트 컨텍스트가 저장되지 않아 제한됩니다. 클라이언트의 각 요청에는 요청을 처리하는 데 필요한 모든 정보가 포함되며 모든 세션 상태가 클라이언트에 유지됩니다.

유일한 RESTful 방법은 트랜잭션 리두 로그를 작성하여 클라이언트 상태로 만드는 것입니다. 요청으로 클라이언트는 리두 로그를 보내고 서버는 트랜잭션을 리두하고

  1. 트랜잭션을 롤백하지만 새로운 트랜잭션 리두 로그를 제공합니다 (한 단계 더 진행).
  2. 또는 마지막으로 거래를 완료하십시오.

그러나 서버 측 트랜잭션을 지원하는 서버 세션 기반 기술을 사용하는 것이 더 간단 할 수 있습니다.


wikipedia REST 항목에서 인용 한 것입니다. 이것이 실제 소스입니까, 위키 백과는 어딘가에서 가져 왔습니까? 클라이언트 컨텍스트와 서버 컨텍스트는 무엇입니까?
bbsimonbb

1

나는 연결 딸꾹질이 API에 의해 저장된 이중성을 암시하지 않도록 클라이언트에서 생성 된 고유 식별자를 사용하는 경우라고 생각합니다.

전송 객체와 함께 클라이언트 생성 GUID 필드를 사용하고 동일한 GUID를 다시 삽입하지 않는 것이 은행 송금 문제에 대한 더 간단한 해결책이라고 생각합니다.

여러 항공권 예약 또는 마이크로 아키텍처와 같은보다 복잡한 시나리오에 대해 알지 마십시오.

RESTful 서비스의 트랜잭션 원 자성다루는 경험과 관련하여 주제에 관한 논문을 발견했습니다 .


0

단순한 경우 (분산 된 리소스가없는 경우)에는 트랜잭션을 리소스로 간주하여 트랜잭션을 만드는 행위가 최종 목표를 달성 할 수 있습니다.

따라서 <url-base>/account/a와 사이를 전송 <url-base>/account/b하려면에 다음을 게시 할 수 <url-base>/transfer있습니다.

<전송>
    <from> <url-base> / account / a </ from>
    <to> <url-base> / account / b </ to>
    <amount> 50 </ amount>
</ transfer>

예를 들어, 새로운 전송 리소스를 생성하고 새로운 전송 URL을 반환합니다 <url-base>/transfer/256.

성공적인 게시 순간, 서버에서 '실제'거래가 수행되고 금액이 한 계정에서 제거되어 다른 계정에 추가됩니다.

그러나 이는 분산 거래를 다루지 않습니다 (예 : 'a'가 한 서비스 뒤의 한 은행에서 개최되고 'b'가 다른 서비스 뒤의 다른 은행에서 개최되는 경우)- "모두 문구 시도" 분산 트랜잭션을 요구하지 않는 방식으로 운영 ".


2
"분산 트랜잭션을 필요로하지 않는 방식으로 모든 작업을 구문"할 수 없으면 실제로 2 단계 커밋이 필요합니다. REST에서 2 단계 커밋을 구현하기 위해 찾을 수있는 가장 좋은 아이디어는 rest.blueoxen.net/cgi-bin/wiki.pl?TwoPhaseCommit 입니다 .URL 네임 스페이스를 엉망으로 만들지 않고 2 단계 커밋을 계층화 할 수 있습니다 깨끗한 REST 의미론.
Phasmal

3
이 제안의 다른 문제는 캐시 딸꾹질과 POST가 두 번 수행되면 두 번의 전송이 발생한다는 것입니다.
Jon Watte

이 경우에는 2 단계 프로세스가 필요합니다. 고유 한 URL로 "전송"리소스를 생성 한 다음 커밋의 일부로 전송 세부 정보를 추가하십시오 (다른 답변에서 언급 한 두 부분). 물론 이것은 "트랜잭션"리소스를 생성 한 다음 "트랜스퍼 링"작업을 추가하는 것으로 표현할 수 있습니다.
Phasmal

-3

URL / 리소스에 TAN을 포함시킬 수 있다고 생각합니다.

  1. ID를 얻기위한 PUT / transaction (예 : "1")
  2. [PUT, GET, POST 등] / 1 / account / bob
  3. [PUT, GET, POST 등] / 1 / account / bill
  4. ID 1의 삭제 / 트랜잭션

그냥 생각이야


이 접근법에는 두 가지 문제가 있습니다. 1) 트랜잭션 외부의 리소스에 액세스 할 수 없음을 의미합니다 (아마도 이것이 큰 문제는 아닙니다). 2) 서버에 더 이상 Stateless가 없다는 사실에 대해서는 아직까지 답변이 없었습니다.
길리

/ 1 / account / bob과 / account / bob은 두 가지 다른 리소스 일뿐입니다. :) 그리고 RE : stateless는 리소스가 항상 사용 가능하며 이전 요청에 의존하지 않음을 의미합니다. 거래를 요청했기 때문에 그렇습니다. 그러나 다시, 당신은 거래를 원했습니다.
까지

1
클라이언트가 URI를 어셈블해야하는 경우 API는 RESTful이 아닙니다.
aehlke

1
난 당신을 이해할 수 없어요! 트랜잭션을 자원으로 취급하는 경우 (위의 예에서와 같이) 트랜잭션을 고전적인 의미에서 중지하고 "적절한 REST 방식"으로 트랜잭션 트랜잭션 프로세스를 더욱 단순화하는 방식으로 활용하면됩니다. 예를 들어 분산 서버 측 환경에서 변위를 해결하기 위해 응답에 트랜잭션에 href를 포함시킬 수 있습니다. 여전히 상태가 없습니다 (단지 자원이 아니십니까?). 실제로 트랜잭션 메커니즘을 구현할 수 있습니다 원하는 (뒤에 DB가
없다면

1
만약 당신이 단순히 SQL / SOAP 생각을 멈추고 (브라우저처럼) HTTP 생각을 시작한다면 어떤 방법이든 다른 방법이됩니다
Matthias Hryniszak
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.