【问题标题】:Best practice for initiating Azure Function from another Azure Function从另一个 Azure Function 启动 Azure Function 的最佳实践
【发布时间】:2017-08-01 15:14:07
【问题描述】:

我有一个场景,我有 2 个函数,比如说函数 A 和函数 B。

目前,函数 A 和函数 B 都具有相同的记录失败活动的逻辑,其中元数据记录到表存储和 JSON 记录到 Blob 存储。

编辑 --> 函数 A 和函数 B 位于两个不同的函数应用程序中(有意)。功能 A 属于消费计划,功能 B 属于应用服务计划。

第一个问题 - 创建一个函数 C 并从 A 和 B 获取失败的活动日志记录逻辑并将其放入 C 中是否有意义?

这消除了代码重复,逻辑集中在一个更易于管理的地方。

第二个问题 - 从 A 和 B 调用函数 C 的最佳方法是什么?

我读过here,最好使用存储队列或服务总线来实现函数之间的交叉通信。我遇到的问题是 - 在大多数情况下,我需要存储的 JSON 将超过 256KB,因此我无法将其放入队列中以触发函数。

那么,函数 C 是否可以作为 HTTP 触发器,并且我发送一个请求,其中包含通过 HTTP 从函数 A 和 B 记录所需的所有相关信息?

有什么理由不这样做吗?

非常感谢。

【问题讨论】:

  • 我认为代码重复是您要解决的主要问题。希望这篇文章对您有所帮助.. zimmergren.net/…
  • @Venky 谢谢,但函数 A 和函数 B 位于两个不同的函数应用程序中(预期)。功能 A 属于消费计划,功能 B 属于应用服务计划。抱歉,我没有提及,将编辑我的问题。
  • 问题太宽泛/不清楚/几个问题合二为一

标签: c# azure http azure-functions


【解决方案1】:

为了将来参考(以及那些可能通过网络搜索找到这个问题的人),我们为 Azure Functions 构建了一个新的 Durable Functions 扩展,它允许从另一个函数调用一个函数。您的具体问题可能会编码如下:

public static async Task<object> Run(DurableOrchestrationContext ctx)
{
    try
    {
        var result = await ctx.CallActivityAsync<object>("FunctionA");
        var y = await ctx.CallActivityAsync<object>("FunctionB", result);
        return y;
    }
    catch (Exception e)
    {
        // error handling/compensation goes here
        await ctx.CallActivityAsync<object>("FunctionC", e);
        return null;
    }
}

FunctionAFunctionBactivity functions,它们可以存在于同一个函数应用中。上面安排它们的函数是orchestrator function。支持消费和应用服务计划。

在幕后,CallActivityAsync 方法通过 Azure 存储队列发送消息以按名称触发指定的函数。通过自动切换到队列和 Blob 的组合来支持大型消息,以确保它们能够可靠地传递。

然而,一个重要的限制是 FunctionA 和 FunctionB 必须在同一个函数应用中定义。因此,这与您的问题不完全匹配。但是,对于那些可以将其功能保留在同一个函数应用中的人来说,这是一个很好的解决方案。

官方文档https://docs.microsoft.com/en-us/azure/azure-functions/durable-functions-overview

GitHubhttps://github.com/Azure/azure-functions-durable-extension

【讨论】:

  • 持久的 Azure Functions 需要更多的爱,因为它们非常棒:)。我记得几天前读过它,并想用它来回答这个问题,但不幸的是我找不到它(我的 Bing-foo/Google-foo 让我失望了)。我什至查看了 Azure App Service 博客,但没有找到与此相关的条目。我的建议是让它更容易被发现。
  • 非常感谢,克里斯。这看起来与我试图解释的内容一致。我会玩的!
  • @GauravMantri 谢谢!在我们让它进入更稳定的状态(稳定,这意味着我们不需要引入更多的破坏性更改)之前,我们不会对此做太多的 PR。请继续关注公开测试版。 :)
  • 那么,函数1会等到函数2完成吗?我尝试做类似的事情,但如果我的长时间运行过程需要很长时间,webhook(初始事件)会抱怨。我实际上想“触发并忘记下一个函数(正在执行长时间运行的过程)”,可能吗?
  • @CularBytes 是的,函数 1 将等待函数 2 完成,但以不受函数主机超时影响的方式异步进行。您也无需为消费计划中的“等待”时间付费。然而,并不存在真正的“即发即弃”语义。只有在所有活动功能都执行完毕后,编排器功能才会完成。
【解决方案2】:

函数链接的推荐模式是使用队列(SB/存储队列),其中一个函数输出到另一个函数的输入队列,其中包含要处理的有效负载的消息。

这使您的功能保持小型、快速和解耦,同时利用所有现有逻辑进行配置、扩展和故障处理。

【讨论】:

  • 好叫这个,它叫做管道和过滤器模式:docs.microsoft.com/en-us/azure/architecture/patterns/…
  • 谢谢法比奥。这很好,但我的消息将超过服务总线和存储队列的最大消息大小。
  • 为此,您确实需要采用类似于 Chris 在他的回答中提到的模式并将实际有效负载存储在其他地方(例如 blob 存储),并且您的队列消息将只是一个带有引用该 blob。您还可以利用我们的 blob 触发器为您简化操作。
【解决方案3】:

我想你可能想多了。是的,您可以从函数中调用函数,但这很昂贵,因为您必须跨越进程边界,尤其是对于日志记录等潜在的高容量。

我所做的是在程序集中构建共享逻辑,然后上传程序集并从您的函数中调用它。 Here is a blog post that shows you how.

Here is a related post on logging in Azure functions as you may hit the same challenges.

【讨论】:

  • 请查看我更新的问题。函数位于两个不同的函数应用程序中。
  • 没关系。在您的 CI 流程中将相同的程序集部署到两者,或者您甚至可以将其添加到本地 Nuget。
猜你喜欢
  • 1970-01-01
  • 2019-07-14
  • 1970-01-01
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 2019-11-12
  • 2012-02-23
  • 2022-01-18
相关资源
最近更新 更多