Azure Functions Out of Memory Exceptions - azure

I have an Azure Functions Powershell core as below:
# Input bindings are passed in via param block.
param([byte[]] $InputBlob, $TriggerMetadata)
# Write out the blob name and size to the information log.
Write-Host "PowerShell Blob trigger function Processed blob! Name: $($TriggerMetadata.Name) Size: $($InputBlob.Length) bytes Uri: $($TriggerMetadata.Uri)"
By using a Blob Trigger i want to read VDH OS images with Powershell from Azure Blob and convert them to managed disk. The size of the image is 30GB. When the function is triggered, i get the System.OutOfMemoryException below:
2020-09-07T09:52:44.704 [Error] Executed 'Functions.BlobTrigger1' (Failed, Id=93b00718-9941-4379-abd0-348137cdcff2, Duration=56449ms)Exception of type 'System.OutOfMemoryException' was thrown.
2020-09-07T09:52:45.061 [Information] Stopping JobHost
I have increased the App Plan in order to have 14GB of memory but i got the same memory exception.
When i do this operation directly from Cloud Shell, i get success but my main aim is to automize the script with Blob Trigger.
Do you have any advice?

Check the platform configuration of the Function App :
Function -> Configuration -> General Settings -> Platform
The 32 Bit will have less private bytes and it can hit the out of memory exceptions even though the instance has much more capacity.
If this is your case, recommend you to upgrade to the 64 bit.

Related

Stopping the listener 'Microsoft.Azure.WebJobs.Host.Blobs.Listeners.BlobListener' for function <XXX>

I have function app where I have one HttpTrigger and 3 BlobTrigger functions. After I deployed it, http trigger is working fine but for others functions which are blob triggers, it gives following errors
"Stopping the listener 'Microsoft.Azure.WebJobs.Host.Blobs.Listeners.BlobListener' for function " for one function
Stopping the listener 'Microsoft.Azure.WebJobs.Host.Listeners.CompositeListener' for function
" for another two
I verified with other environments and config values are same/similar so not sure why we are getting this issue in one environment only. I am using consumption mode.
Update: When file is placed in a blob function is not getting triggered.
Stopping the listener 'Microsoft.Azure.WebJobs.Host.Blobs.Listeners.BlobListener' for function
I was observed the same message when working on the Azure Functions Queue Trigger:
This message doesn't mean the error in function. Due to timeout of Function activity, this message will appear in the App Insights > Traces.
I have stopped sending the messages in the Queue for some time and has been observed the traces like Web Job Host Stopped and if you run the function again or any continuous activity is present in the Function, then this message will not appear in the traces.
If you are using elastic Premium and has VNET integrated, the non-http trigers needs Runtime scale monitoring enabled.
You can find Function App-->Configuration--> Function runtime settings and turn on Runtime scale monitoring.
If function app and storage account which holds the metadata of the function Private linked, you will need to add the app settings WEBSITE_CONTENTOVERVNET = 1.
Also, make sure you have private linked for blob, file, table and queue on storage account.
I created ticket with MS to fix this issue. After analysis I did some code changes as
Function was async but returning void so changed to return Task.
For the trigger I was using connection string from app settings. But then I changed it to azureWebJobStorage(even though bobth were same) in function trigger attribute param
It started working. So posting here in case it is helpful for others

Azure Function App copy blob from one container to another using startCopy in java

I am using java to write a Azure Function App which is eventgrid trigger and the trigger is blobcreated. So when ever blob is created it will be trigerred and the function is to copy a blob from one container to another. I am using startCopy function from com.microsoft.azure.storage.blob. It was working fine but sometimes, It uses to copy files of zero bytes which are actually containing some data in source location. So at destination sometimes it dumps zero bytes of files. I would like to have a little help on this so that I could understand how to possibly handle this situation
CloudBlockBlob cloudBlockBlob = container.getBlockBlobReference(blobFileName);
CloudStorageAccount storageAccountdest = CloudStorageAccount.parse("something");
CloudBlobClient blobClientdest = storageAccountdest.createCloudBlobClient();
CloudBlobContainer destcontainer = blobClientdest.getContainerReference("something");
CloudBlockBlob destcloudBlockBlob = destcontainer.getBlockBlobReference();
destcloudBlockBlob.startCopy(cloudBlockBlob);
Copying blobs across storage accounts is an async operation. When you call startCopy method, it just signals Azure Storage to copy a file. Actual file copy operation happens asynchronously and may take some time depending how how large file you're transferring.
I would suggest that you check the copy operation progress on the target blob to see how many bytes have been copied and if there's a failure in the copy operation. You can do so by fetching the properties of the target blob. A copy operation could potentially fail if the source blob is modified after the copy operation has started by Azure Storage.
had the same problem, and later figured out from the docs
Event Grid isn't a data pipeline, and doesn't deliver the actual
object that was updated
Event grid will tell you that something has changed and that the actual message has a size limit and as long as the data that you are copying is within that limit it will be successful if not it will be 0 bytes. I was able to copy upto 1mb and beyond that it resulted 0 bytes. You can try and see if azure has increased by size limit in the recent.
However if you want to copy the complete data then you need to use Event Hub or Service Bus. For mine, I went with service bus.

WebJob accessing wrong container

