2009-11-18 4 views
2

우리는 현재 여러 제품에 대한 견적을 수행하는 ASP.NET 응용 프로그램을 향상시키고 있습니다.장기 실행 ADO.NET 쿼리와 함께 ThreadPool 스레드를 사용합니다. 확장 성이 있습니까?

현재 기존 견적 엔진은 기본적으로 큰 저장 프로 시저 (호출 당 2-3 초) 다음에 프로 시저 호출 후에 실행되는 소량의 비즈니스 논리가 뒤 따른다.

우리는 따옴표 세트의 속도를 높이기 위해 각 제품에 대한 호출을 멀티 스레딩하는 방법을 모색 중입니다.

현재 우리의 접근 방식은 각 제품 견적 작업을 ThreadPool 스레드에 캡슐화하는 것입니다. 이것은 성능이 훨씬 좋아진 것으로 보이지만 적은 수의 사용자와 실적이 좋지만 프로덕션 환경에서 확장 성이 우수 할까 걱정됩니다.

현재 비동기 ADO.NET 메서드를 사용하고 있지 않습니다.

참고 : ThreadPool을 호출하는 코드에는 ThreadPool의 구성 가능한 양만 한 번에 사용할 수 있도록 요청을 대기시키는 스로틀이 있습니다. 동일한 페이지에서 견적 결과를 기다릴 필요가 없으며 사용자가 진행하고 업데이트를 확인할 수 있습니다 (견적 결과 페이지는 AJAX를 사용하여 결과를 확인합니다).

추가 정보 : 선호하는 솔루션은 견적 서비스가 단방향 조작이기 때문에 메시지 대기열을 사용하는 것입니다. 그러나 프로젝트의 시간 척도는이를 수행 할 시간을 제공하지 못했습니다.

그 동안 우리는 ADO.NET의 비동기 메서드를 사용하도록 구현을 수정하려고합니다 (프로세스의 모든 장기 실행 측면이 그렇듯이) ThreadPool 스레드를 사용할 필요가 없습니다.

답변

6

실행중인 ADO.NET 쿼리가 길어 진 ThreadPool 스레드를 사용합니다. 이 은 (는) 확장 가능합니까?

짧은 대답은 아니오, 확장 할 수 없습니다.

ThreadPool 스레드는 일반 ASP.NET 요청을 처리하는데도 사용됩니다 (BeginInvoke에서도 마찬가지입니다). 제한된 수의 스레드가 있으며 사용량이 많아지면 들어오는 HTTP 요청은 스레드가 사용 가능해질 때까지 차단됩니다.

ASP.NET 스레드 풀의 스레드 수를 늘릴 수 있지만 스레드 수가 고정되어 있지 않은 것과 같은 다른 문제가 있습니다. 하중에 따라 천천히 증가합니다. 비동기 페이지를 사용할 수도 있고 사용해야 할 수도 있지만 실제로 SP를 실행하는 방법에 대한 질문은 여전히 ​​남아 있습니다. 가능한 경우 해당 부분에 대해 비동기 ADO.NET 메서드로 전환하는 것이 훨씬 더 좋습니다. 또한 요청 당 스레드를 사용하는 것보다 훨씬 가벼운 방법입니다.

도움이 될만한 점은 제 책 (Ultra-Fast ASP.NET)에서 자세히 다룹니다.

+0

안녕 릭, 내가 추가하는 것을 잊었다 , 우리는 기본적으로 스레드에서 얼마나 많은 스레드 주위 스로틀을 넣었습니다. 내 질문을 수정하겠습니다. – spooner

+0

스레드 수를 제한해야한다면 처리 할 수있는 동시 요청 수가 제한되지 않습니까? 한 번에 처리 할 수있는 조작의 수에 따라 확장 성이 정의되지 않았습니까? – RickNZ

+0

