Azure 函数主机死于 OutOfMemoryException,没有触发

Azure function host dies with OutOfMemoryException, without triggering

快速版:为什么我的功能主机在 5 分钟后没有做任何事情就自行杀死了?

我有一个 Azure 函数,它使用 nClam 扫描 blob 文件中的病毒。它似乎工作得很好,但突然间它会在触发任何斑点之前自行杀死它!它会在 5 分钟后关闭并出现 OutOfMemoryException:

[18/9/2019 10:33:33] Host initialized (405ms)
[18/9/2019 10:33:33] Host started (812ms)
[18/9/2019 10:33:33] Job host started
Hosting environment: Production
Content root path: D:\git\TopoAPI\Antivirus\bin\Debug\netcoreapp2.1
Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.
[18/9/2019 10:33:38] Host lock lease acquired by instance ID '000000000000000000000000C913FBA0'.
[18/9/2019 10:38:46] An unhandled exception has occurred. Host is shutting down.
[18/9/2019 10:38:46] Microsoft.WindowsAzure.Storage: Exception of type 'System.OutOfMemoryException' was thrown. System.Private.CoreLib: Exception of type 'System.OutOfMemoryException' was thrown.
[18/9/2019 10:38:46] Stopping host...
[18/9/2019 10:38:46] Stopping JobHost
[18/9/2019 10:38:46] Job host stopped
[18/9/2019 10:38:46] Host shutdown completed.
Application is shutting down...

下面是我的扫描 blob 触发函数:

[FunctionName("scanImports")]
        public static async Task Scan([BlobTrigger("imports/{newBlobName}", Connection = "BlobConnectionstring")]CloudBlockBlob newBlob, string newBlobName, ILogger log, ExecutionContext context)
        {
            var config = new ConfigurationBuilder().SetBasePath(context.FunctionAppDirectory).AddJsonFile("local.settings.json", optional: true, reloadOnChange: true).AddEnvironmentVariables().Build();

            var clamClient = new ClamClient(config["ContainerAddress"], int.Parse(config["ContainerPort"]));
            var blobFileStream = await newBlob.OpenReadAsync();

            using (var memoryStream = new MemoryStream())
            {
                await blobFileStream.CopyToAsync(memoryStream);
                var result = await clamClient.SendAndScanFileAsync(memoryStream.ToArray());
                bool isClean = result.InfectedFiles == null || result.InfectedFiles.Count == 0;

                // Check if newBlob is infected. If infected, move to quarantineBlob
                if (!isClean)
                {
                    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(config["blobConnectionstring"]);
                    CloudBlobClient client;
                    CloudBlobContainer container;
                    CloudBlockBlob quarantineBlob;

                    client = storageAccount.CreateCloudBlobClient();
                    container = client.GetContainerReference(config["QuarantineBlobName"]);

                    await container.CreateIfNotExistsAsync();

                    quarantineBlob = container.GetBlockBlobReference(newBlobName);
                    quarantineBlob.Properties.ContentType = newBlob.Properties.ContentType;

                    await quarantineBlob.UploadFromStreamAsync(memoryStream);
                    await newBlob.DeleteAsync();
                }
            }
        }

更新 1: 主机在刚好 5 分钟后死机并出现 OutOfMemoryException。我曾尝试延长功能超时时间,但没有任何区别。 在此期间,该进程将持续使用 5-8% cpu,并且在它终止之前,该进程将使用超过 1500 MB 的内存。

更新 2: 如果我从函数中删除所有代码,只留下一个 log.info() 语句,主机仍然会在 5 分钟后自行终止它OutOfMemoryException

默认情况下,Azure 函数的生命周期为 5 分钟。之后,它会自杀。

如果您在应用服务计划上托管 azure 函数,那么在 host.json 中您可以将 functionTimeout 值设置为更高的值

Indicates the timeout duration for all functions.

In a serverless Consumption plan, the valid range is from 1 second to 10 minutes, and the default value is 5 minutes.

In an App Service plan, there is no overall limit and the default depends on the runtime version.

In version 2.x, the default value for an App Service plan is 30 minutes.

In version 1.x, it's null, which indicates no timeout. It cannot be set as infinite . If we are not setting this value explicitly it will take the default 30 minutes value.

https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json#functiontimeout

我的问题的原因是我试图触发的 blob 中有 100.000 多个文件。 Microsoft 将其定义为 High scale.

所以我的代码实际上没有问题。只是如果我尝试在 "high scale" blob 上触发,那么我的代码只会分配内存然后死掉。