Záznam ze Vzdělávacího okénka HAVIT, kde Jirka Kanda ukazoval Hangfire – knihovnu pro background jobs, na kterou postupně přecházíme z Quartz.NET.
Tag Archives: WebJobs
Naplánovaný restart Azure App Service
Pokud chcete restartovat Azure App Service dle časového plánu, nabízí se použít jednoduše PowerShell:
Stop-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_' Start-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_'
Jenom je potřeba vyřešit dva problémy:
- Čím budeme takový skript spouštět? …můžeme prostě použít WebJob.
- Jak se bude skript autentizovat? …je potřeba použít Service Principal.
Vezměme to od konce.
Credits: Tento návod vznikl na základě postupu původně publikovaného Karanem Singhem, zaměstnancem Microsoftu, na jeho MSDN blog. Postup jsem opravil a ověřil.
Vytvoření Service Principal Id pro autentizaci
Určitě není dobrý nápad, spouštět podobné joby pod uživatelským účtem reálného uživatele. V mém případě je to navíc v podstatě nemožné, protože mám Organizational Account s 2-FA.
Je potřeba použít servisní účet a Service Principal Id je přesně to, co v kontextu Azure potřebujeme.
Abychom ho vytvořili, můžeme použít jednoduchý Powershell script (jednorázový úkon z vlastního PC):
param ( [Parameter(Mandatory=$true, HelpMessage="Enter Azure Subscription name. You need to be Subscription Admin to execute the script")] [string] $subscriptionName, [Parameter(Mandatory=$true, HelpMessage="Provide a password for SPN application that you would create")] [string] $password, [Parameter(Mandatory=$false, HelpMessage="Provide a SPN role assignment")] [string] $spnRole = "owner" ) #Initialize $ErrorActionPreference = "Stop" $VerbosePreference = "SilentlyContinue" $userName = $env:USERNAME $newguid = [guid]::NewGuid() $displayName = [String]::Format("VSO.{0}.{1}", $userName, $newguid) $homePage = "http://" + $displayName $identifierUri = $homePage #Initialize subscription $isAzureModulePresent = Get-Module -Name AzureRM* -ListAvailable if ([String]::IsNullOrEmpty($isAzureModulePresent) -eq $true) { Write-Output "Script requires AzureRM modules to be present. Obtain AzureRM from https://github.com/Azure/azure-powershell/releases. Please refer https://github.com/Microsoft/vsts-tasks/blob/master/Tasks/DeployAzureResourceGroup/README.md for recommended AzureRM versions." -Verbose return } Import-Module -Name AzureRM.Profile Write-Output "Provide your credentials to access Azure subscription $subscriptionName" -Verbose Login-AzureRmAccount -SubscriptionName $subscriptionName $azureSubscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName $connectionName = $azureSubscription.SubscriptionName $tenantId = $azureSubscription.TenantId $id = $azureSubscription.SubscriptionId #Create a new AD Application Write-Output "Creating a new Application in AAD (App URI - $identifierUri)" -Verbose $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force $azureAdApplication = New-AzureRmADApplication -DisplayName $displayName -HomePage $homePage -IdentifierUris $identifierUri -Password $secpasswd -Verbose $appId = $azureAdApplication.ApplicationId Write-Output "Azure AAD Application creation completed successfully (Application Id: $appId)" -Verbose #Create new SPN Write-Output "Creating a new SPN" -Verbose $spn = New-AzureRmADServicePrincipal -ApplicationId $appId $spnName = $spn.ServicePrincipalName Write-Output "SPN creation completed successfully (SPN Name: $spnName)" -Verbose #Assign role to SPN Write-Output "Waiting for SPN creation to reflect in Directory before Role assignment" Start-Sleep 20 Write-Output "Assigning role ($spnRole) to SPN App ($appId)" -Verbose New-AzureRmRoleAssignment -RoleDefinitionName $spnRole -ServicePrincipalName $appId Write-Output "SPN role assignment completed successfully" -Verbose #Print the values Write-Output "`nCopy and Paste below values for Service Connection" -Verbose Write-Output "***************************************************************************" Write-Output "Connection Name: $connectionName(SPN)" Write-Output "Subscription Id: $id" Write-Output "Subscription Name: $connectionName" Write-Output "Service Principal Id: $appId" Write-Output "Service Principal key: <Password that you typed in>" Write-Output "Tenant Id: $tenantId" Write-Output "***************************************************************************"
Budete dotázáni na název subscription a heslo pro Service Principal Id. Pro úspěšné vykonání musíte být administrátoři své Azure Active Directory.
Založený Service Principal Id si pečlivě uložte a chraňte, dostává totiž roli Owner (popř. můžete nastavit jinou, např. Contributor). Účet lze využít i na spoustu dalších administračních úkonů, byť je dobrý nápad mít oddělené účty pro každý takový job (ideálně s minimálními právy jen pro daný úkon, ale to ponechávám pro tuto chvíli pro vlastní doladění).
Vytvoření naplánovaného WebJobu
V zásadě použijte libovolný vlastní postup pro nasazení naplánovaného WebJobu, který bude spouště příslušný skript:
$ProgressPreference= "SilentlyContinue" $password = '_Service Principal Key/Password_' $secpasswd = ConvertTo-SecureString $password -AsPlainText -Force $mycreds = New-Object System.Management.Automation.PSCredential ("_Service Principal Id_", $secpasswd) Add-AzureRmAccount -ServicePrincipal -Tenant '_Tenant Id_' -Credential $mycreds Select-AzureRmSubscription -SubscriptionId '_Subscription Id_' Stop-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_' Start-AzureRmWebApp -Name '_App Service Name_' -ResourceGroupName '_Resource Group Name_'
Můžete to udělat například ručně přímo z portálu:
- Uložte skript do souboru run.ps1 a ten zazipujte (na názvu ZIPu nezáleží).
- Přes App Service / Web Jobs a Add můžete WebJob přidat:
Hotov. Jen pamatujte, že naplánované WebJoby běží lépe (vůbec), jen pokud běží vaše aplikace, tedy potřebujete mít nastaven režim Always On.
Vytvořený WebJob můžete snadno ověřit i ručním spuštěním z portálu (tlačítko Start), popř. si můžete výsledek prohlédnout přes KUDU Dashboard (tlačítko Logs) – což mimochodem vřele doporučuji, protože není jisté, že se vám vše povedlo bezchybně a čekat na plánované spuštění je zbytečné.
Vývoj cloudových aplikací – 02 Azure AppService, WebJob, SQL, SendGrid [MFF UK NSWI152, LS 2018]
Záznam z druhé vyučovací hodiny (27.2.2018) semináře Vývoj cloudových aplikací (NSWI152) pro MMF UK v letním semestru 2017/2018. Je publikován na našem HAVIT YouTube Channelu.
Dotčená témata
- Azure App Service
- Creating simple Web Site
- Deployment from Visual Studio
- Deployment from GitHub
- Web Jobs – Creating & Deployment
- Azure SQL database – Creating & Accessing from Visual Studio 2017
- Azure SendGrid mail service
Záznam je v angličtině. Ukázalo se, že na hodinu přišlo více zahraničních studentů než českých, tak jsme se domluvili takto.
Bohužel mi zhruba po 30 minutách skončil audio záznam z klopového mikrofonu, zbytek je tedy jen velmi nekvalitní podoba z notebooku.
Quartz .NET – sekvenční zřetězení jobů [Martin Havel, HAVIT Vzdělávací okénko 2.11.2017]
Záznam z interního vzdělávacího okénka HAVIT z 2.11.2017 je publikován na našem HAVIT YouTube Channel. Téma prezentoval Martin Havel:
Dotčená témata:
- Co je Quartz
- Sekvenční spouštění úloh
- Tři způsoby, jak se zřetězením jobů vypořádat
Azure PaaS – Praktické zkušenosti, tipy a triky – slides a záznam [TechEd Praha 05/2017]
Slides, dema a záznam z mé přednášky pro TechEd DevCon Praha z 16.5.2017:
Záznam z přednášky je publikován na našem HAVIT YouTube Channel.
Dotčená témata
- IaaS vs. PaaS vs. XaaS
- Motivace k Azure PaaS vs. Co vás může odradit
- Klíčové služby
- App Service
- Azure SQL
- Azure Storage
- Application Insights
- Praktické scénáře
- Deployment (MSDeploy)
- Práce se soubory
IFileStorage
- Práce s časem (
DateTime.Now
v UTC vs.ITimeService
) - Posílání e-mailů (SendGrid)
- Naplánované úlohy (Quartz.NET, WebJobs, WebJobs SDK, Dashboard)
Azure WebJob se občas spouští dvakrát
Problém
Máme v Azure nasazeno několik Azure Website spolu s naplanovanými (scheduled) web job. Řešíme situaci, kdy se webjob spustí dvakrát, zhruba v rozmezí jedné minuty. (V našem konkrétním případě posíláme notifikační emaily a tyto nám přijdou dva.)
Analýzou historie zjišťuji, že scheduler se webjob pokusil úlohu spustit dokonce třikrát.
Přičemž log jednotlivých pokusů vypadá takto:
- Http Action – Request to host ‚(…).scm.azurewebsites.net‘ failed: The timeout (30 seconds) was reached.
- Http Action – Response from host ‚(…).scm.azurewebsites.net‘: ‚Conflict‘ Response
…
Body: Cannot start a new run since job is already running. - Http Action – Response from host ‚(…).scm.azurewebsites.net‘: ‚Accepted‘ Response
Položky logu interpretuji takto:
- Bod 1 úspěšně spustit webjob, ale nebyl schopen v intervalu 30 sekund toto zjistit.
- Bod 2 se pokusil spustit webjob, ale ten již běžel, takže byl oznámen konflikt.
- Bod 3 se opět pokusil spustit webjob, ten již doběhl, takže byl webjob úspěšně (ve skutečnosti podruhé) spuštěn.
Řešení
Po přečtení
- (zoufalé) diskuse,
- de facto nesouvisející zprávy aspoň trochu popisující nastavení Always On
- a minimalistické dokumentace
se pokouším interpretovat (snad) klíčovou větu „If your site runs continuous web jobs, you should enable Always On, or the web jobs may not run reliably“ tak, že Always On zapínám i pro náš scheduled Web Job. Pomáhá to.
Volba Always On se nastavuje v Azure portálu, v nastavení Azure Website, se přepínačem Always On na záložce Configure.