Azure Function 中 Blob 上传和删除的事件网格间歇性触发问题

问题描述 投票:0回答:1

我正在使用事件网格订阅来触发 Azure 函数,以处理 Azure Blob 存储中的 Blob 上传和删除。但是,我遇到了间歇性问题,触发器没有持续触发。我的意思是触发器没有在应该触发的时候触发。例如,如果我上传一个文件并在上午 10 点删除它,触发器会正常工作,并执行相应的操作。但是,如果我在上午 11 点执行相同的上传和删除操作,触发器不会触发,并且不会执行任何操作。

设置:

存储帐户(事件网格)

事件网格订阅订阅了 Microsoft.Storage.BlobCreated 和 Microsoft.Storage.BlobDeleted 事件。

Azure 函数事件网格触发器

问题:问题是事件网格触发器不会在每次上传或删除 Blob 时触发。当触发器触发时,上传和删除操作都会正常工作。然而,触发器本身是不一致的。

采取的步骤:

订阅了 Microsoft.Storage.BlobCreated 和 Microsoft.Storage.BlobDeleted 事件。

实现了函数代码来处理不同的事件类型并执行必要的业务逻辑。

尽管如此设置,触发器并不会针对每个 Blob 上传或删除事件一致触发。

请求帮助:有人可以帮助我排查并解决用于 blob 上传和删除的事件网格触发器的这些间歇性问题吗?任何见解或指导将不胜感激。

谢谢! 在此输入图片描述 在此输入图片描述

const { app } = require('@azure/functions');

const { BlobServiceClient, StorageSharedKeyCredential } = require('@azure/storage-blob');

const { SearchClient, AzureKeyCredential } = require('@azure/search-documents');

const pdf = require('pdf-parse');

const path = require('path');

// Azure Blob Storage configuration

const accountName = "";

const accountKey = "";

const containerName = 'content';

// Azure Cognitive Search configuration

const searchServiceName = "";

const indexName = "demoindex2";

const apiKey = "";

const blobServiceClient = new BlobServiceClient(

    `https://${accountName}.blob.core.windows.net`,

    new StorageSharedKeyCredential(accountName, accountKey)

);

const containerClient = blobServiceClient.getContainerClient(containerName);

const searchClient = new SearchClient(

    `https://${searchServiceName}.search.windows.net/`,

    indexName,

    new AzureKeyCredential(apiKey)

);

async function indexBlob(blobName) {

    try {

        const blobClient = containerClient.getBlobClient(blobName);

        const downloadResponse = await blobClient.download();

        const encodedName = Buffer.from(blobName).toString('base64');

        const properties = await blobClient.getProperties();

        const pdfBuffer = await streamToBuffer(downloadResponse.readableStreamBody);

        const pdfText = await pdf(pdfBuffer);

        const blobContent = pdfText.text;

        const document = {

            id: encodedName,

            content: blobContent,

            metadata_storage_content_type: properties.contentType || null,

            metadata_storage_size: properties.contentLength || null,

            metadata_storage_last_modified: properties.lastModified ? new Date(properties.lastModified).toISOString() : null,

            metadata_storage_content_md5: properties.contentMD5 ? Buffer.from(properties.contentMD5).toString('base64') : null,

            metadata_storage_name: blobName,

            metadata_storage_path: blobClient.url,

            metadata_storage_file_extension: path.extname(blobName),

            metadata_content_type: properties.contentType || null,

            metadata_language: null,

            metadata_author: null,

            metadata_creation_date: properties.creationTime ? new Date(properties.creationTime).toISOString() : null,

        };

        await searchClient.uploadDocuments([document]);

        console.log(`Document "${document.id}" has been indexed`);

    } catch (error) {

        console.error(`Error indexing document: ${error}`);

    }

}

async function deleteDocument(blobName) {

    try {

        const encodedName = Buffer.from(blobName).toString('base64');

        await searchClient.deleteDocuments([{ id: encodedName }]);

        console.log(`Document "${encodedName}" has been deleted from the index`);

    } catch (error) {

        console.error(`Error deleting document from the index: ${error}`);

    }

}

app.eventGrid('process-event-grid', {

    handler: async (context, eventGridEvent) => {

        try {

            const event = eventGridEvent.eventType;

            const blobUrl = eventGridEvent.data?.url;

            

            if (!blobUrl) {

                console.error("Event data does not contain 'url':", eventGridEvent);

                return;

            }

            

            const blobName = blobUrl.substring(blobUrl.lastIndexOf('/') + 1);

            if (event === 'Microsoft.Storage.BlobCreated') {

                console.log(`Blob created: ${blobName}`);

                await indexBlob(blobName);

            } else if (event === 'Microsoft.Storage.BlobDeleted') {

                console.log(`Blob deleted: ${blobName}`);

                await deleteDocument(blobName);

            } else {

                console.log(`Unhandled event type: ${event}`);

            }

        } catch (error) {

            console.error(`Error processing event: ${error}`, eventGridEvent);

        }

    }

});

async function streamToBuffer(readableStream) {

    return new Promise((resolve, reject) => {

        const chunks = [];

        readableStream.on("data", (data) => {

            chunks.push(data instanceof Buffer ? data : Buffer.from(data));

        });

        readableStream.on("end", () => {

            resolve(Buffer.concat(chunks));

        });

        readableStream.on("error", reject);

    });

}
azure azure-functions azure-blob-storage
1个回答
0
投票

问题是事件网格触发器不会在每次上传或删除 Blob 时触发。

  • 如果没有进程正在运行或没有触发器被触发,函数在一段时间后进入空闲状态。确保触发事件之间没有时间间隔。
  • 在消费和高级计划中,没有选项可以让功能应用程序始终保持打开状态。但是,在专用应用程序服务计划中,
    configuration>>general settings>>Always On
    中有一个可以启用的选项。

enter image description here

我正在使用一个简单的事件绑定器代码,该代码会在上传或删除 blob 时触发。

const { app } = require('@azure/functions');

app.eventGrid('eventGridTrigger1', {
    handler: (event, context) => {
        context.log('Event grid function processed event:', event);
    }
});

主机.Json

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}

enter image description here

我已经在 azure 存储事件中配置了函数和事件网格端点,如下所示:

enter image description here

enter image description here

当我上传并删除存储容器中的文档时,功能成功触发。检查下面:

输出:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.