2013-05-24 2 views
0

이해하기 쉽게하기 : 우리는 연결 풀링 기능이 내장되어 있지 않은 데이터베이스를 사용하고 있습니다. 우리는 자체 연결 풀러를 구현하고 있습니다.비동기 WCF 서비스

좋아, 그래서 제목이 아마도 가장 좋은 설명을 제공하지 않았다. 우선 내가하려고하는 것을 설명해주십시오. 우리는 한 번에 여러 요청을 처리/처리 할 수 ​​있어야하는 WCF 서비스 (Windows 서비스에서 호스팅 됨)가 있습니다. WCF 서비스는 요청을 받아 사용할 수있는 10 개의 데이터베이스 연결 (말)을 시도합니다. 이러한 데이터베이스 연결은 WCF 서비스와 처리가 사용 중으로 설정된 경우 모두 추적됩니다. 요청이 들어오고 WCF가 10 개의 데이터베이스 연결 중 하나와 통화하려고 시도하고 모두가 사용 중으로 설정된 경우 WCF 서비스가 사용 가능할 때까지 기다리고 응답을 반환하고자합니다.

우리는 몇 가지 다른 시도를했습니다. 예를 들어 while 루프를 사용할 수 있습니다.

[OperationContract(AsyncPattern=true)] 
ExecuteProgram(string clientId, string program, string[] args) 
{ 
    string requestId = DbManager.RegisterRequest(clientId, program, args); 
    string response = null; 
    while(response == null) 
    { 
     response = DbManager.GetResponseForRequestId(requestId); 
    } 

    return response; 
} 

기본적으로 DbManager는 요청과 응답을 추적합니다. 각 요청은 요청 ID를 할당하는 DbManager를 호출합니다. 데이터베이스 연결이 가능할 때 그것은 Responses [requestId] = [database reponse]를 할당 할 것이다. 요청은 DbManager에 응답이 있는지 여부와 요청이 반환 할 수 있는지 여부를 지속적으로 묻습니다.

여기에는 문제가 있습니다. 얼마나 많은 시간 동안 누가 알고 있는지 while 루프에 끼어있는 스레드를 여러 개 가질 수 있습니다. 그것은 성능과 CPU 사용량에있어서 끔찍한 것입니다. (최소한 말하기)

우리는 또한 이벤트/리스너와 함께 이것을 시도했다. 나는 이것이 어떻게 성취 될지 모른다. 그래서 아래의 코드는 우리가 그것을 어떻게 구상했는지에 대한 것이다.

[OperationContract(AsyncPattern=true)] 
ExecuteProgram(string clientId, string program, string[] args) 
{ 
    // register an event 
    // listen for that event 
    // when that event is called return its value 
} 

우리는 또한 큐가 있거나 (우리가 익숙있는) 펄스/Monitor.Wait 같은 것들을 사용하여 DbManager으로 보았다.

문제는 다음과 같습니다. 어떻게 할 수있을 때 반환하는 비동기 WCF 연산을 가질 수 있습니까?

+1

연결 풀을 세마포로 보호하십시오. – YK1

답변

2

WCF는 .net 4.5 http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx의 async/await 키워드를 지원합니다. ExecuteProgram async를 만들고 DbManager 요청 작업을 기다릴 수 있도록 약간의 리팩터링을 수행해야합니다.

DbManager가 주어진 clientIds에 대한 결과가 제공 될 때 이러한 작업의 완료를 관리해야하는 경우 각 클라이언트 ID를 TaskCompletionSource에 매핑 할 수 있습니다. TaskCompletionSource을 사용하여 Task을 만들고 DbManager는 TaskCompletionSource을 사용하여 결과를 설정할 수 있습니다.

1

이 전화를 제대로 구현 async 방법, 작동합니다 :

[OperationContract] 
string ExecuteProgram(string clientId, string program, string[] args) 
{ 
    Task<string> task = DbManager.DoRequestAsync(clientId, program, args); 
    return task.Result; 
} 

은 수동으로 열 개 DB 연결을 관리하고 있습니까? 데이터베이스 연결 풀링을 다시 구현 한 것 같습니다. DB 서버 또는 드라이버에 내장 된 연결 풀링을 사용해야합니다.

+0

그래, 작동해야하지만 직접 호출하는 것보다 장점이 무엇입니까'return DbManager.DoRequest (....) ' – I4V

+0

ExecuteProgram 구현이 비동기 패턴 자체를 따르지 않으면 해당 스레드는 여러 요청을 처리 할 수 ​​없습니다. – insipid

+0

우리는 실제로 연결 풀링을 구현하려고합니다 (다소). 우리가 사용하고있는 데이터베이스는 유감스럽게도 평범한 sql/nosql 데이터베이스가 아닙니다. – Shattuck

1

데이터베이스 서버가 하나 뿐인 경우 (해당되는 것으로 의심되는 경우) 풀에 BlockingCollection을 사용하십시오.