所以,我正在尝试为Solr构建一个简单的日志回放机制。这似乎很容易,一个Windows表单应用程序包含一个从日志文件中读取查询参数的循环,重新构建查询URL,使用HttpRequest(或WebClient)提交它。当然,我希望播放尽可能快,因此每个请求都是在自己的异步委托上启动的。
一切都很好;然而,它似乎并没有像我预期的那么快。在做了一些挖掘后,我了解到最大同时连接数是有限的:Improving performance of multithreaded HttpWebRequests in .NET。我做了相应的配置更改,并再次尝试,没有运气。无论我如何尝试,我似乎都可以使servicePoint.CurrentConnections大于1。
我可能还有其他一些事情没有考虑到吗?具体来说:我在表单上使用后台工作程序对象来运行主循环(读取日志文件的那个)。在这个循环中,我调用了我的异步'BeginSearch'函数,然后调用我的异步回调'EndSearch'。
for (int i = 0; i < lines.Length - 1; i++)
{
//System.Diagnostics.Debug.WriteLine(lines[i]);
if ((urlParameters = this.GetURLParameters(lines[i])) != null)
{
//It looks like we have a logged query
Console.WriteLine(string.Format("{0} - {1}", servicePoint.ConnectionLimit, servicePoint.CurrentConnections));
//System.Threading.Tasks.Task<ServiceProviderResults> submitQuery = new System.Threading.Tasks.Task<ServiceProviderResults>(() => this.BeginSearch(urlParameters));
//System.Threading.Tasks.Task processQuery = submitQuery.ContinueWith(x => this.Y(x.Result));
//submitQuery.Start();
//Wait until the count of currently executing asynchronous operations falls below the predetermined threshold
while (this.currentAsyncOperations >= MAX_ASYNC_OPERATIONS)
{
System.Threading.Thread.Sleep(10);
}
lock (this.asyncLock)
{
this.currentAsyncOperations++;
}
SearchDelegate searchDelegate = new SearchDelegate(this.BeginSearch);
searchDelegate.BeginInvoke(urlParameters, new AsyncCallback(this.EndSearch), null);
//System.Threading.Thread.Sleep(0);
Application.DoEvents();
}
}
异步标注:
private ServiceProviderResults BeginSearch(string parameters)
{
QueryURL queryURL = new QueryURL(string.Format("{0}select?{1}", this.textBoxSolrCore.Text, parameters));
//TODO: For purposes of experimentation, overrides go here
return new ServiceProviderResults(queryURL);
}
异步回调:
{
ServiceProviderResults serviceProviderResults = null;
try
{
AsyncResult asyncResult = (AsyncResult)result;
SearchDelegate searchDelegate = (SearchDelegate)asyncResult.AsyncDelegate;
serviceProviderResults = searchDelegate.EndInvoke(result);
lock (statLock)
{
this.queriesCompleted++;
this.qTimeSum += serviceProviderResults.ResponseHeader.QTime;
this.roundTripSum += serviceProviderResults.Stopwatch.ElapsedMilliseconds;
}
string message = string.Format("NumFound: {0} QTime: {1}ms RoundTrip: {2}ms Query {3}", serviceProviderResults.NumFound, serviceProviderResults.ResponseHeader.QTime, serviceProviderResults.Stopwatch.ElapsedMilliseconds, serviceProviderResults.QueryURL.ToString());
//System.Diagnostics.Debug.WriteLine(message);
this.ShowProgress(message);
}
catch (Exception e)
{
this.exceptionsThrown++;
this.AddQueryException(new QueryException(e, serviceProviderResults.QueryURL));
}
finally
{
lock (this.asyncLock)
{
this.currentAsyncOperations--;
}
}
}