How do I handle long running jobs in Azure App Service? - azure

I am rather new to hosting in Azure. I have a .net 4.6 Web app, running in Azure as an App Service.
The solution contains some actions, that run for a long time. These get stopped after a 230 seconds timeout, which seems to be an Azure-thing.
I learned that I should place this code in an Azure Function in order to have it running as a background job. Here there should not be a timeout, as long as I don't use the Consumption plan.
I also use Azure Storage in my solution.
My problem is that if I use Azure Functions v1 (NuGet Microsoft.NET.Sdk.Functions v1.0.24), I am forced to use Newtonsoft.Json version =9.0.1
Meanwhile NuGet WindowsAzure.Storage requires Newtonsoft.Json version >=10.0.2
That breaks for me.
Then I tried out Azure Functions v2. But it only supports .Net Core, which is not an option for me in this project.
My main issue is still to find a way to be able to run these long running tasks.
One way could be to break the job into smaller parts, but in this case, I would like to be handle it in the same request.

Check that you do not have a timeout configured in your hosts.json.
"functionTimeout": "00:05:00"
The full configuration options for V1 and V2 are documented here.
In consumption plan, the maximum timeout is 10 minutes. In an app service plan it can be indefinite (but it makes sense to put a cap in, even if it is just 1 or 2 hours).
If you want to break up your functionality, you may find a suitable Durable Functions pattern.
On your Newtonsoft conflict, see if you can address this using a binding redirect.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30AD4FE6B2A6AEED" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-9.9.0.0" newVersion="10.0.2.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>

Related

Azure Deployment Issue: Unhandled Exception: Could not load file or assembly 'Microsoft.Azure.DocumentDB.Core

I was having performance issues with table storage and upgraded to the latest library/sdk. Everything works fine locally and I can run on the emulator. However, when I try to deploy to my Azure Cloud Service I get the following error:
Details: Recovering role... Unhandled Exception: Could not load file or assembly 'Microsoft.Azure.DocumentDB.Core, Version=2.11.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
The web role just recycles constantly with this error. The actual dll version is 2.11.6.0. Things I have tried:
I have logged on to the web role and checked the dll is the expected one (2.11.6.0).
bindingRedirects: all relevant projects have a binding redirect of this form:
<dependentAssembly>
<assemblyIdentity name="Microsoft.Azure.DocumentDB.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.11.6.0" newVersion="2.11.6.0" />
</dependentAssembly>
I have done a text search through all files in my project for Microsoft.Azure.DocumentDB.Core - every reference (that mentions version) references 2.11.6.0. This includes files of this form dll.config file - which I did not manually edit but which do have the correct redirect.
I tried changing the Azure role osFamily to 6 (it had been 5)
I tried deleting the packages folder and regenerating
I tried deleting all redirect statements and allowing Visual Studio to automatically generate them for me.
The publish is done via 'publish' in Visual Studio 2019 on the Cloud Service (csdef).
Could anyone suggest what else I can try to deploy this cloud service?
Eventually found a way round this. So, when run locally a file WebRoleName.dll.config is produced alongside the web.config. This file is not deployed. The content is an exact copy of the web.config file. All its settings are ignored apart from the redirects. The redirects are used, seemingly, just while the web role is being started up. So, I added the file based on my local configuration (so completely the wrong database settings, etc.) to the root of my Web Role project and set it to Content - Copy Always.
Now everything runs OK - obviously it would be better if this generated file was deployed by the Visual Studio Azure publish automatically.

Azure Web App swap happening BEFORE warmup

