我有一个从服务器获取 api 数据的异步方法。当我在本地计算机上的控制台应用程序中运行此代码时,它会高速执行,每分钟在异步函数中推送数百个 http 调用。然而,当我将相同的代码从 Azure WebJob 队列消息触发时,它似乎同步运行,并且我的数字在爬行 - 我确信我的方法中缺少一些简单的东西 - 感谢任何帮助。
(1) .. WebJob 函数侦听队列上的消息并在收到消息时启动 api get 进程:
public class Functions
{
// This function will get triggered/executed when a new message is written
// on an Azure Queue called queue.
public static async Task ProcessQueueMessage ([QueueTrigger("myqueue")] string message, TextWriter log)
{
var getAPIData = new GetData();
getAPIData.DoIt(message).Wait();
log.WriteLine("*** done: " + message);
}
}
(2) azure外部以异步模式快速工作的类...
class GetData
{
// wrapper that is called by the message function trigger
public async Task DoIt(string MessageFile)
{
await CallAPI(MessageFile);
}
public async Task<string> CallAPI(string MessageFile)
{
/// create a list of sample APIs to call...
var apiCallList = new List<string>();
apiCallList.Add("localhost/?q=1");
apiCallList.Add("localhost/?q=2");
apiCallList.Add("localhost/?q=3");
apiCallList.Add("localhost/?q=4");
apiCallList.Add("localhost/?q=5");
// setup httpclient
HttpClient client =
new HttpClient() { MaxResponseContentBufferSize = 10000000 };
var timeout = new TimeSpan(0, 5, 0); // 5 min timeout
client.Timeout = timeout;
// create a list of http api get Task...
IEnumerable<Task<string>> allResults = apiCallList.Select(str => ProcessURLPageAsync(str, client));
// wait for them all to complete, then move on...
await Task.WhenAll(allResults);
return allResults.ToString();
}
async Task<string> ProcessURLPageAsync(string APIAddressString, HttpClient client)
{
string page = "";
HttpResponseMessage resX;
try
{
// set the address to call
Uri URL = new Uri(APIAddressString);
// execute the call
resX = await client.GetAsync(URL);
page = await resX.Content.ReadAsStringAsync();
string rslt = page;
// do something with the api response data
}
catch (Exception ex)
{
// log error
}
return page;
}
}
首先因为你的触发函数是async
,你应该使用await
而不是.Wait()
。等待会阻塞当前线程。
public static async Task ProcessQueueMessage([QueueTrigger("myqueue")] string message, TextWriter log)
{
var getAPIData = new GetData();
await getAPIData.DoIt(message);
log.WriteLine("*** done: " + message);
}
无论如何,您都可以从以下位置找到有用的信息文档 https://azure.microsoft.com/en-us/documentation/articles/websites-dotnet-webjobs-sdk-storage-queues-how-to/#trigger
并行执行
如果您有多个函数监听不同的队列,则当同时收到消息时,SDK 会并行调用它们。
当单个队列接收到多条消息时也是如此。默认情况下,SDK 获取一次一批 16 个队列消息,并执行并行处理它们的函数。 批量大小是可配置的 https://azure.microsoft.com/en-us/documentation/articles/websites-dotnet-webjobs-sdk-storage-queues-how-to/#config。当正在处理的数量降至批次大小的一半时,SDK 会获取另一个批次并开始处理这些消息。因此,每个函数处理的最大并发消息数是批处理大小的一倍半。此限制分别适用于具有 QueueTrigger 属性的每个函数。
以下是配置批量大小的示例代码:
var config = new JobHostConfiguration();
config.Queues.BatchSize = 50;
var host = new JobHost(config);
host.RunAndBlock();
但是,同时运行太多线程并不总是一个好的选择,并且可能会导致性能下降。
另一种选择是扩展您的网络作业:
多个实例
如果您的 Web 应用程序在多个实例上运行,则连续的 WebJob 在每台计算机上运行,并且每台计算机将等待触发器并尝试运行函数。 WebJobs SDK 队列触发器会自动防止函数多次处理队列消息;函数不必编写为幂等的。但是,如果您想确保即使有多个主机 Web 应用程序实例,也只有一个函数实例运行,则可以使用 Singleton 属性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)