Azure Functions 并不总是在后续请求中获取具有输入 DocumentDB 绑定的文档
Azure Function does not always fetch document with input DocumentDB binding on subsequent requests
我的场景:收到一条来自 Azure 存储队列的消息,我想在 DocumentDB 中创建或更新文档
- 我把DocumentDB的一致性设置为强,这样就可以了
保证文档已更新
- 我用的是Singleton/Listener,
这样一次只处理一个队列条目
这是我的代码:
function.json
{
"disabled": false,
"bindings": [
{
"name": "updateEntry",
"type": "queueTrigger",
"direction": "in",
"queueName": "update-log",
"connection": "AzureWebJobsStorage"
},
{
"type": "documentDB",
"name": "inputDocument",
"databaseName": "logging",
"collectionName": "messages",
"id": "{id}",
"connection": "documentDB",
"direction": "in"
},
{
"type": "documentDB",
"name": "outputDocument",
"databaseName": "logging",
"collectionName": "messages",
"createIfNotExists": true,
"connection": "documentDB",
"direction": "out"
}
]
}
run.csx
#r "Newtonsoft.Json"
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
[Singleton(Mode = SingletonMode.Listener)]
public static void Run(UpdateEntryType updateEntry, TraceWriter log, DocumentType inputDocument, out DocumentType outputDocument)
{
log.Info($"update entry:{updateEntry.id} {updateEntry.created} {updateEntry.Event.ToString()}");
outputDocument = new DocumentType();
outputDocument.Events = new List<JObject>();
if (inputDocument == null)
{
outputDocument.id = updateEntry.id;
outputDocument.created = updateEntry.created;
}
else
{
log.Info($"input document:{inputDocument.id} {inputDocument.created} {inputDocument.Events.Count}");
outputDocument.id = inputDocument.id;
outputDocument.created = updateEntry.created.CompareTo(inputDocument.created) < 0 ? updateEntry.created : inputDocument.created;
outputDocument.Events.AddRange(inputDocument.Events);
}
outputDocument.Events.Add(updateEntry.Event);
log.Info($"output document:{outputDocument.id} {outputDocument.created} {outputDocument.Events.Count}");
}
public class UpdateEntryType
{
public string id { get; set; }
public string created { get; set; }
public JObject Event { get; set; }
}
public class DocumentType
{
public string id { get; set; }
public string created { get; set; }
public List<JObject> Events { get; set; }
}
我的问题:大多数情况下,实际存在的文档是用 id 找到的,因此会更新 - 但至少有 5% 的时间不会
我的问题(在我打开案例之前@MSFT 支持):
我错过了什么?这是正确的方法还是注定要失败?
not for at least 5% of the time
根据我的经验,如果它是 专用 计划,我们需要为我们的 Function App 打开 Always On 设置。
The Function runtime will go idle after a few minutes of inactivity, so only HTTP triggers will actually "wake up" your functions. This is similar to how WebJobs must have Always On enabled.
关于Consumption Plan & Dedicated App Service Plan以及如何设置appsetting的详细信息,请参考Enable Always On when running on dedicated App Service Plan .
使用 Queue batchSize 1 而不是 SingletonMode.Listener 使问题消失。
hosts.json
{
"queues": {
"batchSize": 1
}
我的场景:收到一条来自 Azure 存储队列的消息,我想在 DocumentDB 中创建或更新文档
- 我把DocumentDB的一致性设置为强,这样就可以了 保证文档已更新
- 我用的是Singleton/Listener, 这样一次只处理一个队列条目
这是我的代码:
function.json
{
"disabled": false,
"bindings": [
{
"name": "updateEntry",
"type": "queueTrigger",
"direction": "in",
"queueName": "update-log",
"connection": "AzureWebJobsStorage"
},
{
"type": "documentDB",
"name": "inputDocument",
"databaseName": "logging",
"collectionName": "messages",
"id": "{id}",
"connection": "documentDB",
"direction": "in"
},
{
"type": "documentDB",
"name": "outputDocument",
"databaseName": "logging",
"collectionName": "messages",
"createIfNotExists": true,
"connection": "documentDB",
"direction": "out"
}
]
}
run.csx
#r "Newtonsoft.Json"
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
[Singleton(Mode = SingletonMode.Listener)]
public static void Run(UpdateEntryType updateEntry, TraceWriter log, DocumentType inputDocument, out DocumentType outputDocument)
{
log.Info($"update entry:{updateEntry.id} {updateEntry.created} {updateEntry.Event.ToString()}");
outputDocument = new DocumentType();
outputDocument.Events = new List<JObject>();
if (inputDocument == null)
{
outputDocument.id = updateEntry.id;
outputDocument.created = updateEntry.created;
}
else
{
log.Info($"input document:{inputDocument.id} {inputDocument.created} {inputDocument.Events.Count}");
outputDocument.id = inputDocument.id;
outputDocument.created = updateEntry.created.CompareTo(inputDocument.created) < 0 ? updateEntry.created : inputDocument.created;
outputDocument.Events.AddRange(inputDocument.Events);
}
outputDocument.Events.Add(updateEntry.Event);
log.Info($"output document:{outputDocument.id} {outputDocument.created} {outputDocument.Events.Count}");
}
public class UpdateEntryType
{
public string id { get; set; }
public string created { get; set; }
public JObject Event { get; set; }
}
public class DocumentType
{
public string id { get; set; }
public string created { get; set; }
public List<JObject> Events { get; set; }
}
我的问题:大多数情况下,实际存在的文档是用 id 找到的,因此会更新 - 但至少有 5% 的时间不会
我的问题(在我打开案例之前@MSFT 支持): 我错过了什么?这是正确的方法还是注定要失败?
not for at least 5% of the time
根据我的经验,如果它是 专用 计划,我们需要为我们的 Function App 打开 Always On 设置。
The Function runtime will go idle after a few minutes of inactivity, so only HTTP triggers will actually "wake up" your functions. This is similar to how WebJobs must have Always On enabled.
关于Consumption Plan & Dedicated App Service Plan以及如何设置appsetting的详细信息,请参考Enable Always On when running on dedicated App Service Plan .
使用 Queue batchSize 1 而不是 SingletonMode.Listener 使问题消失。
hosts.json
{
"queues": {
"batchSize": 1
}