如何在Azure函数中调用另一个函数

Gal*_*let 20 azure azure-functions

我写了3个函数如下

  1. 在db中创建用户
  2. 从db获取用户
  3. 处理用户

在[3]函数中,我将调用[2]函数来获取用户使用Azure函数URL,如下所示: -

https://hdidownload.azurewebsites.net/api/getusers

有没有其他方法在没有完整路径的另一个Azure功能中调用Azure功能?

Mik*_*kov 14

函数应用程序中没有任何内置功能可以从其他函数调用一个HTTP函数,而无需实际进行HTTP调用.

对于简单的用例,我会坚持使用完整的URL进行调用.

有关更高级的工作流程,请查看Durable Functions,特别是Function Chaining.


Jul*_*iën 7

前面的所有答案都是有效的,但是,正如评论中提到的那样,今年早些时候(2018年第一季度/第二季度)引入了持久功能的概念。简而言之,耐用功能:

...使您可以在无服务器环境中编写有状态功能。该扩展为您管理状态,检查点并重新启动。

这实际上意味着您现在还可以将多个功能链接在一起。如果需要,它管理从功能A => B => C流出的状态。

通过将耐久功能扩展安装到您的功能应用程序中,它可以工作。这样,您就可以使用一些新的上下文绑定,例如在C#中,您可以执行以下操作(伪代码):

[FunctionName("ExpensiveDurableSequence")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] DurableOrchestrationTrigger context)
{
    var response = new List<Order>();

    // Call external function 1 
    var token = await context.CallActivityAsync<string>("GetDbToken", "i-am-root");

    // Call external function 2
    response.Add(await context.CallActivityAsync<IEnumerable<Order>>("GetOrdersFromDb", token));

    return response;
}

[FunctionName("GetDbToken")]
public static string GetDbToken([ActivityTrigger] string username)
{
    // do expensive remote api magic here
    return token;
}

[FunctionaName("GetOrdersFromDb")]
public static IEnumerable<Order> GetOrdersFromDb([ActivityTrigger] string apikey)
{
    // do expensive db magic here
    return orders;
}
Run Code Online (Sandbox Code Playgroud)

这里有一些不错的方面:

  • 主序列将两个附加功能串联在一起
  • 当执行外部功能时,主程序进入休眠状态。这意味着一旦外部功能忙于处理,您就不会再被计费

这样,您既可以依次运行多个功能(例如,功能链),也可以并行执行多个功能,然后等待所有功能完成(扇出/扇入)。

关于此的一些其他背景参考:


Jua*_*ell 7

我知道我们有 Durable 函数,但我像普通的静态方法一样调用我的函数并且它可以工作,这里有一个例子:

public static class HelloWorld
{
    [FunctionName("HelloWorld")]
    public static string Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log)
    {
        return "Hello World";
    }

}

public static class HelloWorldCall
{
    [FunctionName("HelloWorldCall")]
    public static string Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req, ILogger log)
    {
        var caller = HelloWorld.Run(req, log);
        return caller;
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 假设原始海报示例中的所有功能都在同一个功能应用程序中,是否有任何理由不应该对这个答案进行投票?我知道这个解决方案并不“持久”,因为如果任何步骤失败,都不会重试。但是,如果这不是要求,这不是一个有效的解决方案吗? (3认同)
  • 与此相关的一些问题 - 您拥有的任何监控(例如应用程序见解)不会将其视为第二个函数调用 - 您无法执行“即发即忘”,因为第二个函数在第一个函数内同步运行 - 任何所需的缩放都从 azure 中隐藏,因为第二个触发器永远不会被触发,因此放大规模将受到限制 (2认同)

Art*_*ous 5

您可以通过将第二个函数作为普通 C# 静态方法调用来直接执行此操作。

但在这种情况下,您将失去 Azure Functions 缩放和分发的好处(例如,根据服务器负载,您的第二个函数可能会从世界的不同地方调用)。

  1. 向另一个函数的公共 URL 发送 HTTP 请求
  2. 将消息放入 Azure 队列,让其他 Azure 函数处理它
  3. 使用持久函数

至于 C# 中的第一个选项,您可以这样做:

    static HttpClient client = new HttpClient();

    [FunctionName("RequestImageProcessing")]
    public static async Task RequestImageProcessing([HttpTrigger(WebHookType = "genericJson")]
        HttpRequestMessage req)
    {
            string anotherFunctionSecret = ConfigurationManager.AppSettings
                ["AnotherFunction_secret"];
            // anotherFunctionUri is another Azure Function's 
            // public URL, which should provide the secret code stored in app settings 
            // with key 'AnotherFunction_secret'
            Uri anotherFunctionUri = new Uri(req.RequestUri.AbsoluteUri.Replace(
                req.RequestUri.PathAndQuery, 
                $"/api/AnotherFunction?code={anotherFunctionSecret}"));

            var responseFromAnotherFunction = await client.GetAsync(anotherFunctionUri);
            // process the response

    }

    [FunctionName("AnotherFunction")]
    public static async Task AnotherFunction([HttpTrigger(WebHookType = "genericJson")]
    HttpRequestMessage req)
    {
        await Worker.DoWorkAsync();
    }
Run Code Online (Sandbox Code Playgroud)

此外,有时您需要第一个 Azure 函数首先返回 HTTP 响应,然后在后台执行某些操作,因此此解决方案不起作用。在这种情况下,选项 2 和 3 是合适的。

  • 这段代码可能有效,但作为一般原则,您应该避免为每次调用创建和处理 HttpClient 对象,而是为整个应用程序创建一个静态对象。根据 https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.8 (2认同)