Since about a week when I publish a new version of our Web App and do a Swap from Staging to Production, it actually seems to swap before the warmup initialization is done.
As it is a large application it will takes more then five minutes to warmup the site, making the application unresponsive.
I have official Azure support, but it is taking a long time to respond to this request and I still have no answer that works.
I can't fix any issues on our platform or publish a new version without bringing the whole site down for eight minutes. This is a highly visited website, with paying clients.
Does anyone know:
anything that I could investigate myself?
a workaround or any tips that I can take a look at myself to try to fix or work around this issue?
Extra information
I do use applicationInitialization, and I see that Azure is hitting the pages - it just happens after the swap instead of before.
<system.webServer>
<applicationInitialization>
<add initializationPage="/nl" hostName="mydomain.com" />
<add initializationPage="/warmup-application-for-azure" hostName="mydomain.com" /> (special page just for warming up services)
<add initializationPage="/deeplink1" hostName="mydomain.com" />
<add initializationPage="/deeplink2" hostName="mydomain.com" />
[etc]
</applicationInitialization>
</system.webServer>
Maybe not 100% relative to this question but since I had similar issue with warm up I want to share how I solved it.
I used to have issue with auto-scaling because my nodes were not warmed up due to url rewrite module. So what if you have url rewrites in your app make sure that you are checking for
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
Now this is in official documentation and it has link to common problems
This was an Azure bug, confirmed by the Microsoft Azure team.
Sometimes hitting the site’s root URL is not enough to completely warm up the application. For example it maybe necessary to hit all important routes in an ASP.NET MVC app or to pre-populate the in-memory cache. That is where the Application Initialization Module can help.
When you use the warmup-functionality provided by IIS (and Azure) instead of those old-fashioned methods and if deploying to an App Service, just add a slot setting to make sure it always triggers such as below:
This tutorial explains how you can use the recently enabled Application Initialization Module to completely warm up your application prior to swapping it into production.
So here is the important thing you should consider:
Unless you specify which url address azure needs to request to your website, how can it knows. If you don't do that, it only calls the root of the application
Even if you specify the url and your url needs to authorisation/authentication, how can azure sign in your website automatically and call the url that you specify.
You have got two option to deal with it.
1) Write your own warming up api to call your web application with authorisation/authentication. Then create a scheduler to call the application every hour or half an hour. It also allows you to keep the entire application up & running & warm. You can also set AlwaysOn feature under the Application Settings. You can also trigger this api on your CI/CD pipeline after the staging slot deployed successfully.
2) If you don't want to touch your CI/CD pipeline or whatever reason and don't want to write api, you should sign in to your web application, go through each page and warm it up manually. Then you can swap without any problem.

FSharp.Core version errors during startup of an Azure worker role