I have a WebJob:
public class StandardizeFileFunction : FunctionBase
{
public static async Task StandardizeFile([BlobTrigger("foobar/Raw/{blobName}")] Stream input, string blobName)
{ ... }
}
The AzureWebJobsDashboard and AzureWebJobsStorage connection strings point to Azure, but I am running locally in debug mode.
In the past, the blob trigger was set up to work against "foo/Raw/{blobName}" and "foo2/Raw/{blobName}", but I have since done a clean build and deleted the bin and obj directories. Even so, I still see the WebJob accessing the old containers in addition to the new container. In the below, you'll see that containers foo and foo2 are being accessed despite the function being set up for foobar:
StandardizeFileFunction.StandardizeFile
Job host started
Executing 'StandardizeFileFunction.StandardizeFile' (Reason='New blob detected: foo/Raw/Study/062014.txt', Id=98c90b27-b1b4-464a-898c-8d9137c564a1)
Exception while executing function: StandardizeFileFunction.StandardizeFile
Executing 'StandardizeFileFunction.StandardizeFile' (Reason='New blob detected: foo2/Raw/Study/Temperature/HF732 1310-Room-3.txt', Id=90060f17-9a6f-47f2-a09d-b39784f5152f)
Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: StandardizeFileFunction.StandardizeFile ---> System.InvalidOperationException: Exception binding parameter 'blobName' ---> System.InvalidOperationException: Binding data does not contain expected value 'blobName'.
at Microsoft.Azure.WebJobs.Host.Bindings.Data.ClassDataBinding`1.BindAsync(BindingContext context)
at Microsoft.Azure.WebJobs.Host.Triggers.TriggeredFunctionBinding`1.<BindCoreAsync>d__8.MoveNext()
--- End of inner exception stack trace ---
Why does it keep accessing the old containers and how do I stop it?
UPDATE
I repro-ed this with a new WebJob project. Here's what I did:
Use Azure Storage Explorer to add hundreds of files to container "foo"
Run the WebJob (it doesn't need to do anything)
After a couple dozen blobs are processed, stop the WebJob
Change the container name in the blob trigger (like "fooed" or "abcde")
Run the WebJob
At this point you may see errors, if not, keep switching back and forth between "foo" and "fooed" until you do.
Executing 'StandardizeFileFunction.StandardizeFile' (Reason='New blob detected: foo/Raw/Study/062014.txt', Id=98c90b27-b1b4-464a-898c-8d9137c564a1)
public static async Task StandardizeFile([BlobTrigger("foobar/Raw/{blobName}")] Stream input, string blobName)
According to your description and error message, I found in your error message your function is triggered by blob container “foo/foo2”.
But your code is triggered by blob container “foobar”.
I think maybe something wrong with your solution projects.
I suggest you could start a new webjob and try again. Make sure you have started the right project.

Increase Azure blob block upload limit from 32 MB

I am trying to upload a contents to azure blob and the size is over 32MB. The c# code snippet below:
CloudBlockBlob blob = _blobContainer.GetBlockBlobReference(blobName);
blob.UploadFromByteArray(contents, 0, contents.Length, AccessCondition.GenerateIfNotExistsCondition(), options:writeOptions);
Everytime the blob is over 32MB, the above raises an exception:
Exception thrown: 'Microsoft.WindowsAzure.Storage.StorageException' in Microsoft.WindowsAzure.Storage.dll
Additional information: The remote server returned an error: (404) Not Found.
As per this
When a block blob upload is larger than the value in this property,
storage clients break the file into blocks.
Should there be a separate line of code to enable this.
Storage clients default to a 32 MB maximum single block upload. When a block blob upload is larger than the value in SingleBlobUploadThresholdInBytes property, storage clients break the file into blocks.
As Tamra said, the storage client handles the work of breaking the file into blocks. Here is my tests for you to have a better understanding of it.
Code Sample
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
var writeOptions = new BlobRequestOptions()
{
SingleBlobUploadThresholdInBytes = 50 * 1024 * 1024, //maximum for 64MB,32MB by default
};
blob.UploadFromByteArray(contents, 0, contents.Length, AccessCondition.GenerateIfNotExistsCondition(), options: writeOptions);
Scenario
If you are writing a block blob that is no more than the SingleBlobUploadThresholdInBytes property in size, you could upload it in its entirety with a single write operation.
You could understand it by capturing the Network Package via Fiddler when you invoke the UploadFromByteArray method.
When a block blob upload is larger than the value in SingleBlobUploadThresholdInBytes property in size, storage clients break the file into blocks automatically.
I upload a blob which size is nearly 90MB, then you could find the difference as follows:
Upon the snapshot, you could find that storage clients break the file into blocks with 4MB in size and upload the blocks simultaneously.
Every time the blob is over 32MB, the above raises an exception
You could try to set the SingleBlobUploadThresholdInBytes property or capture the Network Package when you invoke the UploadFromByteArray method to find the detailed error.

Azure WebJob: BlobTrigger vs QueueTrigger resource usage

I created a WebJob project to backup images from Azure to Amazon that used the BlobTrigger attribute for the first parameter in the method
public static async Task CopyImage([BlobTrigger("images/{name}")] ICloudBlob image, string name, TextWriter log)
{
var imageStream = new MemoryStream();
image.DownloadToStream(imageStream);
await S3ImageBackupContext.UploadImageAsync(name, imageStream);
}
Then I read that the BlobTrigger is based on the best effort basis in the document How to use Azure blob storage and changed it to a QueueTrigger.
Both works perfectly fine :-) so it's not a problem but a question. Since I deployed the change the CPU and Memory usage of the WebJob looks like
Can somebody explain me the reason for the drop of memory and CPU usage? Also the data egress went down.
Very interesting.
I think you're the only one who can answer that question.
Do a remote profile for both blob and queue versions, see which method eats up that CPU time:
https://azure.microsoft.com/en-us/blog/remote-profiling-support-in-azure-app-service/
For memory consumption you probably need to grab a memory dump:
https://blogs.msdn.microsoft.com/waws/2015/07/01/create-a-memory-dump-for-your-slow-performing-web-app/

Resources