如何在Azure WebJob函数中执行异步 [英] How to do Async in Azure WebJob function

查看:99
本文介绍了如何在Azure WebJob函数中执行异步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个异步方法,该方法从服务器获取api数据.当我在本地计算机上的控制台应用程序中运行此代码时,它以很高的速度运行,每分钟在异步函数中推送数百个http调用.但是,当我将相同的代码从Azure WebJob队列消息中触发时,它似乎是同步运行的,而且我的电话号码也会爬行-我确定我的方法中缺少一些简单的东西-感谢您提供任何帮助.

I have an async method that gets api data from a server. When I run this code on my local machine, in a console app, it performs at high speed, pushing through a few hundred http calls in the async function per minute. When I put the same code to be triggered from an Azure WebJob queue message however, it seems to operate synchronously and my numbers crawl - I'm sure I am missing something simple in my approach - any assistance appreciated.

(1).. WebJob函数,用于侦听队列中的消息并针对收到的消息启动api get进程:

(1) .. WebJob function that listens for a message on queue and kicks off the api get process on message received:

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的类以异步模式快速运行...

(2) the class that outside azure works in async mode at speed...

 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().等待将阻止当前线程.

First because your triggered function is async, you should use await rather than .Wait(). Wait will block the current thread.

public static async Task ProcessQueueMessage([QueueTrigger("myqueue")] string message, TextWriter log)
{
    var getAPIData = new GetData();
    await getAPIData.DoIt(message);
    log.WriteLine("*** done: " + message);
}

无论如何,您都可以从

Anyway you'll be able to find usefull information from the documentation

并行执行

如果您有多个功能在不同的队列上侦听,则SDK将在同时接收消息时并行调用它们.

If you have multiple functions listening on different queues, the SDK will call them in parallel when messages are received simultaneously.

当为单个队列接收到多个消息时,情况也是如此.默认情况下,SDK一次获取一批16个队列消息,并执行并行处理它们的功能.

The same is true when multiple messages are received for a single queue. By default, the SDK gets a batch of 16 queue messages at a time and executes the function that processes them in parallel. The batch size is configurable. When the number being processed gets down to half of the batch size, the SDK gets another batch and starts processing those messages. Therefore the maximum number of concurrent messages being processed per function is one and a half times the batch size. This limit applies separately to each function that has a QueueTrigger attribute.

以下是配置批处理大小的示例代码:

Here is a sample code to configure the batch size:

var config = new JobHostConfiguration();
config.Queues.BatchSize = 50;
var host = new JobHost(config);
host.RunAndBlock();

但是,同时运行太多线程并不总是一个好选择,这可能会导致性能下降.

However, it is not always a good option to have too many threads running at the same time and could lead to bad performance.

另一种选择是扩展您的网络作业:

Another option is to scale out your webjob:

多个实例

如果您的Web应用程序在多个实例上运行,则连续的WebJob将在每台计算机上运行,​​并且每台计算机将等待触发器并尝试运行功能. WebJobs SDK队列触发器会自动阻止函数多次处理队列消息.函数不必写为幂等的.但是,如果即使在主机Web应用程序有多个实例的情况下也要确保仅运行一个功能实例,则可以使用Singleton属性.

if your web app runs on multiple instances, a continuous WebJob runs on each machine, and each machine will wait for triggers and attempt to run functions. The WebJobs SDK queue trigger automatically prevents a function from processing a queue message multiple times; functions do not have to be written to be idempotent. However, if you want to ensure that only one instance of a function runs even when there are multiple instances of the host web app, you can use the Singleton attribute.

这篇关于如何在Azure WebJob函数中执行异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