2012-03-01 2 views
2

새로운 ASP.NET 웹 API를 기반으로 웹 API를 만들고 있습니다. 나는 동시에 여러 데이터 세트를 제출하는 사람들을 다루는 가장 좋은 방법을 이해하려고 노력하고있다. 10 만 건의 요청이있는 경우 한 번에 1,000 건을 제출하게하는 것이 좋습니다.새 ASP.NET 웹 API에서 "일괄 처리"요청을 어떻게 디자인합니까?

public string Put(Contact _contact) 
{ 
    //add new _contact to repository 
    repository.Add(_contact); 

    //return success 
} 

사용자가 "배치"새 연락처를 전송할 수 있도록하는 적절한 방법은 무엇입니까 :

이의 내가 내 연락처 컨트롤러의 새로운 연락 방법을 만들 수 있다고 가정 해 봅시다? 나는 생각 해요 :

public string BatchPut(IEnumerable<Contact> _contacts) 
{ 
    foreach (var contact in _contacts) 
    { 
     respository.Add(contact); 
    } 
} 

이 좋은 방법인가? 이것은 JSON 배열의 연락처로 GET 요청을 구문 분석합니까 (형식이 올바른 것으로 가정)?

마지막으로 일괄 요청에 가장 효과적으로 응답하는 방법에 대한 팁은 무엇입니까? 300 명 중 4 명이 실패한다면?

감사합니다.

+0

요청 크기, 사용자 수, 사용자 유형, 데이터 품질, 시간 제한 및 데이터베이스 안정성과 관련하여 서버에서 보장 할 수있는 보장은 무엇입니까? 이는 귀하가 사용할 수있는 디자인 선택에 영향을 미칩니 까? – bloudraak

+0

API 요청 당 1 개의 작업을 생성하는 API가 있습니다. 현재까지 API는 한 번에 하나의 작업 만 수행했습니다. 이러한 제한으로 인해 200,000 건의 요청을 많이 내야하는 대형 클라이언트에 대한 골치 거리가되었습니다. 각 단일 API 호출은 메시지로 Amazon SQS에 들어갑니다. 따라서 동시성은 문제가되지 않았으며 더 많은 양의 고객에겐 골치 거리였습니다. 감사! –

+0

비즈니스 프로세스에서 비동기 처리를 허용합니까? 예를 들어, 보험 회사에서 일하면서 큐를 사용하여 견적을 계산 했으므로 클라이언트가 데이터를 제출하고 견적을 만들었을 때 설문 조사를해야했습니다. 사용 가능한 리소스에 따라 2 ~ 2 분에서 30 분까지 걸렸습니다. – bloudraak

답변

2

컬렉션을 PUT하면 전체 컬렉션을 삽입하거나 기존 컬렉션을 단일 리소스 인 것처럼 바꿉니다. 이는 GET, DELETE 또는 POST 콜렉션과 매우 유사합니다. 이것은 원자 적 연산입니다. 사용하는 것은 PUT에 대한 개별 호출의 대체물로서 연락처가 매우 RESTfull이 아닐 수도 있습니다 (그러나 이는 논쟁의 여지가 있습니다).

HTTP pipelining을보고 동일한 소켓에 대해 여러 개의 PutContact 요청을 보낼 수 있습니다. 각 요청마다 단일 요청에 대한 표준 HTTP 상태를 반환 할 수 있습니다.

과거에는 SOAP을 사용하여 일괄 업데이트를 구현했으며 시스템로드시 예상치 못한 여러 문제가 발생했습니다. 나는 당신이주의를 기울이지 않으면 똑같은 문제에 빠질 것이라고 생각합니다.

  1. 예를 들어, 데이터베이스가 일괄 업데이트의 중간에 타임 아웃 할 수 있으며, 모든 지옥이 실패의 측면에서 풀려나, 신뢰성 등 거래 및 가난한 클라이언트가 실제로 업데이트 된 알아낼 시도했다 다시.
  2. 업데이트 할 레코드가 너무 많으면 너무 오래 걸리므로 HTTP 요청이 시간 초과됩니다. 그것은 벌레의 또 다른 깡통을 열었다.
  3. 업데이트하는 동안 얼마만큼의 데이터를 허용합니까? 10MB의 연락처로 충분 했습니까? 아마 1MB? 버퍼가 클수록 메모리 사용 및 보안 측면에서 많은 영향을 미칩니다.

