Como vim viver assim?
Há pouco tempo tive que trabalhar no backend de um projeto altamente carregado, no qual era necessário organizar a execução regular de um grande número de tarefas em segundo plano com cálculos complexos e solicitações de serviços de terceiros. O projeto é assíncrono e antes de eu chegar, ele tinha um mecanismo simples para iniciar tarefas do cron: um loop verificando a hora atual e lançando grupos de corrotinas via coleta - essa abordagem acabou sendo aceitável até que houvesse dezenas e centenas dessas corrotinas , porém, quando seu número ultrapassou dois mil, tive que pensar em organizar uma fila normal de tarefas com um corretor, vários trabalhadores e assim por diante.
Primeiro decidi experimentar o Aipo, que já tinha usado antes. Devido à natureza assíncrona do projeto, mergulhei na questão e vi
Direi uma coisa, o projeto é muito interessante e funciona com bastante sucesso em outras aplicações de nossa equipe, e o próprio autor diz que conseguiu implementá-lo em produção usando um pool assíncrono. Mas, infelizmente, isso realmente não me agradou, como descobri
Nesse sentido, comecei a procurar alternativas e encontrei! Os criadores do aipo, especificamente, pelo que entendi
Além disso, você pode olhar
O que nós fazemos?
Então, em uma pequena série de artigos, mostrarei como coletar dados de tarefas em segundo plano usando o Faust. A fonte do nosso projeto de exemplo será, como o nome sugere,
PS A julgar pela confiança com que foi escrito o ponto sobre monitoramento, acho que o leitor do final do último artigo ainda ficará mais ou menos assim:
Requisitos do projeto
Pelo que já prometi, vamos fazer uma pequena lista do que o serviço deve ser capaz de fazer:
- Carregue títulos e uma visão geral deles (incluindo lucros e perdas, balanço patrimonial, fluxo de caixa - do último ano) - regularmente
- Carregue dados históricos (para cada ano de negociação, encontre valores extremos do preço de fechamento da negociação) - regularmente
- Carregue os dados comerciais mais recentes - regularmente
- Carregue regularmente uma lista personalizada de indicadores para cada título
Como esperado, escolhemos um nome para o projeto do zero: horton
Estamos preparando a infraestrutura
O título é certamente forte, no entanto, tudo o que você precisa fazer é escrever uma pequena configuração para docker-compose com kafka (e zookeeper - em um contêiner), kafdrop (se quisermos ver as mensagens nos tópicos), mongodb. Nós temos [docker-compose.yml](
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
Não há nada complicado aqui. Dois ouvintes foram declarados para o kafka: um (interno) para uso dentro da rede composta e o segundo (externo) para solicitações externas, para que eles o encaminhassem para fora. 2181 — porto do zookeeper. O resto, penso eu, está claro.
Preparando o esqueleto do projeto
Na versão básica, a estrutura do nosso projeto deve ficar assim:
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 *
*Tudo que eu anotei Ainda não tocamos nisso, apenas criamos arquivos vazios.**
Criamos uma estrutura. Agora vamos adicionar as dependências necessárias, escrever a configuração e conectar ao mongodb. Não fornecerei o texto completo dos arquivos do artigo, para não atrasá-lo, mas fornecerei links para as versões necessárias.
Vamos começar com dependências e meta sobre o projeto -
A seguir, começamos a instalar dependências e criar um virtualenv (ou você mesmo pode criar a pasta venv e ativar o ambiente):
pip3 install poetry (если ещё не установлено)
poetry install
Agora vamos criar
Ao conectar-se ao Mongo, tudo é bastante simples. anunciado
O que vai acontecer a seguir?
O artigo não é muito longo, pois aqui estou falando apenas de motivação e preparação, então não me culpe – prometo que a próxima parte terá ação e gráficos.
Então, nesta próxima parte nós:
- Vamos escrever um pequeno cliente para alphavantage em aiohttp com solicitações para os endpoints que precisamos.
- Vamos criar um agente que irá coletar dados sobre títulos e preços históricos para eles.
Fonte: habr.com