Bakgrundsuppgifter om Faust, del I: Introduktion

Bakgrundsuppgifter om Faust, del I: Introduktion

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 artikeln, och ocksÄ projektet, 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 problem med grupprĂ€kningsuppgifter (se. grupp). Vid tidpunkten för artikelns skrivande problem 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. ). Ett typiskt exempel pĂ„ anvĂ€ndning:.

I samband med detta började jag leta efter alternativ och jag hittade! Skaparna av Celery, och specifikt, som jag förstod Ask Solem, skapade Faust, ursprungligen för projektet robinhood.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Ä en kort jÀmförelse 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, alphavantage.co. 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:

Bakgrundsuppgifter om Faust, del I: Introduktion

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:

  1. Exportera vÀrdepapper och översikt över dem (inklusive vinster och förluster, balans, kassaflöde - för det senaste Äret) - regelbundet
  2. Exportera historiska data (för varje handelsÄr hitta extremvÀrden för stÀngningspriser) - regelbundet
  3. Exportera de senaste handelsdata - regelbundet
  4. 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](https://github.com/Egnod/horton/blob/562fa5ec14df952cd74760acf76e141707d2ef58/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-service

Det À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— pyproject.toml

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 install

Nu skapar vi config.yml — kredentialer och vart vi ska ansluta. Dit kan vi ocksĂ„ placera data för alphavantage. Och nu gĂ„r vi vidare till config.py — vi extraherar data för applikationen frĂ„n vĂ„r konfiguration. Ja, jag erkĂ€nner, jag anvĂ€nde mitt bibliotek— sitri.

NÀr det gÀller anslutningen till mongo Àr det vÀldigt enkelt. Vi har deklarerat en klientklass för anslutning och en basklass 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:

  1. Skriva en liten klient för alphavantage pÄ aiohttp med förfrÄgningar till de endpoints vi behöver.
  2. Skapa en agent som samlar in data om vÀrdepapper och historiska priser för dem.

Projektkod

Koden för denna del

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster