繁体   English   中英

使用多个长时间运行的操作优化ASMX Web服务

[英]Optimizing an ASMX web service with Multiple Long-Running Operations

我正在使用具有DoLookup()函数的C#编写ASP.NET Web服务。 对于每次调用DoLookup()函数,我需要我的代码执行两个单独的查询:一个到另一个Web服务在远程站点,一个到本地数据库。 在我编译结果并将它们作为对DoLookup方法的响应返回之前,两个查询都必须完成。 我正在处理的问题是,我希望在响应时间和Web服务器上的资源使用方面尽可能提高效率。 我们预计每小时会有数千个查询。 这是一个粗略的C#概述我到目前为止所拥有的:

public class SomeService : System.Web.Services.WebService
{
    public SomeResponse DoLookup()
    {
        // Do the lookup at the remote web service and get the response 
        WebResponse wr = RemoteProvider.DoRemoteLookup();   

        // Do the lookup at the local database and get the response
        DBResponse dbr = DoDatabaseLookup();

        SomeResponse resp = new SomeResponse( wr, dbr);

        return resp;
    }
}

上面的代码按顺序执行所有操作并且运行良好但现在我想使其更具可伸缩性。 我知道我可以异步调用DoRemoteLookup()函数(RemoteProvider具有BeginRemoteLookup / EndRemoteLookup方法),并且我还可以使用BeginExecuteNonQuery / EndExecuteNonQuery方法异步执行数据库查找。

我的问题(最后)是这样的:如何在不同的线程上同时触发远程Web服务查找和数据库查找,并确保它们在返回响应之前都已完成?

我想在不同的线程上执行这两个请求的原因是它们都可能具有较长的响应时间(1或2秒)并且我想释放Web服务器的资源以在等待响应时处理其他请求。 另外一个注意事项 - 我目前正在异步运行远程Web服务查找,我只是不想让上面的示例太混乱。 我正在努力解决的问题是同时启动远程服务查找和数据库查找,并弄清楚它们何时完成。

谢谢你的任何建议。

您可以使用一对AutoResetEvents ,每个线程一个。 在线程执行结束时,您调用AutoResetEvents.Set()来触发事件。

产生线程后,使用WaitAll()和两个AutoResetEvents。 这将导致线程阻塞,直到设置了两个事件。

这种方法的警告是你必须确保调用Set(),否则你将永远阻止。 另外,请确保使用线程执行正确的异常处理,否则当无法处理的异常导致Web应用程序重新启动时,您将无意中导致更多性能问题。

MSDN有关于AutoResetEvent用法的示例代码。

请参阅异步XML Web服务方法如何:创建异步Web服务方法如何:使用Web服务方法链接异步调用

但请注意这些条款的第一段:

本主题特定于遗留技术。 现在应使用Windows Communication Foundation(WCF)创建XML Web服务和XML Web服务客户端。


顺便说一句,按照这些文章说的方式做事非常重要,因为它可以在长时间运行的任务运行时释放ASP.NET工作线程。 否则,您可能会阻止工作线程,阻止它为进一步的请求提供服务,并影响可伸缩性。

假设您可以为Web请求和数据库查找提供回调函数,那么这些行中的某些内容可能会起作用

bool webLookupDone = false;
bool databaseLookupDone = false;

private void FinishedDBLookupCallBack()
{
    databaseLookupDone = true;
    if(webLookupDone)
    {
        FinishMethod();
    }
}

private void FinishedWebLookupCallBack()
{
    webLookupDone = true;
    if(databaseLookupDone)
    {
        FinishMethod();
    }
}

我想我没有足够的代表来进行投票或评论。 所以这是对John Saunders的回答以及Alan对此的评论。

如果您担心可扩展性和资源消耗,那么您肯定希望得到John的答案。

这里有两个注意事项:加速单个请求,并使系统有效地处理许多并发请求。 前者Alan和John的答案都是通过并行执行外部调用来实现的。

后者,听起来这是你的主要关注点,是通过不在任何地方阻止线程来实现的,即John的回答。

不要生成自己的线程。 线程很昂贵,如果你使用.net框架提供的asynch方法,IO Threadpool中已经有很多线程可以为你处理你的外部调用。

您的服务的web方法也需要异步。 否则,工作线程将被阻塞,直到外部调用完成(即使它们并行运行,它仍然是1-2秒)。 并且每个CPU只有12个线程处理传入的请求(如果你的machine.config是根据建议设置的。)即你最多能够处理12个并发请求(CPU的数量)。 另一方面,如果您的Web方法是异步的,那么Begin将会非常有效地返回,并且线程返回到工作线程池准备好处理另一个传入请求,而您的外部调用正在被IO完成端口等待,他们将在那里一旦返回,就由IO线程池中的线程处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM