REST는 낙관적 동시성 제어로만 제한됩니까?


9

문맥

각 요청이 완전히 독립적 인 REST 아키텍처 스타일의 상태 비 저장으로 인해 서버는 클라이언트에 대한 정보를 저장하지 않습니다.

따라서 비관적 동시성 제어는 어떤 클라이언트가 리소스에 대한 잠금을 가져 오는 서버 저장소가 필요하기 때문에 적합하지 않습니다. Etag헤더 의 도움으로 낙관적 동시성 제어가 사용됩니다 . (btw, 거기에 /programming/30080634/concurrency-in-a-rest-api 요청 )

문제

낙관적 동시성 제어 메커니즘의 주요 문제점은 모든 클라이언트가 모든 작업을 항상 수행 할 수 있다는 것입니다.

그리고 REST의 statelessness 원칙을 어 기지 않고 그것을 피하고 싶습니다. 모든 클라이언트가 언제든지 작업을 수행 할 수 없음을 의미합니다.

질문

내 생각에는 다음과 같은 반 낙관적 동시성 제어 메커니즘을 사용하면 가능합니다.

  • 고객은 토큰을 요청할 수 있습니다
  • 하나의 토큰 만 생성 할 수 있으며 유효 기간이 제한되어 있습니다.
  • 리소스 (예 : POST 또는 PUT ) 에 대한 작업을 수행하려면 클라이언트가 요청의 본문 (또는 헤더?)의 일부로이 토큰을 제공해야합니다. 토큰이없는 클라이언트는 이러한 작업을 수행 할 수 없습니다.

"모든 클라이언트가 모든 작업을 수행 할 수 있습니다"와 반대되는 방식으로 한 클라이언트 만 일부 작업 (토큰을 보유한 작업)을 수행 할 수 있다는 점을 제외하고 낙관적 동시성 제어와 매우 유사합니다.

이 메커니즘은 REST 아키텍처 스타일과 호환됩니까? 제약 조건을 위반합니까? SO에 대해 생각하고 있었지만 소프트웨어 디자인과 관련하여 더 높은 수준의 질문 인 것 같습니다.


1
실제로는 간단합니다. Transaction명시 적으로 리소스로 모델링해야합니다 .
Jörg W Mittag 2016 년

무엇이 바뀌나요? 귀하의 의견을 이해하지 못합니다. 트랜잭션에 대한 동시성 제어를 수행하는 것이 아니라 클라이언트에게 "지금은 아무도 고유 한 토큰을 가지고 있기 때문에 아무도 리소스를 변경하지 않을 것이라고 확신합니다"라고 말하는 것입니다.
AilurusFulgens

1
차이점은 무엇입니까? 한쪽에서는 Etag를 사용하여 누가 "현재"버전을 업데이트 할 수 있는지 확인합니다. 충돌이 발생하면 버전을 업데이트 한 후 업데이트를 수행해야합니다. 다른쪽에는 "잠금"메커니즘이 있습니다. 하나는 허용되고 다른 하나는 기다려야합니다. 꽤 똑같습니다. 두 번째 접근 방식의 단점은 2 개의 요청-1은 잠금, 1은 업데이트입니다. 최적의 경우 Etag 접근 방식을 통해 업데이트가 하나만 있습니다.
토마스 정크

글쎄, 일반적으로 동시성 제어에 대해 말하면 ... "레이스를 잃어버린"두 번째는 항상 기다려야 할 것입니다 (다른 이유로, 나는 그것에 동의합니다). Etag? 와의 차이점 으로 Etag당신이 당신의 작업이 완료 될 것이라고 결코 확신합니다, 당신은 당신이 어떤 작업을 수행하지 않을 상황이있을 수 있습니다. 잠금 장치를 사용하면 최소한 작업을 수행해야합니다. 따라서 간단한 잠금을 갖는 것은 "높은 충돌"과 "드문 충돌"이 발생할 수있는 환경 사이의 중간에 있습니다.
AilurusFulgens 2016 년

답변:


3

사용자 상호 작용을 기다리는 동안 리소스를 잠그지 않아야합니다.

어느 시점에서 일부 사용자는 긴 주말 동안 이륙하여 중요한 레코드를 잠급니다.

아 그러나 당신은 당신이 영리한 타임 아웃 / 교착 상태 해결 계획을 가지고 있기 때문에 그렇게하지 못하게 할 것입니다; 그런 다음 어느 시점에서 이것은 끔찍하게 잘못 될 것이며 멋진 "위젯이 주문되었습니다"라는 메시지를받은 사용자는 자신의 위젯이 배달되지 않은 이유를 알기 위해 헬프 데스크에서 비명을지를 것입니다.

대부분의 사람들은 "다른 사용자가 방금이 부품을 주문했습니다"라는 메시지를 처리 ​​할 수 ​​있습니다.