I have a well-established project that includes three worker roles. This project has always used F#, not in the worker roles themselves, but in the functions that they call. I've recently added another worker role to the project but the architecture (C# worker roles calling F# code) remains the same. Since these changes I've been getting these messages after deployment:
Could not load file or assembly 'FSharp.Core, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.
This happens during Autofac dependency resolution:
Autofac.Core.DependencyResolutionException", "exceptionMessage": "An exception was thrown while invoking the constructor 'Void .ctor(Amazon.DynamoDBv2.AmazonDynamoDBConfig
I know this is a well known issue, and the solution is generally to add some binding redirects. I've added a redirect thus:
<dependentAssembly>
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
...to every project in the solution that has an app.config, which includes all the worker roles. I've also verified that every reference to FSharp.core uses version 4.3.1.0 and has copy local set to true.
I've also tried adding FSharp.core to the C# projects in the solution via the FSharp.Core nuget package.
I'm not sure why you would need a BR here as it sounds to me like this was always working and just adding a new worker role has somehow botched things up.
Without knowing your deployment process, I would suggest firstly just performing a manual package of the Cloud Service (you can do this directly from within Visual Studio or the command line using cspack). This will give you a zip file which contains all the code that will be deployed into the worker role - make sure that this contains FSharp.Core (and the correct version).
I would also suggest doing a quick diff (if you're not already done so) with what has changed since you added the new worker role in.
Lastly - watch out with the FSharp.Core Nuget package - FSharp.Core is treated differently by Visual Studio and by default won't reference the Nuget version if there's already a version of FSharp.Core referenced in the project.

VS 2012 MVC Web App Publish fails when Precompilation set

I have an MVC 5 web application that I'd prefer to save time with startup by pre-compiling on publication. However, when I choose "Precompile during publishing", I get the following Error:
Error 5082 Could not load file or assembly 'DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246'
or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040).
error ASPRUNTIME 0 0 USIS
The Web.Config Does have a binding redirect for this Reference
<dependentAssembly>
<assemblyIdentity name="DotNetOpenAuth.Core" publicKeyToken="2780CCD10D57B246" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>
This builds and deploys fine if I do not have this precompile option checked, and the Web is working fine without issues. I just cannot publish with this precompile option checked.
I'd really like to have the website compile all views and etc only on publish, and never recompile in the live production site. Some Documentation I was looking at was suggesting this was the propose of these features... but I'm having no luck.
EDIT: I have had some success. I realized that I was purposely not deploying the Web.Config file such that a developer doesn't accidently harm the production environment configuration, but it appears that the precompile build was copying files to a temporary location, and without the Web.Config file being deployed, no Web.Config file was there, meaning no Dependency translations.
So, Now it looks like I'm going to have to deploy the Web.Config if I want to pre-compile (I had set its Build Action from "Content" to "None", and now I've set it back again.) This means I'm going to need to look into Web.Config Transformations, or etc.
Thanks,
Greg
The only thing precompilation does is compile the views. The fact that this happens only when precompilation is set means that there's something in one of your views that is generating this error. That's kind of irrelevant, though.
The best way I've found to correct this particular error is to uninstall and reinstall the offending Nuget package.
Just go into the Package Manager Console, make sure the project that generates the error is selected for "Default Project", and then run:
> Uninstall-Package DotNetOpenAuth.Core -Force
> Install-Package DotNetOpenAuth.Core
That should resolve the issue and allow your site to publish and run fine, with or without precompilation.
Solution:
It turns out that since I wasn't publishing the Web.config file, that the binding redirects were not being made. The solution was to change this file back to being published (Build Action from "None" to "Content"), and then the pre-compilation was succeeding.
For others with an MVC or ASP.NET web site that runs slow each time hitting a new page/view, I'd recommend giving this pre-compilation feature with publishing a try. It's just hidden under file options in the publication settings (VS 2012.) I chose to Precompile, and to make the site not-updatable to avoid the dynamic view/page compilations. See for more information: What effect does the new precompile during publishing option have on MVC4 applications? .
Also, to push the correct settings and connection strings to Live and Test I started using the Translation Templates "Web.Release.config" and "Web.Debug.config". These will swap out Web.config lines when deploying only. See http://go.microsoft.com/fwlink/?LinkId=125889 for more information.

Visiting an Azure Website while Publishing displays IIS Errors

I have an MVC app hosted on an Azure Website.
I have custom errors enabled and working (when not publishing):
<customErrors mode="On" defaultRedirect="~/Error/NotFound" xdt:Transform="Replace">
<error redirect="~/Error/NotFound" statusCode="404" />
<error redirect="~/Error/NotFound" statusCode="403" />
</customErrors>
When I publish the website from Visual Studio, if I try to visit the site while the dlls are being updated, I get a nasty IIS error.
I'm surprised that Azure doesn't wait to "tie down" the new version until the publication is complete, to avoid this scenario. Is there a way to achieve this "instantaneous switch" behavior?
And/Or - How can I prevent this error from being displayed?
I can't say this would be unusual. Depending on size of the deployment it may take a while for IIS to restart and reload leading to 503 Service Unavailable or similar errors in the meantime. CustomErrors won't help you here as the ASP.Net pipeline isn't even being reached at this point. What Azure Website level are you running on (Free, Shared or Standard?) If you can up the size of the instance to try and get things moving again more quickly.
I think you deployment is too slow. IIS detects changes in dll files and restart the app-pool automatically without waiting for the other dll files.
Try to set custom values in waitChangeNotification and maxWaitChangeNotification in web.config. Doing so you can ask IIS to wait for some seconds before restarting app-pool. I'm not sure if it works on Azure. On my on-premises IIS I use custom values that allow me to do a long deploy (about 5 seconds).
Documentation: http://msdn.microsoft.com/en-us/library/e1f13641(v=vs.85).aspx

Resources