클라이언트와 서버 간의 다단계 작업에서 오류를 처리하기위한 모범 사례는 무엇입니까?

Aug 18 2020

내 API에 채용 공고를 업로드하는 웹 사이트가 있습니다. 여러 단계를 거쳐야합니다.

  1. 파일 저장소에 로고 이미지를 업로드합니다.

  2. 채용 공고에 대한 데이터를 데이터베이스에 삽입합니다.

  3. 타사 제공 업체를 통해 결제를 처리합니다.

  4. 타사 제공 업체를 통해 이메일을 보냅니다.

일반적으로 타사 API에서 일부 정보 가져 오기, ReCAPTCHA 유효성 검사, Google Indexing API 업데이트, SMS 전송 등과 같은 다른 응용 프로그램에서 여기에 다른 단계가 있다고 상상할 수 있습니다.

이들 모두는 타사를 사용하고 API 호출을 처리하는 서버와 독립적이기 때문에 이들 중 하나는 일부 단계를 성공적으로 완료하지 못하고 나머지는 완료하지 못할 수 있습니다 (예 : 로고가 업데이트되었지만 결제가 이루어지지 않음).

제 질문은 일반적으로 프로덕션 시스템에서 클라이언트와 서버 간의 이러한 종류의 다단계 작업에서 오류가 어떻게 처리됩니까? 허용되는 표준이나 모범 사례가 있습니까?


나는 다음을 고려했습니다.

  1. 오류를 처리하지 않고 모든 것이 오류없이 진행되기를 바랍니다.

  2. 각 단계에 대해 백엔드에서 '실행 취소'기능을 정의하고 단계 중 하나가 실패하면 이전 단계에서이를 호출합니다. 여러 단계로 구성된 작업을 사용하면 매우 빠르게 스파게티 코드로 바뀔 수 있으며 일부 단계는 쉽게 취소 할 수 없습니다 (예 : 이메일 보내기).

  3. 각 단계에 대해 백엔드에 별도의 엔드 포인트를 만들고 클라이언트가 각 단계를 차례로 호출하도록합니다. 또한 '실행 취소'API 엔드 포인트를 사용할 수 있으므로 클라이언트가 단계 중 하나에서 오류를 수신하면 이전 단계를 모두 실행 취소 할 수 있습니다. 이것은 클라이언트가 완료되고있는 작업의 진행 상황을 추정 할 수 있도록하는 장점이 있습니다. 즉, 사용자에게 '5 단계 중 1 단계 완료'를 표시 할 수 있습니다.

  4. 각 작업에 대해 DB (또는 메모리 내 데이터베이스?)에 행을 만들고 각 단계가 완료되면 해당 열을 완료된 것으로 표시합니다. 행의 모든 ​​열이 완료되면 사용자에게 응답을 보냅니다.

답변

1 RalfKleberhoff Aug 19 2020 at 13:30

이 다단계 프로세스는 일관된 초기 상태 ( '아무것도 발생하지 않음')에서 일부 최종 상태 ( '채용 ​​게시 완료')로 이동하는 트랜잭션이며 앱을 일관성없는 상태로 만드는 중간 단계를 포함합니다.

거래 처리를 고객에게 위임해서는 안되며, 특히 프로세스를 개별 통화로 분할해서는 안됩니다 (또는 결제 단계를 건너 뛸 수 있으므로 비즈니스에 좋지 않음).

한 단계가 실패하더라도 계속하는 것은 말도 안되는 일입니다. 반드시 초기 상태가 아닌 수용 가능한 상태로 일종의 롤백을 수행해야합니다. 예를 들어 업로드 된 이미지를 파일 저장소에서 제거해야 할 절대적인 필요성이 없다고 생각합니다.

첫째, 대부분의 중간 단계가 허용되는 방식으로 단계를 배열하려고하므로 롤백 할 필요가 없습니다.

