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, která běží v Azure Cloudu (PaaS).
App Service Plan Definice výpočetních prostředků, které je možné pro webovou službu vyhradit. Plány se liší cenou i podporou některých funkcí. V jednom plánu může běžet vícero aplikací.
WebJob Funkce, která je součástí App Service služby. Umožňuje nám spouštět skripty, které běží buď pořád (continuous jobs) nebo je lze spouštět manuálně pomocí HTTP požadavku nebo můžeme spouštění naplánovat přes CRON scheduler (triggered jobs).
FTPS Protokol pro bezpečný přenos dat. App Service Plan FTPS podporuje ve výchozím nastavení, přihlašovací údaje najdeme v záložce Azure portálu "App Service name" > Deployment Center > FTPS credentials. Protokol pak můžeme využít pro nasazení web jobu.
FileZilla Populární open-source a cross-platform FTPS klient. První verze byla uvolněna již v roce 2001.

Obsah

Úvod

WebJob, který budeme nastavovat bude typu continuous, to znamená že nahraný script poběží pořád. Script bude napsaný v Pythonu a vyzkoušíme si pomocí Telethon knihovny odposlouchávat Telegram zprávy. To má hned několik využítí, buď si zprávy můžeme přeposílat do jiné služby a nebo je můžeme pojmout jako příkazy a ovládat tímto způsobem z Telegram aplikace libovolnou službu, disponující API. Obě možnosti mi přijdou super, ale use case samozřejmě může být jiný 🙂 WebJoby mohou běžet pouze na Windows platformě (Linux zatím není podporovaný) a potřebujeme minimálně App Service plán B1.

Příprava služby

Než budeme moci spustit náš script, musíme přidat podporu pro Python runtime do App Service služby a také nastavit podporu pro continuous spouštění. Zároveň odebereme limit pro počet zaznamenaných logů, tím že logy přesměrujeme do blob úložiště.

Přidání podpory pro Python

Python standardně ve službě nainstalovaný není, tak ho musíme přidat. To můžeme provést v Azure portálu v záložce
"App Service name" > Development Tools: Extensions

Tady je třeba si dát pozor na verzi, kterou používá náš script a verzí kterou podporuje web job. Například Python je již ve verzi 3.10, ale web job k dnešnímu dni podporuje max verzi 3.6.

Nastavení funkce Always On

Ve výchozím stavu pokud na webový server nejde žádný požadavek po dobu 20 minut tak se přepne do nečinného (idle) stavu a náš script by přestal fungovat. Nastavením funkce Always On, která je mandatorní pro continuous joby a CRON scheduled joby, tomu předejdeme.
Nastavení je v 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áš script bude používat nějaké credentials, connection stringy apod. můžeme je nastavit jako tzv. environment proměnné. Výhodou je, že náš kód nebude obsahovat žádné sensitivní údaje, takže ho můžeme zaverzovat a zároveň jsme schopní tyto údaje snadno měnit. Nastavení provedeme v "App Service name" > Settings: Configuration > Application settings. V mém případě to budou přihlašovací údaje do API Telegramu.

Script

Použít můžeme několik jazyků jako je 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í run soubor s podporovanou příponou, například run.py nebo run.bat. run.bat můžeme použít k instalaci závislostí jako jsou python knihovny a až poté teprve spustit náš script. Závislosti stačí nainstalovat pouze jednou, takže po prvním spuštění můžeme run.bat zjednodušit, případně balíčky nainstalovat pomocí Azure console.

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

Nicméně zpátky ke scriptu, script naslouchá na příchozí zprávy v námi vybraném Telegram kanálu. To samo o sobě není příliš podstatné, jedná se pouze o ukázku libovolného jobu.

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

telethon
requests
run.bat
Soubor, který se spustí jako první, nejdříve zaktualizuje balíčkovacího manažera pip a potom nainstaluje závislosti ze souboru requirements.txt. Cestu k Python.exe souboru 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í script, který naslouchá na příchozí zprávu a přepošle jí na HTTP adresu s parametrem message. Credentials načítáme z env proměnných z os.environ pole.
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ý script, můžeme ho nasadit jako web job. Nasazení probíhá dvojím způsobem. Nejdříve při vytváření jobu musíme nahrát scripty zabalené jako .zip soubor a poté můžeme scripty přehrávat pomocí FTPS klienta. V "App Service name" > Settings: Web Jobs > Add nahrajeme naše soubory pomocí jednoduchého formuláře.

Po chvíli se nám job zobrazí v seznamu a automaticky se spustí. Z portálu můžeme job ručně zastavit/spustit a zobrazit si 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 znova se spustí 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ý nám běží na pozadí webového serveru. Alternativou může být použití standardní webové aplikace nebo Azure funkce a úlohu spouštět pomocí HTTP požadavku. Doufám, že článek byl alespoň trochu srozumitelný a těším se na příště 😎

Odkazy