1

저는 새로운 코드가 레거시 시스템과 상호 운용되도록 WCF 서비스를 개발하고 있습니다. 이 과정은 다음과 같습니다.WCF 서비스는 클라이언트가 결과를 수신 한 경우에만 로그를 작성합니다.

  1. 클라이언트는 레거시 시스템에 대한 요청으로 서비스를 호출합니다.
  2. 서비스가 요청을 데이터베이스에 기록합니다.
  3. DB에서 자체 시스템 시간 요청을 요청하고 DB에 결과를 다시 기록합니다 (상태 플래그를 업데이트하여 결과가 준비 됨).
  4. 클라이언트는 준비 플래그가 설정 될 때까지 DB를 폴링하는 두 번째 서비스 메서드를 호출하여 결과를 검색합니다.
  5. 결과를 반환하기 직전에 서비스는 클라이언트에 결과가 인 상태 플래그를 업데이트하여 관련 DB 행을 삭제할 수 있습니다.

내 관심사는 마지막 단계의 경쟁 조건입니다. 나는 이런 일을 볼 수

  1. 서비스 업데이트 상태 에 클라이언트는 결과가 있습니다.
  2. 서비스가 DB를 폴링하기를 기다린 후 클라이언트 시간 초과.
  3. 서비스가 결과를 반환하려고 시도합니다. Hilarity가 계속됩니다.

이 문제를 해결하는 한 가지 방법은 두 가지가 아닌 세 가지 서비스 호출을 사용하는 것입니다. 두 번째 호출이 결과를 검색하고 마지막 호출이 클라이언트에 의해 명시적인 확인 응답입니다. 나는이 여분의 "프로토콜"부담을 클라이언트에 부과하지 않는 방법이 있는지를 알고 싶습니다.

WCF에서 트랜잭션을 사용하는 방법을 간략히 살펴 보았습니다. 필요한 작업을 수행 할 수있는 것 같습니다. 클라이언트 (선택적)는 트랜잭션을 시작하여 서비스에 전달하고 서비스가 있으면 서비스를 사용하고 완료되면 커밋합니다. 이것은 암묵적으로 "세 번째 호출"을 수행하는 것처럼 보입니다.

이 아이디어는 어떤 장점이 있습니까? 당신이 볼 수있는 단점은 무엇입니까? 내가 탐색 할 수있는 다른 방법이 있습니까?

답변

1

트랜잭션 흐름을 사용할 수 있지만 폴링 시나리오 (각 폴링 호출에서)는 트랜잭션이 끔찍한 아키텍처입니다. 일반적으로 필요한 것은 서비스가 레코드를 수정하고 데이터를 클라이언트에 반환하는 실제 읽기 작업을위한 트랜잭션 흐름입니다. 클라이언트는 트랜잭션을 커밋하고 서비스가 수행 한 변경을 커밋합니다.

트랜잭션 처리를 사용하면 서비스 및 클라이언트에 몇 가지 추가 요구 사항이 추가됩니다.

또 다른 방법은 트랜잭션 MSMQ가 될 수 있습니다

  1. 클라이언트가 기존 시스템에 대한 요청과 함께 서비스를 호출 = 클라이언트가 서비스의 큐
  2. 서비스에 메시지를 전송하는 데이터베이스 = 서비스 프로세스에 요청을 기록 대기열의 메시지
  3. 기존 시스템 서비스가 자체 시간에 DB에서 요청하고 결과를 DB에 기록합니다 (결과 플래그가 업데이트 됨).
  4. 서비스는 데이터베이스를 폴링하고 메시지를 클라이언트 큐를 수정하도록 배치합니다. 데이터베이스 레코드를 메시지를 배치 및 수정하는 트랜잭션에서 실행
  5. 클라이언트는 수신 메시지를 처리 ​​

트랜잭션 큐는 트랜잭션 읽기 (메시지가 추가됩니다 (메시지가 트랜잭션이 커밋 경우에만 큐에서 제거) 및 기록 할 수 있습니다 트랜잭션이 커밋 된 경우에만 대기열). 이렇게하면 메시지가 성공적으로 읽힐 때까지 (또는 일부 오류 큐에 전달 될 수있는 시간 초과가 될 때까지) 메시지가 큐에 남아 있기 때문에 클라이언트가 메시지를 읽기 전에 레코드를 삭제할 수 있습니다.

두 경우 모두 서비스를 사용할 클라이언트를 생각해야합니다. 트랜잭션 흐름은 상호 운용 가능할 수 있지만 모든 웹 서비스 스택이이를 지원하는 것은 아닙니다. MSMQ는 상호 운용 할 수 없습니다.

1

왜이 대신 수행하여 클라이언트 타이밍의 가능성을 감소시키지 :

  1. 클라이언트는 레거시 시스템에 대한 요청으로 서비스를 호출합니다.
  2. 서비스가 요청을 데이터베이스에 기록합니다.
  3. DB에서 자체 시간에 요청한 레거시 시스템 서비스가 결과를 다시 DB에 기록합니다 (결과 플래그가 업데이트 됨).
  4. 클라이언트는 결과가 준비되었는지 확인하기 위해 서비스를 호출합니다. NB. 폴링 없음 : 즉시 예 또는 아니오로 반환됩니다.
  5. 결과가 준비되지 않은 경우 클라이언트는 조금 기다린 다음 4 단계로 돌아갑니다.
  6. 결과가 준비되면 서비스를 호출하여 결과를 검색하십시오. 서비스는 그 시점에서 "클라이언트 결과"상태를으로 업데이트 할 수 있습니다.

이렇게하면 클라이언트는 4 단계에서 서비스 호출을 기다리지 않고 오랜 기간 동안 반환 할 수 없으므로 제한 시간이 최소화되어야합니다.

그러나 클라이언트는 100 % 특정이 될 것입니다. 클라이언트가 최종 서비스 호출을하지 않으면 클라이언트는 결과를 수신합니다. (마지막 요청을 한 후에 클라이언트가 죽는 경우 어떻게됩니까?)

+0

답변 해 주셔서 감사합니다. 서비스에 대한 폴링을 수행하는 이유는 DB를 개별 클라이언트의 손에 맡기는 대신 폴링 빈도에 대한 정책을 설정하는 유일한 곳이 있다는 것입니다. 우리가 배포하고 우리가 너무 힘들다는 것을 알게되면 수십, 수백 건의 클라이언트 업데이트를 배포 할 필요가 없습니다. 아무도 interop을하는 우아한 방법이라고 말하지 않았습니다. 아아 :) 100 % 확신 할 수 없다는 요점은 잘 받아 들여지지만 트랜잭션 (내가 생각하는대로 작동한다면)은 시간 초과 및 롤백의 이점을 얻을 수 있습니다. 저지른. – shambulator

+0

@Anton : 클라이언트 코드를 소유 한 경우 클라이언트에 "nother!"서비스를 호출하는 로직을 추가하여 클라이언트가 "내 결과 준비 완료"서비스를 호출 할 수있는 빈도를 문의 할 수 있습니다. 이런 방식으로 서버 한 곳에서 임계 값을 변경하여 클라이언트 호출을 조정할 수 있습니다. 이를 수행하기 위해 클라이언트에서 코드를 업데이트 할 필요가 없습니다. – razlebe

+0

@Anton : 또 다른 제안 : 결과가 준비 될 시점에 대한 예상치를 계산하여 클라이언트에 전달할 수 있다는 점을 서버 측에서 충분히 예측할 수 있습니다 (사실상 결과에 대한 첫 번째 클라이언트 호출 일정 지정)? – razlebe

관련 문제