Přeskočit na obsah
Codedock
SlužbyJak pracujemeReferenceInsightsKariéraKontakt
Zpět na všechny články
Enterprise integrace

·

7 min čtení

·

Napsal Tomáš Mikeš

Ingestion milionů fotek z IoT zařízení na Azure: od kamery po cloud

Pro Fotopast.cloud zpracováváme fotky z tisíců fotopastí. Popis pipeline, která škáluje: Event Grid triggery, blob storage tiering, deduplikace a cost optimization pro bulk upload.

IoTAzureBlob StoragePipeline

IoT zařízení posílá fotku jednou za hodinu. Zní jako malý objem. Vynásobeno 5 000 zařízeními v provozu to je 120 000 fotek za den. Podstatná část pošle celý dávkový upload 1× denně (spícího zvířete neví fotopast nafotit, ale při podvečerní aktivitě posílá 40-60 fotek najednou). Pipe ingestion takového objemu bez drop zpráv a s rozumnými náklady vyžaduje víc než „API endpoint, který zapisuje do S3“.

Tohle je architektura, kterou jsme postavili pro Fotopast.cloud a která běží ~18 měsíců bez zásahu kromě scalingu.

Fáze 1: Příjem — HTTP endpoint, který neztrácí

Zařízení posílá POST s multipart bodu obsahujícím fotku + JSON metadata (GPS, čas, device ID, baterie). Endpoint musí:

  • Odpovědět do 5 sekund, jinak zařízení retry — což zdvojuje data
  • Akceptovat i špatně formovaný JSON (starší firmware verze) a dohoně
  • Ověřit auth token — ale neblokovat ingestion na pomalé auth check (pre-validace na edge)

Naše řešení: Azure Functions s Consumption plánem, HTTP trigger. Funkce jen zapíše blob do landing containeru a vrátí 202 Accepted. Žádná validace business logiky, žádný DB write. Průměrná latence 120 ms, P99 800 ms.

Business logika se dělá později z landing bucketu. Když ingestion zvládne i špatná data, drop rate = 0.

Fáze 2: Deduplikace — stejná fotka nemá být 2×

Firmware zařízení v edge cases odešle stejnou fotku vícekrát. Naše řešení: landing blob pojmenovaný jako {deviceId}/{photoHash}.jpg. SHA-256 z binárního obsahu fotky. Pokud blob s tím jménem existuje, overwrite se projeví jako no-op.

Hash se počítá až v processing fázi (ne v ingestion — tam je rychlost key), ale v databázi každou fotku indexujeme podle hashe. Dva záznamy stejné fotky se po hashování dostanou na stejný řádek DB a duplicita zmizí.

Fáze 3: Event Grid — processing bez polling

Event Grid emituje event při každém blob upload. Druhá Azure Function se spouští eventem, nikoliv polováním — „v 10 s intervalu zkontroluj, co je nové“ by bylo drahé a pomalé.

Processing function:

  • Spočítá hash, vytvoří DB záznam (idempotentně)
  • Vygeneruje 3 thumbnail velikosti (400 px, 1200 px, full) a uloží do hot containeru
  • Extrahuje EXIF metadata (GPS, čas)
  • Posílá push notifikaci uživateli (pokud má zapnutou)
  • Přesune původní blob do cold containeru (archiv, levnější storage tier)

Proč thumbnaily ne on-the-fly? Protože jedna fotka se čte ~50-200× (app listing, detail, sdílení). Vytvořit thumbnaily jednou, cachovat navždy, je 10-50× levnější než server-side resize při každém čtení.

Fáze 4: Blob storage tiering — cena klesne 3-5×

Azure Blob má tři tiery:

  • Hot: ~$0.018/GB/měs, čtení instantně. Používáme pro thumbnaily.
  • Cool: ~$0.010/GB/měs, čtení po ~1 minutě wakeup. Původní plné fotky mladší 30 dní.
  • Archive: ~$0.002/GB/měs, rehydration 1-15 hodin. Fotky starší 1 roku.

Automatický lifecycle policy: každá fotka jde po 30 dnech do Cool, po 12 měsících do Archive. Business logic: 90 % uživatelů se dívá jen na posledních 30 dní, 99 % se nedívá na věci starší roku — ale ukládat MUSÍME pro compliance / dokazování.

Pro Fotopast to snížilo storage náklady o 60 % po prvním roce provozu — z ~$1 200/měs na ~$480/měs.

Fáze 5: Backpressure a rate limiting

Jedno zařízení s buggy firmware začne posílat 100 fotek za minutu. Bez ochrany by to zaplnilo queue a zpomalilo processing pro ostatní. Řešení na device-level rate limit:

  • Na ingestion endpointu Redis counter per deviceId
  • Limit 200 fotek / 5 min. Překročení = vratím 429 Too Many Requests (zařízení retry později)
  • Alert na monitoring, když 10+ device překročí limit (možná firmware bug v fleetu)

Výsledná čísla

Po 18 měsících provozu (Fotopast):

  • ~45 M fotek v systému
  • ~120 TB celkem (většina v Archive tieru)
  • Ingestion throughput peaky 500 fotek/minutu
  • P99 latence na API end-to-end: 950 ms
  • Azure cost ~$600/měs (včetně compute a storage)
  • 0 ztracených fotek za 18 měsíců

Co bychom udělali jinak

Tři poučení, která si odnáším do dalšího IoT projektu:

  • Queue s dead-letter od prvního dne. My jsme ho přidali po měsíci provozu, když jsme viděli první edge case data.
  • Lifecycle policy nastavená den 1, ne den 60. Move do Cool tieru backlog existujících fotek je dražší než správně nastavit napoprvé.
  • Monitoring na device-level metriky, ne jen system-level.Agregát „500 fotek/min“ je zdravý průměr. Ale 10 devices posílajících 50 fotek/min každé = buggy firmware, který najdeš jen per-device.

Jinak — za 2 měsíce dodávky a 18 měsíců provozu bez zásahu — je to architektura, která se za celou dobu nezměnila, jen škálovala.

Řešíš něco podobného?

Domluvme si 30min technický call. Bez obchodních procesů — přímá architekturní zpětná vazba.

Vybrat termín

Architektura, cloud a integrace pro komplexní systémy. Senior architekt na každém projektu.

Navigace

SlužbyJak pracujemeReferenceInsightsKariéraKontaktSrovnání s agenturou

Služby

VývojCloudDevOpsAI & DataKonzultaceŘízení

Kontakt

CodeDock s.r.o.

Zlenická 863/9, 104 00 Praha 22

Česká republika

info@codedock.com

IČO: 14292769

DIČ: CZ14292769


© 2026 Codedock

KontaktOchrana osobních údajů
Domluvit call