Spouštění úloh pomocí Azure WebJobs

27.11.2021

Slovníček

App Service Web App Služba určená k hostování webových stránek, provozovaná v Azure Cloud (PaaS).
App Service Plan Definice výpočetních prostředků, které lze vyhradit pro webovou službu. Plány se liší cenou a podporou vybraných funkcí. V rámci jednoho plánu je možné provozovat i více aplikací.
WebJob Komponenta služby App Service, která spouští úlohy na pozadí. Skripty lze spustit ručně pomocí HTTP požadavku, nebo naplánovat prostřednictvím CRON scheduleru (triggered jobs). Joby mohou běžet také nepřetržitě (continuous jobs).
FTPS Protokol pro bezpečný přenos dat. App Service Plan podporuje FTPS ve výchozím nastavení a přihlašovací údaje jsou dostupné na záložce Azure portálu: "App Service name" > Deployment Center > FTPS credentials. Protokol lze využít pro nasazení WebJobu.
FileZilla Populární open-source a multiplatformní FTPS klient, jehož první verze byla vydána již v roce 2001.

Obsah

Úvod

WebJob, který budeme nastavovat, bude typu continuous, což znamená, že nahraný skript poběží nepřetržitě. Skript bude napsaný v Pythonu a vyzkoušíme si pomocí knihovny Telethon odposlouchávat zprávy z Telegramu. Toto řešení má několik možných využití: zprávy můžeme například přeposílat do jiné služby, nebo je použít jako příkazy. Obě možnosti jsou zajímavé, ale použití závisí na konkrétním scénáři. 🙂 WebJoby mohou běžet pouze na platformě Windows (Linux zatím není podporován) a vyžadují minimálně App Service plán B1.

Příprava služby

Před spuštěním našeho skriptu je potřeba přidat podporu pro Python runtime do služby App Service a nastavit podporu pro nepřetržité (continuous) spouštění. Zároveň odstraníme limit na počet zaznamenaných logů tím, že je přesměrujeme do blob úložiště.

Přidání podpory pro Python

Python není ve službě standardně nainstalovaný, takže je potřeba jej přidat. To lze provést v Azure portálu na záložce
"App Service name" > Development Tools: Extensions

Je důležité věnovat pozornost kompatibilitě mezi verzí Pythonu, kterou používá náš skript, a verzí podporovanou WebJobem. Například Python je aktuálně dostupný ve verzi 3.10, ale WebJob k dnešnímu dni podporuje maximálně verzi 3.6.

Nastavení funkce Always On

Ve výchozím nastavení, pokud na webový server není odeslaný žádný požadavek po dobu 20 minut, přepne se do nečinného (idle) stavu a náš skript by přestal fungovat. Tento problém můžeme vyřešit nastavením funkce Always On, která je povinná pro continuous joby a CRON scheduled joby.
Nastavení je na záložce "App Service name" > Settings: Configuration > General settings

Přesměrování logů do Blob úložiště

Logy si můžeme procházet v SCM dashboardu, do kterého se dostaneme následovně
"App Service name" > WebJobs: "Web Job name" => Logs (přesměrování do SCM dashboardu) > "Web Job Name"
Nicméně množství logů, které se zobrazují je omezené a může se nám zobrazit následující chyba

c6c289: WARN] Reached maximum allowed output lines for this run, to see all of the job's logs you can enable App Service Logs option in the Portal.
Chybě se vyhneme nastavením v záložce "App Service name" > Monitoring: App Service logs kde si můžeme zvolit blob storage úložiště a dobu retence (jak dlouho zpětně se mají logy ukládat)

Nastavení env proměnné

Pokud náš skript bude používat přihlašovací údaje, connection stringy apod., můžeme je nastavit jako environment proměnné. Výhodou je, že kód nebude obsahovat žádné citlivé údaje, což nám umožní jej verzovat a zároveň snadno tyto údaje měnit. Nastavení provedeme v 'App Service name' > Settings: Configuration > Application settings. V mém případě to budou přihlašovací údaje pro API Telegramu.

Script

K dispozici máme několik jazyků, jako jsou PowerShell, PHP, Python, JavaScript, Java, nebo Bash a Windows CMD příkazy. Princip je vždy stejný: po nahrání souborů do složky /site/wwwroot/App_Data/jobs/[continuous|triggered]/job_name/job_name se spustí soubor run s podporovanou příponou, například run.py nebo run.bat.

Soubor run.bat můžeme využít k instalaci závislostí, jako jsou Python knihovny, a až poté spustit náš skript. Závislosti stačí nainstalovat pouze jednou, takže po prvním spuštění můžeme soubor run.bat zjednodušit, nebo balíčky nainstalovat přímo pomocí Azure Console.

Konzoli najdeme v "App Service name" > Development tools: Console, a je velmi užitečná i pro různé další účely, například pro zjištění podporované verze Node.js a podobně.

Nicméně zpět ke skriptu: skript naslouchá na příchozí zprávy v námi vybraném Telegram kanálu.

requirements.txt
Soubor obsahující závislosti.

telethon
requests
run.bat
Soubor, který se spustí jako první, nejprve aktualizuje balíčkovacího manažera pip a poté nainstaluje závislosti ze souboru requirements.txt. Cestu k souboru Python.exe zjistíme v Azure portálu v detailu nainstalovaného rozšíření.
D:\home\python364x86\python -m pip install --upgrade pip
D:\home\python364x86\python -m pip install --upgrade -r requirements.txt
D:\home\python364x86\python program.py
program.py
Náš hlavní skript naslouchá na příchozí zprávy a přeposílá je na HTTP adresu s parametrem message. Přihlašovací údaje načítáme z environmentálních proměnných pomocí pole os.environ.
import os
import requests
from telethon import TelegramClient, events

print("Program started.", flush=True)

# define variables
api_id = os.environ['Telegram_api_id']
api_hash = os.environ['Telegram_api_hash']
channel = '@some_channel'
webhook = 'some url'

# prepare client
client = TelegramClient('session', api_id, api_hash)

# prepare incoming handler
@client.on(events.NewMessage(chats=channel))
async def my_event_handler(event):
    requests.get(url = webhook, params = {'message': event.text})

# start
client.start()
print("Listening...", flush=True)

# end
client.run_until_disconnected()
print("Program ended.", flush=True)

Deployment

Pokud máme vytvořený skript, můžeme ho nasadit jako WebJob. Nasazení probíhá dvěma způsoby. Nejprve při vytváření jobu musíme nahrát skripty zabalené do .zip souboru, a poté se můžeme připojit FTPS klientem. V 'App Service name' > Settings: Web Jobs > Add nahrajeme naše soubory prostřednictvím jednoduchého formuláře

Po chvíli se job zobrazí v seznamu a automaticky se spustí. Z portálu můžeme job ručně zastavit nebo spustit a zobrazit logy.
Aktualizovat soubory můžeme přes FTPS klienta, v mém případě FileZilla. Server rozpozná, že došlo k přehrání souborů, a automaticky spustí soubor run.bat.
Pro automatizovaný deployment by se teoreticky dalo použít WebJobs API, ale nezkoušel jsem.

Závěr

V tomto článku jsme si nastavili program, který běží na pozadí webového serveru. Obdobně bychom mohli nastavit variantu, kdy by job byl spouštěn pomocí HTTP požadavku. V takovém případě bychom ale mohli zvážit i využití webové aplikace nebo Azure funkcí. Doufám, že byl článek srozumitelný a těším se na příště. 😎

Odkazy