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

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

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
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
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



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ě. 😎