
Hur kom jag hit?
För inte sĂ„ lĂ€nge sedan fick jag arbeta med backend pĂ„ ett högt belastat projekt dĂ€r det var nödvĂ€ndigt att organisera regelbundet utförande av ett stort antal bakgrundsuppgifter med komplexa berĂ€kningar och anrop till externa tjĂ€nster. Projektet Ă€r asynkront och innan jag kom dit anvĂ€ndes en enkel cron-mekanism för att starta uppgifter: en loop som kontrollerade aktuell tid och startade grupper av korutiner med gather â detta tillvĂ€gagĂ„ngssĂ€tt visade sig vara acceptabelt sĂ„ lĂ€nge det fanns tiotals eller hundratals korutiner, men nĂ€r deras antal översteg tvĂ„ tusen, var jag tvungen att tĂ€nka pĂ„ hur man skulle organisera en normal uppgiftskö med en broker, flera arbetare och sĂ„ vidare.
Först beslutade jag mig för att prova Celery, som jag tidigare hade anvÀnt. Med tanke pÄ projektets asynkronitet, fördjupade jag mig i frÄgan och sÄg , och ocksÄ , skapad av artikelns författare.
LĂ„t mig sĂ€ga sĂ„ hĂ€r, projektet Ă€r mycket intressant och fungerar ganska bra i andra applikationer av vĂ„rt team, och författaren sjĂ€lv sĂ€ger att han lyckades fĂ„ det i produktion, genom att anvĂ€nda en asynkron pool. Men tyvĂ€rr, det passade inte mig sĂ„ bra, eftersom det upptĂ€cktes med grupprĂ€kningsuppgifter (se. ). Vid tidpunkten för artikelns skrivande var den redan stĂ€ngd, men arbetet pĂ„gick under en mĂ„nad. Hur som helst, jag önskar författaren lycka till och allt gott, eftersom det redan finns fungerande verktyg i biblioteket... i allmĂ€nhet, det handlar om mig och för mig var verktyget lite för grönt. Dessutom, i vissa uppgifter gjorde jag 2-3 http-anrop till olika tjĂ€nster, sĂ„ Ă€ven vid optimering av uppgifterna skapar vi 4 000 tcp-anslutningar varje 2 timmar â inte sĂ„ bra... Jag skulle vilja skapa en session för en typ av uppgifter nĂ€r jag startar arbetarna. Lite mer om det stora antalet förfrĂ„gningar genom aiohttp. .
I samband med detta började jag leta efter alternativ och jag hittade! Skaparna av Celery, och specifikt, som jag förstod , skapade , ursprungligen för projektet Faust Ă€r skriven inspirerad av Kafka Streams och fungerar med Kafka som broker, dessutom anvĂ€nds rocksdb för att lagra resultat frĂ„n agenternas arbete, och viktigast av allt â biblioteket Ă€r asynkront.
Dessutom kan du ta en titt pÄ celery och faust frÄn skaparna av den senaste: deras skillnader, skillnader i mÀklare, implementeringen av en grundlÀggande uppgift. Allt Àr ganska enkelt, men faust har en trevlig egenskap - typade data för överföring till en topic.
Vad ska vi göra?
SÄ i en liten artikelserie kommer jag att visa hur man samlar in data i bakgrundsuppgifter med hjÀlp av Faust. KÀllan för vÄrt exempelprojekt kommer, som namnet antyder, . Jag kommer att demonstrera hur man skriver agenter (sink, topics, partitioner), hur man schemalÀgger (cron) körningar, de mest anvÀndarvÀnliga cli-kommandona i faust (ett wrapper över click), enkel klustring, och i slutet ansluter vi datadog (som fungerar direkt ur lÄdan) och försöker se nÄgot. För att lagra de insamlade uppgifterna kommer vi att anvÀnda mongodb och motor för anslutning.
P.S. Baserat pÄ den sÀkerhet med vilken punkten om övervakning skrivits, tror jag att lÀsaren i slutet av den sista artikeln kommer att se ut ungefÀr sÄ hÀr:

Krav pÄ projektet
Med tanke pÄ vad jag redan har lovat, lÄt oss göra en liten lista över vad tjÀnsten ska kunna:
- Exportera vÀrdepapper och översikt över dem (inklusive vinster och förluster, balans, kassaflöde - för det senaste Äret) - regelbundet
- Exportera historiska data (för varje handelsÄr hitta extremvÀrden för stÀngningspriser) - regelbundet
- Exportera de senaste handelsdata - regelbundet
- Exportera en anpassad lista med indikatorer för varje vÀrdepapper - regelbundet
Som det bör vara vÀljer vi ett namn för projektet frÄn ingenstans: horton
Förbereda infrastrukturen
Rubriken Àr förstÄs stark, men allt vi behöver göra Àr att skriva en liten konfiguration för docker-compose med kafka (och zookeeper - i en behÄllare), kafdrop (om vi vill se meddelanden i topicarna), mongodb. Vi fÄr [docker-compose.yml]() följande typ:
version: '3'
services:
db:
container_name: horton-mongodb-local
image: mongo:4.2-bionic
command: mongod --port 20017
restart: always
ports:
- 20017:20017
environment:
- MONGO_INITDB_DATABASE=horton
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=admin_password
kafka-service:
container_name: horton-kafka-local
image: obsidiandynamics/kafka
restart: always
ports:
- "2181:2181"
- "9092:9092"
environment:
KAFKA_LISTENERS: "INTERNAL://:29092,EXTERNAL://:9092"
KAFKA_ADVERTISED_LISTENERS: "INTERNAL://kafka-service:29092,EXTERNAL://localhost:9092"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT"
KAFKA_INTER_BROKER_LISTENER_NAME: "INTERNAL"
KAFKA_ZOOKEEPER_SESSION_TIMEOUT: "6000"
KAFKA_RESTART_ATTEMPTS: "10"
KAFKA_RESTART_DELAY: "5"
ZOOKEEPER_AUTOPURGE_PURGE_INTERVAL: "0"
kafdrop:
container_name: horton-kafdrop-local
image: 'obsidiandynamics/kafdrop:latest'
restart: always
ports:
- '9000:9000'
environment:
KAFKA_BROKERCONNECT: kafka-service:29092
depends_on:
- kafka-serviceDet Àr helt enkelt. För kafka har vi deklarerat tvÄ lyssnare: en (intern) för anvÀndning inom det sammansatta nÀtverket och den andra (extern) för förfrÄgningar utifrÄn, dÀrför har vi exponerat den. 2181 Àr zookeepers port. NÀr det kommer till resten, tror jag att det Àr klart.
Vi förbereder projektets struktur
I grundversionen ska strukturen av vÄrt projekt se ut sÄ hÀr:
horton
âââ docker-compose.yml
âââ horton
âââ agents.py *
âââ alphavantage.py *
âââ app.py *
âââ config.py
âââ database
â âââ connect.py
â âââ cruds
â â âââ base.py
â â âââ __init__.py
â â âââ security.py *
â âââ __init__.py
âââ __init__.py
âââ records.py *
âââ tasks.py **Allt jag markerat rör vi oss inte vid Ă€nnu, utan vi skapar bara tomma filer.
Vi har skapat strukturen. Nu lÀgger vi till de nödvÀndiga beroendena, skriver konfigurationen och kopplingen till mongodb. Jag kommer inte att inkludera hela texten för filerna i artikeln för att inte dra ut pÄ tiden, utan jag kommer att lÀnka till de nödvÀndiga versionerna.
LĂ„t oss börja med beroendena och metainformationen om projektetâ
DÀrefter utför vi installationen av beroendena och skapar virtualenv (eller sÄ kan ni sjÀlva skapa en mapp för venv och aktivera miljön):
pip3 install poetry (om det inte redan Àr installerat)
poetry installNu skapar vi â kredentialer och vart vi ska ansluta. Dit kan vi ocksĂ„ placera data för alphavantage. Och nu gĂ„r vi vidare till â vi extraherar data för applikationen frĂ„n vĂ„r konfiguration. Ja, jag erkĂ€nner, jag anvĂ€nde mitt bibliotekâ .
NÀr det gÀller anslutningen till mongo Àr det vÀldigt enkelt. Vi har deklarerat för anslutning och för CRUD-operationer, sÄ att det blir enklare att göra förfrÄgningar pÄ kollektionerna.
Vad hÀnder hÀrnÀst?
Artikeln Ă€r inte sĂ„ lĂ„ng, eftersom jag hĂ€r bara pratar om motivation och förberedelse, sĂ„ snĂ€lla ha förstĂ„else â jag lovar att det kommer att bli action och grafik i nĂ€sta del.
SÄ, i denna nÀsta del kommer vi att:
- Skriva en liten klient för alphavantage pÄ aiohttp med förfrÄgningar till de endpoints vi behöver.
- Skapa en agent som samlar in data om vÀrdepapper och historiska priser för dem.
KĂ€lla: habr.com