까다로운 단계는 확실히 지불 및 이메일입니다 (비즈니스를 올바르게 이해 한 경우).

  • 이메일을 보내지 않고 고객에게 청구하는 것은 좋지 않습니다 (사기에 가깝습니다).
  • 지불하지 않고 이메일을 보내는 것은 돈을 잃는 것을 의미합니다 (이런 일이 자주 발생하지 않는 경우 허용 될 수 있음). 이메일이 전송 된 후에는 확실히 롤백 할 수 없지만 지불을 롤백 할 수 있습니다 (그 순간에 공급자와의 연결이 끊어지지 않는 한).

외부 연결에 의존하기 때문에 트랜잭션의 부분적인 완료를 절대적으로 피할 수있는 방법이 없으므로 중간 오류가 발생하는 방식으로 프로세스를 설계 할 것입니다.

  • 가능성이 매우 낮거나
  • 또는 견딜 수있는 상태를 유지하십시오.

그래서 나는

  1. 모든 expernal 서비스를 Ping하여 현재 작동하고 연결 가능한지 확인하십시오.
  2. 파일 저장소에 로고 이미지를 업로드합니다.
  3. 채용 공고에 대한 데이터를 데이터베이스에 삽입합니다.
  4. 타사 제공 업체를 통해 이메일을 보냅니다.
  5. 타사 제공 업체를 통해 결제를 처리합니다.

롤백 절차는 다음과 같습니다.

  • 파일 저장소에서 이미지를 제거하고,
  • 데이터베이스에서 채용 공고를 제거하고
  • 이메일을 보냈지 만 결제에 실패한 경우 : 나중에 재 시도 할 수 있도록 결제 요청을 예약합니다.
JacquesB Aug 18 2020 at 21:56

"최고"는 분명히 요구 사항에 따라 다릅니다. 1 번은 구현하기 가장 간단하지만 오류가 발생하면 트랜잭션이 손실되거나 불완전합니다. 아마도 이것이 비즈니스 관점에서 받아 들일 수있는 절충안일까요?

가장 강력한 솔루션은 프로세스를 각 단계가 트랜잭션 인 일련의 단계로 분할하는 것입니다. 트랜잭션은 완료되거나 실패하며 실패한 경우 안전하게 다시 시도 할 수 있습니다. (예를 들어 메일 또는 SMS를 보내는 것은 트랜잭션이됩니다.) 데이터베이스 행은 완료된 단계를 추적합니다.

고객이 각 단계를 호출하도록해야한다고 생각하지 않습니다. 그것은 긴밀한 결합을 만들고 복잡성을 증가시킬 것입니다. 클라이언트가 필요한 모든 데이터가 포함 된 단일 요청을 호출하도록하면 워크 플로가 시작됩니다. 그런 다음 클라이언트는 진행 상황을 표시하려는 경우 상태를 폴링하기 위해 별도의주기적인 요청을 보낼 수 있습니다.

실행 취소 지원은 더 복잡하며 (보시다시피) 항상 가능한 것은 아닙니다. 신용 카드가 유효하지 않은 경우와 같이 전체 프로세스가 거부되어야하는 방식으로 일부 단계가 실패 할 수있는 경우 다단계 프로세스가 시작 되기 전에 유효성 검사 단계에서 수행되어야한다고 생각합니다 . 이를 통해 고객에게 동기식 피드백을 제공하고 고객이 데이터를 검토하고 다시 입력하도록 할 수 있습니다.

AdrianL Aug 27 2020 at 01:00

다른 사람들이 언급했듯이 이상적으로 성공적인 채용 공고에 필요한 모든 부분을 번들로 묶고 클라이언트가 한 번의 요청으로이를 백엔드로 보내도록하는 것이 좋습니다. 모바일 개발자로서 저는 항상 데이터 사용량과 배터리 수명을 보존하기 위해 가능한 최소한의 작업으로 고객을 옹호합니다.

백엔드는 DB에 가장 중요한 정보를 먼저 삽입 한 다음 로고 이미지와 같은 추가 데이터를 삽입하는 등의 시도를 권장합니다.