【问题标题】:Pattern match blob name to function variables with input binding使用输入绑定将 blob 名称模式匹配到函数变量
【发布时间】:2018-10-12 02:58:12
【问题描述】:

根据Azure Blob storage bindings for Azure Functions documentation,在配置 blob 触发器时,您可以利用 blob 名称上的模式匹配来将部分路径映射到函数中的变量,例如。

[FunctionName("BlobTriggered")]        
public static void BlobTriggered(
    [BlobTrigger("myContainer/{name}.{extension}")] Stream myBlob,
    string name,
    string extension,
    TraceWriter log)
{
    // Given the blob path "myContainer/myBlob.png":
    // name == "myBlob"
    // extension == "png"
}

我已经对此进行了测试,它非常适合我的用例,但是由于BlobTrigger 触发的大量延迟(通常超过 5 分钟),这不是一个可行的选择。因此,我希望根据Azure Functions scale and hosting documentation 的建议将此设置为事件网格触发器:

当您在消耗计划中使用 blob 触发器时,处理新 blob 最多可能会延迟 10 分钟。当函数应用空闲时会发生此延迟。函数应用运行后,会立即处理 blob。要避免这种冷启动延迟,请使用启用 Always On 的应用服务计划,或使用事件网格触发器。

有没有办法从输入绑定而不是触发器中获得相同的模式匹配行为?

在我的具体情况下,我为 blob 创建设置了一个 EventGrid 订阅,它运行一个协调器函数,调用一个活动函数来读取和解析 blob:

[FunctionName("NewBlobCreated")]
public static async Task NewBlobCreated(
    [EventGridTrigger]EventGridEvent eventGridEvent,
    [OrchestrationClient]DurableOrchestrationClient starter,
    ILogger log)
{
    // Start our orchestrator function to read the file
    string instanceId = await starter.StartNewAsync(
        "OrchestrateBlobReader",
        eventGridEvent);
}

// Orchestrator function
[FunctionName("OrchestrateBlobReader")]
public static async Task OrchestrateBlobReader(
    [OrchestrationTrigger] DurableOrchestrationContext context,
    ILogger log)
{
    var eventGridEvent = context.GetInput<EventGridEvent>();
    var parsedBlob = await context.CallActivityAsync<string>("ReadBlob", eventGridEvent.Data);        
    ...
}

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    ILogger log)
{
    using (var blobStream = await blob.OpenReadAsync())
    {
        // Blob is able to be read from blobStream here
        ...
    }
}

理想情况下,我希望我的 ReadBlob 函数的行为类似于上面第一个示例中的 BlobTriggered 函数,以执行以下操作:

[FunctionName("ReadBlob")]
public static async Task<string> ReadBlob(
    [ActivityTrigger] JObject eventData,
    [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
    string extension,
    ILogger log)
{
    if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
    { ... }
    else if (extension.Equals("png", StringComparison.OrdinalIgnoreCase)
    { ... }
    else
    { ... }
}

问题是我看不到任何将extension 参数绑定到Blob 输入绑定的方法,就像我为BlobTrigger 所做的那样——特别是路径绑定到@ 提供的url 987654333@ 形式为eventDataJObject

在这种情况下是否可以实现相同的模式匹配功能?还是我必须自己解析路径字符串以提取相关信息?

【问题讨论】:

    标签: c# azure-functions azure-blob-storage


    【解决方案1】:

    在查看了 blob 触发器绑定的源代码后,我的“快速而肮脏”的解决方案是利用底层的 BindingTemplateSource class,触发器用于将路径和模式映射到字典。

    更新ReadBlob函数如下:

    // So we can access the BindingTemplateSource class
    using Microsoft.Azure.WebJobs.Host.Bindings.Path;
    
    [FunctionName("ReadBlob")]
    public static async Task<string> ReadBlob(
        [ActivityTrigger] JObject eventData,
        [Blob("{data.url}", FileAccess.Read)]CloudBlockBlob blob,
        ILogger log)
    {
        // Define the pattern to match
        var blobPattern = "myContainer/{name}.{extension}";
        // Create a BindingTemplateSource from the pattern string
        var patternTemplate = BindingTemplateSource.FromString(blobPattern);
        // Use this BindingTemplateSource to create the binding data
        // This returns a IReadOnlyDictionary<string, object> with the parameters mapped
        var parameters = patternTemplate.CreateBindingData($"{blob.Container.Name}/{blob.Name}");
        // Assuming blob path was "myContainer/myBlob.png":
        // Parameters are objects so we need to ToString() them
        var name = parameters["name"].ToString(); // name == "myBlob"
        var extension = parameters["extension"].ToString(); // extension == "png"
    
        if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
        { ... }
        else if (extension.Equals("png", StringComparison.OrdinalIgnoreCase))
        { 
            // This executes now!
        }
        else
        { ... }
    }
    

    然后,此功能可能会被包装在 custom binding 中,其中参数映射到函数上的输出绑定,就像 BlobTrigger 为最优雅的解决方案所做的那样,但是像这样将其破解到函数中可以实现我所需要的短期内

    【讨论】:

    • 感谢您的提醒。我不得不等待 48 小时超时,还没有机会回到这个状态
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    相关资源
    最近更新 更多