잘 설명하셨습니다. 첫 문장으로 완전히 확신하지는 못하지만 어떤 시점에서는 다른 사람이 주문을 수행 할 수 없음을 보장합니다. 그러나 마지막 문장은 99 %의 경우에 좋은 요약입니다.
AilurusFulgens

1
특정 사용자에 대한 레코드를 잠 가야하는 경우 애플리케이션 레벨에서 수행하십시오. 단순한 "LockedBy"속성이거나보다 정교한 버전 관리 및 워크 플로우 메커니즘이 있습니다.
제임스 앤더슨

"응용 프로그램 수준에서"는 무엇을 의미합니까? 자원에 "LockedBy"속성을 추가하면 서버에 클라이언트에 대한 정보가 저장됩니다. 아니면 당신의 의견을 이해하지 못했습니다. 세부 사항을 제공 할 수 있다면 좋을 것입니다!
AilurusFulgens

1
@AilurusFulgens-데이터베이스에 LockedBy 속성 (및 아마도 LockedOn 타임 스탬프)을 추가합니다. 응용 프로그램 코드에서 클라이언트가 업데이트 상호 작용을 시작할 때마다 사용자 이름과 시간을 설정합니다. 클라이언트가 완료되면 설정을 해제합니다. 그런 다음 충돌 및 시간 초과 등을 해결하기 위해 몇 가지 비즈니스 규칙을 수행해야합니다.
James Anderson

2

토큰 사용은 API에서 매우 일반적이며, 이러한 토큰은 일반적으로 헤더로 전송되며 명확한 수명주기를 갖습니다. 예를 들어 OAuth를 생각해보십시오.

프로그래밍 언어 나 프레임 워크에 관계없이 REST API는 비슷합니다.

동시성을 제한하려는 몇 가지 시나리오를 생각할 수 있습니다. 그 중 두 가지는 다음과 같습니다.

  1. 데이터베이스 행과 같은 동일한 리소스를 업데이트하는 여러 클라이언트 예를 들어, 두 개의 동시 요청 중 하나는 레코드를 삭제하고 다른 하나는 동일한 레코드를 업데이트하려고합니다. 데이터베이스 및 설정 방법에 따라 데이터가 다르거 나 존재하지 않기 때문에 레코드에 대한 잠금 또는 유효하지 않은 조작이 발생할 수 있습니다.

  2. API로 특수 작업을 수행하는 수퍼 유저 또는 관리자


이 경우 어떻게해야합니까?

  1. 데이터베이스, 싱글 톤, 잠금 및 유사한 메커니즘에서 트랜잭션을 사용하여 리소스에 대한 액세스를 동기화하십시오.

  2. 토큰이 작동 할 수 있습니다. 클라이언트에 대한 정보를 저장하지 않으면 토큰 자체에 대해서만 더 좋을 것이라고 생각합니다. 한 단계에서 사용자를 확인하고 토큰을 할당 할 수 있습니다. 그런 다음 토큰이 살아 있고 유효한지 확인하십시오. 추가 정보를 얻으려면 해독 할 수있는 토큰을 사용하십시오. 이 토큰이 특수 토큰 인 경우 저장할 수 있으며 한 번에 하나만 허용 할 수 있습니다. 이렇게하면 사용자가 아닌 토큰의 유효성을 검사 할 수 있습니다.

이게 도움이 되길 바란다.


예, 토큰의 유사성과 OAuth 메커니즘에 대한 응답을 기대하고있었습니다. 마지막은 인증 전용입니다. 시나리오 1의 요점을 이해하지 못했습니다. REST API에서 동시성을 처리하는 까다로운 부분은 상태 비 저장 제약 조건을 유지하는 것입니다. 서버가 클라이언트에 대한 정보를 저장하지 않음을 의미합니다. 귀하의 시나리오 2는 현재 내가하고있는 일입니다! :)
AilurusFulgens

질문에 대답 했습니까?
Pablo Granados

죄송합니다 나는 그것이 문제에 대한 좋은 개요를 제공하기 때문에 당신의 대답을 찬성했지만 불행히도, imo, 그것은 실제로 문제를 다루지 않습니다.
AilurusFulgens

0

REST만으로는 너무 원시적입니다. REST를 시작할 수 있지만 결국 리치 애플리케이션에는 조인 및 트랜잭션 업데이트가 포함 된 쿼리가 필요합니다. 이러한 것들을 스스로 추가하려고 시도하는 모든 개발자는 오류가 발생하기 쉽고 일관성이 없습니다. 다행히도 OData라는 새로운 표준이 있습니다. REST 위에 계층화되고 (1) 탐색 속성을 사용하여 간단한 외래 키를 허용하는 외래 키를 노출시키지 않고 (2) 원자 변경 세트를 포함하는 일괄 처리를 제공하는 쿼리 언어를 제공합니다.

(1) https://stackoverflow.com/a/3921423/471129에 대해서는 여기를 참조하십시오 .

여기와 (2) https : //.com/a/21939972/471129 참조

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