공정한 포인트 :) 이 접근법은 다음과 같습니다. 단일 스레드 풀 스레드에서 모든 인용 부호를 실행합니다 (페이지를 위로 올려 놓고 따옴표를 백그라운드에서 실행). 그런 다음 따옴표의 논리에서 ADO.NET의 비동기 메서드 (대신 IO 스레드를 사용한다고 생각합니다)를 사용합니다. – spooner

1

ASP.NET에는 요청을 시작할 수있는 비동기 처리기가 있으며 처리기가 아닌 스레드에서 실행되며 모든 기본 제공 요청 처리기 스레드와 다른 3 번째 스레드에서 완료 될 수 있습니다 . 나는 그것을 수천 번 사용했습니다.

http://msdn.microsoft.com/en-us/magazine/cc163725.aspx

는 모두를 연결하는 자신에게 약간의 도우미 메서드를 작성합니다.

/// <summary> 
/// On load event override 
/// </summary> 
/// <param name="e">arguments to the event</param> 
protected override void OnLoad(EventArgs e) 
{ 
    base.OnLoad(e); 
    string query = this.Page.Request.QueryString["query"]; 
    if (!string.IsNullOrEmpty(query)) 
    { 
     var pat = new PageAsyncTask(this.BeginAsync, this.EndAsync, this.TimeOut, query); 
     this.Page.RegisterAsyncTask(pat); 
    } 
    string me = string.Format(Format, System.Threading.Thread.CurrentThread.ManagedThreadId, "Onload"); 
    Trace.Write(me); 
} 
protected override void Render(HtmlTextWriter writer) 
{ 
    string me = string.Format(Format, System.Threading.Thread.CurrentThread.ManagedThreadId, "Render"); 
    Trace.Write(me); 
    this.Icompleted.Text = DateTime.Now.ToString(); 
    base.Render(writer); 
} 
/// <summary> 
/// start the async task 
/// </summary> 
/// <param name="sender">original caller</param> 
/// <param name="e">unused arguments</param> 
/// <param name="cb">call back routine</param> 
/// <param name="state">saved stated</param> 
/// <returns>IAsyncResult to signal ender</returns> 
private IAsyncResult BeginAsync(object sender, EventArgs e, AsyncCallback cb, object state) 
{ 
    this.bsc = new YourWebServiceReferenceGoesHere(); 
    return this.bsc.BeginGetResponseXml("1", (string)state, "10", "1", cb, state); 
} 

/// <summary> 
/// when the task completes 
/// </summary> 
/// <param name="ar">the async result</param> 
private void EndAsync(IAsyncResult ar) 
{ 
    XmlResponse response = this.bsc.EndGetResponseXml(ar); 
    this.bsc.Close(); 
    this.bsc = null; 
    this.PostProcess(response); 
} 

private void TimeOut(IAsyncResult ar) 
{ 
    // currently we do nothing here. 
} 

/// <summary> 
/// 
/// </summary> 
private void PostProcess(XmlResponse response) 
{ 
    string me = string.Format(Format, System.Threading.Thread.CurrentThread.ManagedThreadId, "bingsearch"); 
    Trace.Write(me); 
    var xds = new XmlDataSource 
    { 
     EnableCaching = false, 
     CacheDuration = 0, 
     Data = response.Xml, 
     Transform = this.RemoveNamespaces() 
    }; 
    this.some.DataSource = xds; 
    this.some.DataBind(); 
} 
+0

비동기 페이지 사용을 고려했지만 인용 프로세스를 트리거하는 페이지에서 응답을 기다릴 필요가 없습니다. 아이디어는 기본적으로 백그라운드에서 작업을 시작한 다음 사용자가 필요할 때 견적 결과 페이지를 볼 수 있으며 AJAX를 사용하여 해당 페이지의 결과를 확인합니다. – spooner

+0

기다리고 싶지 않으면 위의 코드를 사용하고 EndAsync에 대한 호출을 직접 연결하십시오. 페이지가 대기하지 않고 스레드를 만들지 않으며 후속 통화가 차단되지 않습니다. –

관련 문제