我有一个Azure耐用功能,可与也托管在Azure中的PostgreSQL数据库进行交互。
PostgreSQL数据库的连接限制为50,此外,我的连接字符串将连接池的大小限制为40,从而为超级用户/管理员连接留出了空间。
尽管如此,在某些负载下我还是得到了错误
53300:剩余的连接插槽保留用于非复制超级用户连接
Microsoft的这份文档似乎很相关,但是似乎我不能制作一个静态客户端,并且正如我提到的那样,
因为您仍然可以用尽连接,所以应该优化与数据库的连接。
我有这种方法
private IDbConnection GetConnection()
{
return new NpgsqlConnection(Environment.GetEnvironmentVariable("PostgresConnectionString"));
}
Run Code Online (Sandbox Code Playgroud)
当我想与PostgreSQL交互时,我喜欢这样
using (var connection = GetConnection())
{
connection.Open();
return await connection.QuerySingleAsync<int>(settings.Query().Insert, settings);
}
Run Code Online (Sandbox Code Playgroud)
因此,我正在创建(和布置)许多NpgsqlConnection对象,但是根据此,这应该没问题,因为连接池是在后台处理的。但是有关Azure Functions的某些信息可能会使这种想法无效。
我注意到我最终有很多空闲连接(来自pgAdmin):
基于此,我尝试摆弄Npgsql连接参数(如Connection Idle Lifetime,,Timeout和)Pooling,但连接过多的问题似乎一直持续到某种程度。另外,我尝试限制并发编排器和活动函数的数量(请参阅本文档),但这似乎在一定程度上破坏了Azure函数具有可伸缩性的目的。它确实有帮助-我得到的太多连接错误更少了。据推测,如果我继续用较小的数字进行测试,我什至可以消除它,但是,再次看来,这很不合理,并且可能还有另一种解决方案。
如何在不增加连接数的情况下将PostgreSQL与Azure函数一起使用?
postgresql azure npgsql azure-functions azure-durable-functions
我试图Non-Deterministic workflow detected: TaskScheduledEvent: 0 TaskScheduled ...在我们的持久功能项目中追踪一些偶然的错误。这种情况很少见(10,000 次左右的情况下为 3 次)。
将协调器代码与此处记录的约束进行比较时,我们使用了一种我不清楚的模式。为了使编排器代码更干净/可读,我们使用一些私有的异步辅助函数来进行实际CallActivityWithRetryAsync调用,有时包装在异常处理程序中以进行日志记录,然后await在此辅助函数上使用主编排器函数。
类似这个简化示例的东西:
[FunctionName(Name)]
public static async Task RunPipelineAsync(
[OrchestrationTrigger]
DurableOrchestrationContextBase context,
ILogger log)
{
// other steps
await WriteStatusAsync(context, "Started", log);
// other steps
await WriteStatusAsync(context, "Completed", log);
}
private static async Task WriteStatusAsync(
DurableOrchestrationContextBase context,
string status,
ILogger log
)
{
log.LogInformationOnce(context, "log message...");
try
{
var request = new WriteAppDocumentStatusRequest
{
//...
};
await context.CallActivityWithRetryAsync(
"WriteAppStatus",
RetryPolicy,
request
);
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试 Azure Durable 功能。目前,我在InvalidOperationException调用活动后进入编排功能。它抱怨检测到多线程执行。如果协调器功能之前从不受支持的异步回调中恢复,则可能会发生这种情况。
有没有人遇到过这样的问题?我做错了什么?完整代码可以在GitHub上找到
这是编排函数中的一行:
var res = await ctx.CallActivityAsync<int>("LengthCheck", "inputData");
Run Code Online (Sandbox Code Playgroud)
该LengthCheckactivitiy功能是:
[FunctionName("LengthCheck")]
public static Task<int> Calc([ActivityTrigger] string input)
{
var task = Task.Delay(TimeSpan.FromSeconds(5));
task.Wait();
return Task.FromResult(input.Length);
}
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪是:
ac6fd5cdd07a4dc9b2577657d65c4f27:函数“InpaintOrchestration(Orchestrator)”,版本“”失败并出现错误。原因:System.InvalidOperationException:检测到多线程执行。如果协调器功能之前从不受支持的异步回调中恢复,则可能会发生这种情况。
在 Microsoft.Azure.WebJobs.DurableOrchestrationContext.ThrowIfInvalidAccess()
在 Microsoft.Azure.WebJobs.DurableOrchestrationContext.d__47`1.MoveNext()
从上一个抛出异常的位置开始的堆栈跟踪结束
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
在 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
我有一个 Durable Orchestration,可根据请求扩展和缩减 Azure Cosmos DB 吞吐量。放大是通过 HTTP 触发的,缩小是稍后通过Durable Timer发生的,该定时器应该在当前或下一小时结束时唤醒 Azure 函数。这是 Orchestrator 功能:
public static class CosmosDbScalerOrchestrator
{
[FunctionName(nameof(CosmosDbScalerOrchestrator))]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var cosmosDbScalerRequestString = context.GetInput<string>();
var didScale = await context.CallActivityAsync<bool>(nameof(ScaleUpActivityTrigger), cosmosDbScalerRequestString);
if (didScale)
{
var minutesUntilLastMinuteOfHour = 59 - context.CurrentUtcDateTime.Minute;
var minutesUntilScaleDown = minutesUntilLastMinuteOfHour < 15
? minutesUntilLastMinuteOfHour + 60
: minutesUntilLastMinuteOfHour;
var timeUntilScaleDown = context.CurrentUtcDateTime.Add(TimeSpan.FromMinutes(minutesUntilScaleDown));
await context.CreateTimer(timeUntilScaleDown, CancellationToken.None);
await context.CallActivityAsync(nameof(ScaleDownActivityTrigger), cosmosDbScalerRequestString);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是ScaleUpActivityTrigger: …
我制作了一个应用程序,它使用 azure 函数持久扇出策略,通过向我们自己的内部 API 发送 http 请求来对数据库进行并行查询和更新。
我发现扇出策略比使用TPL 库并在普通 .net Core Web 应用程序上以这种方式进行并行性要慢得多。它不仅慢了,而且慢了大约 20 倍。130 次更新需要 10 分钟,而我为速度比较而制作的 .net core 3.1 应用程序执行完全相同的操作,在 0.5 分钟内完成 130 次更新,而且计划要低得多。
我知道由于耐用的框架基础设施(与存储帐户等进行通信)而存在延迟,但我不明白这种速度差异是如何正常的。每个单独的更新都发生在 ActivityTrigger 函数中,编排器负责收集所有必要的更新并将它们放入 Task.WhenAll() 调用中,就像 Microsoft 文档中的示例一样。
我在这里做错了什么吗?这个业务场景可能不兼容这个技术吗?该代码似乎工作正常并且并行性有效,只是比 .net core 应用程序慢很多。另一件值得一提的是,当函数打开第二个实例时(由于它处于消耗计划中并自然打开第二个实例来处理重负载,或者它处于应用程序服务计划中并且我手动打开一个实例),它甚至会发生尽管 CPU 负载在两个实例中以某种方式平衡,但速度较慢。我怀疑这可能是由于两个实例之间的天蓝色队列通信造成的额外延迟,但我不完全确定。
最后一个细节是,该应用程序还有一个 TimeTrigger,它每隔一分钟在数据库中进行一次简单的选择(甚至不会消耗 CPU 资源,但它可能会影响性能)。
我已经在高级计划、消费计划和应用程序服务计划中尝试过该功能应用程序,无论该计划有多大,它似乎都会在 10 分钟内达到 130 次更新。
我使用了 v2 azure 函数(持久函数)和调用服务的自定义 dll(.net core 2.2),但出现以下异常:
无法加载文件或程序集“System.Private.ServiceModel,版本=4.1.2.4,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a”
在调试过程中,我无法进入该方法,并且在不让我进入该方法的情况下抛出异常,我不知道究竟是什么试图访问该库。将 .nuget 中的包手动放入 bin 文件夹中不起作用,奇怪的是,如果使用示例 C# 函数运行相同的代码,它会起作用。
c# azureportal asp.net-core azure-functions azure-durable-functions
我正在尝试使用 SpecFlow 和 MSTest 测试(集成测试)我的 Azure Durable Function v3。
函数用 DI 和 Startup 类初始化:
[assembly: FunctionsStartup(typeof(Startup))]
namespace MyNamespace.Functions
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
ConfigureServices(builder.Services);
}
...
Run Code Online (Sandbox Code Playgroud)
Orchestrator 入口点由 HTTP 端点触发:
public class Function1
{
[FunctionName(nameof(Function1))]
public async Task<IActionResult> DoYourJob(
[HttpTrigger(AuthorizationLevel.Anonymous, methods: "post", Route = "api/routes/function1")] HttpRequestMessage httpRequest,
[DurableClient] IDurableOrchestrationClient starter)
{
...
Run Code Online (Sandbox Code Playgroud)
我的 IntegrationTest 构造函数初始化 Az 函数HostBuilder(感谢这篇文章):
[Binding]
public sealed class Function1StepDefinitions
{
private readonly IHost _host;
private …Run Code Online (Sandbox Code Playgroud) integration-testing azure .net-core azure-functions azure-durable-functions
我想按需处理数百万条记录,大约需要 2-3 个小时来处理。我想要无服务器,这就是为什么尝试持久功能(第一次)。我想检查一下,我可以运行持久函数多长时间,所以我创建了 3 个函数
我的 DurableFunction 正在运行并在 Application Insights 中发出过去 5 天的日志,根据我的代码,它需要 15 天才能完成。
我想知道如何手动停止 Orchestrator 功能?
我可以在 ApplicationInsights 请求表中看到数千个单次执行条目,有没有办法检查后端运行了多少个 DurableFunction?以及单次执行需要多少时间?
我可以在“DurableFunctionHubInstance”表中看到一些有关协调器功能的信息,但正如 MS 建议的那样,不要依赖表。
我有一个用例,要求我启动一些 Azure Durable Functions,而不关心其结果,我想知道我的方法是否正确。
这是我所处的场景:
A使用一个HttpTriggerB使用一个ActivityTrigger这是我的工作流程:
A被调用,需要做一些业务逻辑A调用时运行此任务。A需要尽快返回,这就是为什么我等不及后台任务完成BA返回时处理此后台任务我在网上找到的所有耐用功能示例都显示如下内容:
await starter.StartNewAsync("BackgroundDurableFunction", data)
Run Code Online (Sandbox Code Playgroud)
我的问题是,我不想要await持久功能,但我需要它在后台运行并执行其操作(主要是网络 I/O)。
为了避免等待这个持久功能,我最终采用了以下解决方法:
Task.Factory.StartNew(() => starter.StartNewAsync("BackgroundDurableFunction", data));
Run Code Online (Sandbox Code Playgroud)
这似乎工作得很好,因为我不需要await任何东西,但在阅读了Task.Factory.StartNew 的危险之后,我有点担心这可能是一个危险的解决方案。
所以,问题是:启动持久功能并让它在后台运行而不关心其结果(并且没有关于不等待任务的警告)的正确方法是什么?
据我了解,Azure Durable 函数使用一系列 Azure 存储队列和表来管理编排和状态。
最大活动响应是否会受到队列或存储属性限制 (64 Kb) 的限制?
活动结果到底存储在哪里?
.net c# azure-storage azure-functions azure-durable-functions