I have an Azure website with several deployment slots. I use Visual Studio to deploy to a Staging slot and then swap this into Production.
My Visual Studio solution contains one project for my web application and another for a continuous WebJob. I used (Right-click project) > Add > Existing Project as Azure WebJob to configure the WebJob to be deployed to the site along with the web application.
My problem is that the WebJob sometimes continues to run old code after a swap. Sometimes it runs the new code on one invocation and then switches back to the old code on the next invocation. I can't seem to figure out a rhyme or reason to this.
This morning, in order to try to find the cause of this, I did the following experiment:
Delete WebJob in Staging.
Delete WebJob in Production.
Deploy web app to Staging.
Verify that WebJob is running new code in Staging.
Swap Staging into Production.
Verify that WebJob no longer appears in Staging and that it now appears in Production.
What I found was that, after step 4, all the WebJob functions started afresh in Staging and were all running the new code. But after I swapped Staging into Production, there were no new invocations of the WebJob in Production, and when I manually invoked it, the old code ran!
What on earth is going on here? How can I totally clear out the old code and ensure the new WebApp code will run in Production?
I did see another thread saying that checking the Exclude files from the App_Data folder box in publishing settings could cause this issue, but I do not have it checked.
I feel like I'm taking crazy pills here. Any pointers would be sincerely appreciated.
Update 1: As described in my comment below, I have given up and switched to Azure Functions, but I just thought of something that might help anyone else who is encountering this. I recall that at least once or twice, I deployed my WebJob by manually uploading a zip file as opposed to deploying via Visual Studio. I'm starting to wonder if perhaps, under the covers, there is a different code path in use that could give rise to this behavior. Perhaps that will be a useful pointer for someone.
Update 2: I've figured out what happened. I'm describing this in the hopes that it might help someone in the future.
We have several deployment slots: Staging, Production, and a few others. One such slot is called Replica. Its purpose is to be a replica of Production (same code, same configuration settings). The idea is that, for those weird one-off problems that only repro in Production, you can upload a debug build to the Replica slot and attach a debugger without disrupting Production.
This is useful once in a while, but we didn't use it very frequently. The result was that the code running in the Replica slot, including our WebJob code, gradually got further and further out of date compared to what was running in Production. However, meanwhile, the Replica WebJobs kept running the old code, and since the Replica slot has all the same configuration settings as Production, it was operating on the same data and writing to the same logs as our Production WebJobs. So when I would go look at my Production WebJob logs, I would see output that I knew should no longer be there, and I couldn't figure out why. The rogue code was actually running in another slot that I had forgotten about.
So, mystery solved. This probably means we didn't need to cut everything over to Azure Functions. But I'm still glad that we did. I like them better. I like how we have the option to run them in the same app service as our site or a separate one, and the logging system is better. It feels more modern overall.
Anyway, I hope this helps someone out there.
Usually it is not possible run old code after swap successfully and restart your web app. So you can check the content under site->wwwroot in kudu: https://YourWebApp.scm.azurewebsites.net/DebugConsole to make sure your webjob is correct.
Related
We have 2 Azure Webjobs connected to our ASP WebApi application. None of them is using any dependencies from the other one. And yet, after publishing, one of them has executables from the other one. It's worth mantioning that this only happens on publish. Everything is normal on VS build.
This is how files hierachy looks like on Azure FTP
The first one, Deployment, is being published as expected. Those are executables in it's folder:
The second one, EmailSender, has executables from the Deployment:
What's curious, there is also app.publish folder in both of them, containing only one and the same file WebJob.Deployment.exe:
Deployment job works fine. Unfortunately Azure don't recognize EmailSender job, instead it executes Deployment. The only solution that works right now is to manualy delete Deployment's executables directly from FTP, on every publish.
Right now we tried couple of things from SO and blogs, but with no success.
Microsoft.Web.WebJobs.Publish producing duplicate assemblies in deploy package
Azure Webjobs not getting updated after new publish
GitHub solution
Azure Web Job Run Command Incorrectly Set
Edit:
I did accomplished something. It did not resolve the problem, but we don't have app.publish folder anymore. Here is the link to solution on SO. I don't know why we had 'ClickOnce security' options checked for WebJob.Deployment application.
Update:
I run few tests with MSBuild and found something curious. As I said before, Visual Studio Publish works just fine - no additional executables are deployed. But when I run MSBuildprogram (with the same publish profile and project configuration) I got additional Deployment.exe inside EmailsSender folder. This is the command I run:
MSBuild RestAPI.Host.csproj /t:Build /p:Configuration="Develop" /p:Platform="AnyCPU" /p:DocumentationFile="RestAPI.Host.XML" /p:DeployOnBuild="true" /p:PublishProfile="fakebuild_develop.pubxml" /p:OutputPath="backend\build\app\\" /p:SolutionDir="backend\\"
Can someone tell me what's the difference between MSBuild and VS Publish? I cannot find anything usefull on the internet.
I'm looking for some advices concerning release management in azure
I've found a lot of ressources, but I still have some questions
I have an asp.net 4 solution (to make it simple : one asp.net project, one database project, one test project)
I'm using GIT in visual studio online
At this moment I have one app service and one sql server database in azure.
I have a build that download nuget packages, build, execute a dacpac for the database, executes the tests from the project (I have integration tests that uses the database) and finaly deploys the app on an azure app services
What I want to do seems a "normal stuff" :
I want to cerate the build, then deploy it on a "dev" environnement in azure, then in a "qa" environnement, then in a "stagging" and in "prod"
In my web project, I created different web.config transformations (one for each environnement)
I've seen the releases in visual studio online and I get that its for the deployment part in different environnements
What I have questions with :
In Azure :
Do I create 1 app service by environnement ? or do I create a single app service and use slots ?
Do I create 1 sql server for each environnement or is it best to use a single sql server and to have one database for each environnement ?
In visual studio online :
How do I do the tasks ?
In the build part, what configuration do I use ? Which environnement do I select ?
In the build, how do I manage the database project ? I thing the deployment part should be in the release part, but I don't see how to configure the connexionstring ?
For the tests -> Do I execute them in the release part? How do I change the connexionstrings and appsettings? there is no transformations for the app.config
I've seen that there is test-plans as well, but I don't really get it
Can somebody help me to see a little bit better in all of that ?
I cannot answer all of these, but I can answer a few.
I would create separate Web App instances for your separate environments. With slots, your slots exist on the same Web App and share computing resources. If something goes horribly wrong (your staging code pegs CPU to 100% or eats all of your RAM), this will cause problems for your production slot. I see slots as part of A/B testing or to aid in deployment.
You will likely need to create a separate database per environment as well. This is almost always required if you will be upgrading your database schema at any point in the future and introduce breaking changes to your database schema. For example, what happens if your production code requires a specific field in a database table, but your next version of the database removes that field?
You mentioned you're using web.config transforms, but I want to throw out another option that we've found to be easier and have fewer moving parts and sources for error. If you're just changing connection strings and AppSettings, consider using the Web App's application settings per environment. These override whatever is in your web.config. Doing so means you can forget about web.config transforms and not have one more thing that could possibly go wrong in a deployment.
Since you're using a Database project, to deploy your database, check out the VSTS Azure SQL Database Deployment task. It'll use your database project to create a DACPAC, and then deploy that to your target server.
I'm currently running a webApp with several deployment slots (e.g. dev, staging, production). Every Slot is connected to a database (db_dev, db_staging, db_production). I want to deploy to the staging slot and then switch with production. How do database migrations fit in here?
I mean, if i deploy a new build with db migrations to staging the db_staging gets updated. What happens if I switch the slots? Do the migrations get applied to db_production? What about downtimes?
From my understanding only the URLs are switched, so after the switch the app in the staging slot would point to the db_production? That does not make sense.
I could deploy to the staging slot and point to db_production (with migrations), but then the db would be updated and could possibly break the app in the live slot.
I have been pondering this too, and as far as I can see the only sensible process is as follows:
Stop Prelive stites
Clone live DB back to a new staging DB
Run scripts to make data safe (clear information which may contact real users etc)
Change staging slot sticky connection string to point at this database
Run DBUP aganst staging DB (now an upgraded version of live-ish)
Deploy to staging slot
Restart prelive sites
Test staging until satisfied
Backup live DB
Run DBUP against live (if they are non-breaking changes, site can
stay up)
Swap live and prelive slots
Check live
If you can keep your db updates non-breaking, then rollback can be simple as swapping the slots back. If not, you are back in the familiar pain of rollback scripts or restoring snapshots.
Instead of hard coding the connecting string in your source code, put them under the connecting strings section of your app service settings and access it as an environment variable. It's not only safer as it will allow you to have just one code for any environment and by checking the setting as a "slot setting" no matter if you swap or not, for that slot, the configuration remains fixed.
More info here:
https://azure.microsoft.com/en-us/documentation/articles/web-sites-configure/
Update:
In the case of a database update, i.e, necessary scripts that need to be run in order to update the database schema for the new app version, you can use the applicationInitialization section of your web.config. Usually used to warm-up the app, but should work for your case as well.
<system.webServer>
<applicationInitialization >
<add initializationPage="/init-script.php" hostName="xxxxxx.azurewebsites.net"/>
</applicationInitialization>
<system.webServer>
The AppInit module will wait until this code completes before finishing the swap process which is basically allowing production traffic to the app. Basic logic would be checking if the database is running the expected version and if not some other logic would be executed in sequence.
We are trying to work out a good continuous deployment setup using TFS, Visual Studio and Azure. At our company, each developer has their own Azure subscription that we use for testing, as well as shared QA1/QA2/PROD subscriptions that we can deploy to. We have matching TFS XAML build definitions for each of these, running Powershell scripts with parameters and PublishSettings files.
This all gives us a set of .cspkg and .cspkg files, and in theory we can deploy the right cspkg with the correct cspkg to any Azure system.
The problem we are encountering now though is that we want to start using the Redis Cache service. Installing the nuget package writes subscription-specific settings into the web.config, to point at the cache. This means that the cspkg is now complied specifically for the Azure subscription.
We could use SlowCheetah to merge web.config files on build, but this means that we would have to compile the package for each build definition, and as the number of developers increases this is obviously going to become unsustainable.
I am looking for a way to keep our old generic packages and still use the Redis Cache. We can connect to the cache in code during app_start, but then we can't use it to store IIS session state. I understand that the Azure Load Balancer is meant to keep users on the same server, but I'm unsure how that will work as we swap servers in/out.
It feels like we are approaching the problem wrong and there should be a simple solution that we are overlooking.
We are using Azure Tools 2.6, Visual Studio 2013, TFS 2015r2.
I think there are always 3 ways of doing this.
1st one is config during build, which is building one thing for one thing you described, which is not desired in most of scenario.
2nd is config during deployment, which means you open the cspkg file, change config, then put it back before upload without re-compile.
3nd is config after deployment, have a configuration management tool adjust the config file for you on the fly.
We use octopus deploy to archive #2 above, our CI tool feed octopus with cspkg and cscfg, octopus handles the rest. I would definitely not going after #1 but consider #3 is a valid option too.
As of today we store all our connection settings in .cscfg files. Even if for security reasons, we avoid storing any production connection strings in source control, only QA. And we have CI for QA, but not production. This way it works well for us, we just maintain different .cscfg for different environments (subscriptions)
However, in near future I think we will move to Key Vault for this.
During development of my webjob i have redeployed it multiple times to Azure. When i visit the webjob dashboard i am greeted by this:
It seems that every webjob deployment gets registered as a new function, deprecating the old one. Searching around how to alter this behaviour (fold all previous functions together with the current one) gives no results.
Does anybody know how to configure the azure webjob dashboard to merge previous functions together if name+arguments are still the same?
The function list/index for a job host exe is based on the fully qualified assembly name. One thing I can think of that might cause the above would be if your assembly name is changing each time you deploy for some reason. Do you have anything like that going on?
Another question: do you have multiple job hosts sharing the same dashboard storage account?