따라서 제 제안은 HTTP pipelining입니다.

업데이트

나의 제안은 비동기 프로세스와 연락처의 일괄 생성을 처리 할 것. "일자리"가 "일괄 생성"프로세스와 동일하다고 가정하십시오. 그래서 같이 보일 수 있습니다 서비스는 다음과 같습니다

public class JobService 
{ 
    // Post 
    public void Create(CreateJobRequest job) 
    { 
     // 1. Create job in the database with status "pending" 
     // 2. Save job details to disk (or S3) 
     // 3. Submit the job to MSMQ (or SQS) 
     // 4. For 20 seconds, poll the database to see if the job completed 
     // 5. If the job completed, return 201 with a URI to "Get" method below 
     // 6. If not, return 202 (aka the request was accepted for processing, but has not completed) 
    } 

    // Get 
    public Job Get(string id) 
    { 
     // 1. Fetch the job from the database 
     // 2. Return the job if it exists or 404 
    } 
} 

실행 및 완료에 작업 상태를 업데이트 할 서비스에 PUT을 수행 대안으로 데이터베이스를 업데이트하거나 할 수있는 큐에서 물건을 소비하는 백그라운드 프로세스.

방금 ​​처리 된 데이터를 탐색하고 오류를 해결하기 위해 다른 서비스가 필요합니다.

배경 프로세스가 유효성 검사 오류를 허용해야 할 수도 있습니다. 그렇지 않거나 서비스가 유효성 검증을 수행하는 경우 (응답 시간을 보장 할 수없는 데이터베이스 호출 등을 수행하지 않는다고 가정), 클라이언트가 문제점을 수정하고 요청을 다시 제출하기위한 충분한 정보가 들어있는 CreateJobResponse와 같은 구조를 리턴 할 수 있습니다. 시간이 많이 소요되는 유효성 검증을 수행해야하는 경우 백그라운드 프로세스에서 수행하고 실패한 것으로 표시하고 클라이언트가 오류를 수정하고 요청을 다시 제출할 수있는 정보로 작업을 갱신하십시오. 이것은 클라이언트가 작업이 실패했다는 사실을 가지고 무언가를 할 수 있다고 가정합니다.

Create 메서드가 작업 요청을 여러 개의 작은 "작업"으로 나누면 작업량이 원자적일 수없고 작업이 성공적으로 완료되었는지 여부를 모니터링하는 데 많은 어려움이 있습니다.

+0

안녕하세요. Werner - 귀하의 제안에 감사드립니다. 나는 PUT 동사를 사용해서는 안됩니다 - 저의 실수. 위의 질문에 대해 다시 한 번 생각해 보겠습니다. 건배! –

+0

이것은 대단히 감사합니다. Werner, 정말 고마워요! 당신은 내가 아직 대답 할 생각조차하지 않은 질문에 대답하고 있습니다. MVC 웹 API의 모델 바인딩이 위와 같이 사용자 정의 객체의 목록을 처리 할 정도로 똑똑한 지 궁금합니다. 내가 더 큰 문제를 다루는 것처럼 들린다. 건배! –

0

PUT 작업은 리소스를 대체해야합니다. 일반적으로이 작업은 단일 리소스에 대해 수행하지만 컬렉션에 대해 수행 할 때 원본 컬렉션을 전달 된 데이터 집합으로 대체한다는 의미입니다. 확신 할 수는 없지만 컬렉션의 하위 집합을 업데이트 중이라면 PATCH 메서드가 더 적합 할 것이라고 가정합니다.

마지막으로, 일괄 요청에 응답하는 최선의 방법에 어떤 조언? 300 명 중 4 명이 실패한다면?

정말 당신에게 달렸습니다. 하나의 응답 만 있으므로 200 OK 또는 400 Bad Request를 보내고 본문에 세부 정보를 입력 할 수 있습니다.

+0

고마워 Maurice- 나는 PUT을 말하지 말았어야 했어. 사람들이 일괄 적으로 새 연락처를 만들 수 있도록 목표를 세우고 있습니다 (한 번에 1000 개). –

관련 문제