我正在使用事件网格订阅来触发 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);
});
}
问题是事件网格触发器不会在每次上传或删除 Blob 时触发。
configuration>>general settings>>Always On
中有一个可以启用的选项。我正在使用一个简单的事件绑定器代码,该代码会在上传或删除 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)"
}
}
我已经在 azure 存储事件中配置了函数和事件网格端点,如下所示:
当我上传并删除存储容器中的文档时,功能成功触发。检查下面:
输出: