Azure Durable Functions 无法将 HttpRequestMessage 作为 OrchestrationClient.StartNewAsync 的输入传递

Posted

技术标签:

【中文标题】Azure Durable Functions 无法将 HttpRequestMessage 作为 OrchestrationClient.StartNewAsync 的输入传递【英文标题】:Azure Durable Functions can't Pass HttpRequestMessage as Input for OrchestrationClient.StartNewAsync 【发布时间】:2021-10-27 00:17:18 【问题描述】:

我正在尝试使用 Azure Durable Functions 将从 Http Triggered 函数接收到的 HttpRequestMessage 传递给另一个函数,如下所示:

[FunctionName("RequestHandler")]
public static async Task<IActionResult> Run(
                                [HttpTrigger(AuthorizationLevel.Anonymous, methods: new string[] "get", "post", Route = "RequestHandler")]
                                HttpRequestMessage request,
                                [DurableClient] IDurableOrchestrationClient orchestrationClient,
                                ILogger logger)


    var instanceId = await orchestrationClient.StartNewAsync<HttpRequestMessage>("MakeCallout", request);

    return new AcceptedResult("", "");

[FunctionName("MakeCallout")]
public static async Task RunOrchestrator(
                            [OrchestrationTrigger] IDurableOrchestrationContext context,
                            ILogger logger)

    HttpRequestMessage request = context.GetInput<HttpRequestMessage>();

但是我在运行时在 Newtonsoft 中遇到了一个异常,我想是因为持久函数使用 Json Seralization 在函数之间传递数据:

System.Private.CoreLib:执行函数时出现异常:RequestHandler。 Newtonsoft.Json:检测到类型为“Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine”的属性“Engine”的自引用循环。路径“Properties.HttpContext.ServiceScopeFactory.Root”。

有没有办法解决这个问题并在不将数据复制到另一个对象然后传入的情况下传递请求消息?

【问题讨论】:

HttpRequestMessage 传递给可期望的方法似乎充满了问题,特别是因为HttpRequestMessage 的内部可以包含各种风格的内容流。简而言之,您应该真正重新考虑您的问题,也许可以通过 MetaData 来创建 HttpRequestMessage,而后者又可以被序列化并创建 HttpRequestMessage。简而言之,持久功能将所有内容序列化到后备存储,然后再为您的客户重新补水。有些事情在技术上无法序列化,或者这样做似乎比它的价值更麻烦 【参考方案1】:

您应该将 JSON 可序列化的值传递给 Orchestrator。

[FunctionName("RequestHandler")]
public static async Task<IActionResult> Run(
                            [HttpTrigger(AuthorizationLevel.Anonymous, methods: new string[] "get", "post", Route = "RequestHandler")]
                            HttpRequestMessage request,
                            [DurableClient] IDurableOrchestrationClient orchestrationClient,
                            ILogger logger)

    dynamic data = await req.Content.ReadAsAsync<object>(); // if you have some json data in your http request's body. Or use req.Content.ReadAsStringAsync()

    var instanceId = await orchestrationClient.StartNewAsync("MakeCallout", data);

    return new AcceptedResult("", "");

【讨论】:

【参考方案2】:

您需要在 HTTP 函数中读取请求并将可序列化的对象发送到编排器。 在编排器中定义一个包含您需要的数据的类。 就像评论中提到的 TheGeneral 一样,序列化 HttpRequestMessage 很可能是不可能的。

为什么需要这个? 因为 Durable Functions 会将输入对象作为 JSON 存储在 Table Storage 中。 Orchestrator 函数从那里读取它。

【讨论】:

以上是关于Azure Durable Functions 无法将 HttpRequestMessage 作为 OrchestrationClient.StartNewAsync 的输入传递的主要内容,如果未能解决你的问题,请参考以下文章

Azure基础:何时使用Azure Functions无服务器计算(11)

Azure Durable 编排功能触发两次

在本地按需运行 Azure Functions

使用 Azure Function V2 Durable 函数时,ILogger 不记录到 Application Insights

Azure Durable Function Activity 似乎运行多次且未完成

Azure Functions - 限制并行执行