งานเบื้องหลังเกี่ยวกับเฟาสต์ ตอนที่ XNUMX: บทนำ

งานเบื้องหลังเกี่ยวกับเฟาสต์ ตอนที่ XNUMX: บทนำ

ฉันมาใช้ชีวิตแบบนี้ได้ยังไง?

ไม่นานมานี้ ฉันต้องทำงานในส่วนแบ็คเอนด์ของโปรเจ็กต์ที่มีการโหลดสูง ซึ่งจำเป็นต้องจัดระเบียบการดำเนินงานเบื้องหลังจำนวนมากเป็นประจำด้วยการคำนวณที่ซับซ้อนและการร้องขอบริการจากบุคคลที่สาม โครงการเป็นแบบอะซิงโครนัสและก่อนที่ฉันจะมา มันมีกลไกง่ายๆ สำหรับงาน cron-launching: การวนซ้ำตรวจสอบเวลาปัจจุบันและการเปิดตัวกลุ่มของ coroutines ผ่านการรวบรวม - วิธีการนี้เป็นที่ยอมรับจนกระทั่งมี coroutines ดังกล่าวหลายสิบหลายร้อย อย่างไรก็ตาม เมื่อมีจำนวนเกินสองพันคน ฉันก็ต้องคิดถึงการจัดคิวงานตามปกติโดยมีนายหน้า คนงานหลายคน และอื่นๆ

ก่อนอื่นฉันตัดสินใจลองใช้คื่นฉ่ายซึ่งฉันเคยใช้มาก่อน เนื่องจากลักษณะของโปรเจ็กต์ไม่ตรงกัน ฉันจึงดำดิ่งลงไปในคำถามและเห็น บทความเช่นกัน โครงการที่สร้างโดยผู้เขียนบทความ

ฉันจะพูดแบบนี้โครงการนี้น่าสนใจมากและทำงานได้ค่อนข้างประสบความสำเร็จในแอปพลิเคชันอื่น ๆ ของทีมของเราและผู้เขียนเองก็บอกว่าเขาสามารถนำไปใช้จริงได้โดยใช้พูลแบบอะซิงโครนัส แต่น่าเสียดายที่มันไม่เหมาะกับฉันจริงๆ ปัญหา ด้วยการเปิดตัวงานกลุ่ม (ดู. กลุ่ม). ในขณะที่เขียน ปัญหา ปิดไปแล้ว แต่งานยังดำเนินไปเป็นเวลาหนึ่งเดือนแล้ว ไม่ว่าในกรณีใด ขอให้ผู้เขียนโชคดีและขอให้โชคดี เนื่องจากมีสิ่งต่าง ๆ ที่กำลังดำเนินการอยู่บน lib... โดยทั่วไปแล้ว ประเด็นอยู่ที่ฉันและเครื่องมือกลับกลายเป็นว่าไม่เหมาะกับฉัน นอกจากนี้ งานบางอย่างมีการร้องขอ http 2-3 ครั้งไปยังบริการที่แตกต่างกัน ดังนั้นแม้ว่าจะเพิ่มประสิทธิภาพงาน เราก็สร้างการเชื่อมต่อ TCP 4 ครั้งทุกๆ 2 ชั่วโมงโดยประมาณ - ไม่ค่อยดีนัก... ฉันต้องการสร้างเซสชันสำหรับประเภทหนึ่ง งานเมื่อเริ่มต้นคนงาน ข้อมูลเพิ่มเติมเล็กน้อยเกี่ยวกับคำขอจำนวนมากผ่าน aiohttp ที่นี่.

ในเรื่องนี้ฉันเริ่มมองหา ทางเลือก และพบมัน! ผู้สร้างขึ้นฉ่ายโดยเฉพาะอย่างที่ฉันเข้าใจ ถามโซเลม, ถูกสร้าง เฟาสต์เดิมสำหรับโครงการ Robinhood. Faust ได้รับแรงบันดาลใจจาก Kafka Streams และทำงานร่วมกับ Kafka ในฐานะนายหน้า นอกจากนี้ Rockdb ยังใช้เพื่อจัดเก็บผลลัพธ์จากการทำงานของตัวแทนด้วย และที่สำคัญที่สุดคือไลบรารีเป็นแบบอะซิงโครนัส

นอกจากนี้คุณยังสามารถดูได้ การเปรียบเทียบอย่างรวดเร็ว คื่นฉ่ายและเฟาสท์จากผู้สร้างหลัง: ความแตกต่างความแตกต่างระหว่างนายหน้าการดำเนินงานเบื้องต้น ทุกอย่างค่อนข้างง่าย แต่ฟีเจอร์ที่ดีในเฟาสต์ดึงดูดความสนใจ - พิมพ์ข้อมูลเพื่อส่งไปยังหัวข้อ

พวกเราทำอะไร?

ดังนั้น ในบทความชุดสั้นๆ ฉันจะแสดงวิธีรวบรวมข้อมูลจากงานเบื้องหลังโดยใช้ Faust แหล่งที่มาสำหรับโครงการตัวอย่างของเราจะเป็นตามชื่อที่แนะนำ อัลฟ่าแวนเทจ.co. ฉันจะสาธิตวิธีการเขียนเอเจนต์ (ซิงค์ หัวข้อ พาร์ติชัน) วิธีดำเนินการปกติ (cron) คำสั่ง faust cli ที่สะดวกที่สุด (ตัวตัดคำเหนือการคลิก) การทำคลัสเตอร์แบบง่าย และในตอนท้ายเราจะแนบ datadog ( ออกกำลังกายนอกกรอบ) และลองทำอะไรดูดู ในการจัดเก็บข้อมูลที่รวบรวมเราจะใช้ mongodb และ motor สำหรับการเชื่อมต่อ

ป.ล. เมื่อพิจารณาจากความมั่นใจในการเขียนประเด็นการติดตามฉันคิดว่าผู้อ่านในตอนท้ายของบทความที่แล้วจะยังคงมีลักษณะดังนี้:

งานเบื้องหลังเกี่ยวกับเฟาสต์ ตอนที่ XNUMX: บทนำ

ข้อกำหนดของโครงการ

เนื่องจากฉันได้สัญญาไว้แล้ว เรามาสร้างรายการเล็กๆ น้อยๆ ว่าบริการนี้ควรจะทำอะไรได้บ้าง:

  1. อัปโหลดหลักทรัพย์และภาพรวม (รวมถึงกำไรขาดทุน งบดุล กระแสเงินสด - สำหรับปีที่แล้ว) - เป็นประจำ
  2. อัปโหลดข้อมูลย้อนหลัง (สำหรับแต่ละปีการซื้อขาย ค้นหาค่าสุดขีดของราคาปิดของการซื้อขาย) - เป็นประจำ
  3. อัปโหลดข้อมูลการซื้อขายล่าสุด - เป็นประจำ
  4. อัปโหลดรายการตัวบ่งชี้ที่กำหนดเองสำหรับการรักษาความปลอดภัยแต่ละรายการ - เป็นประจำ

ตามที่คาดไว้ เราเลือกชื่อสำหรับโปรเจ็กต์ตั้งแต่เริ่มต้น: ฮอร์ตัน

เรากำลังเตรียมโครงสร้างพื้นฐาน

ชื่อนี้แข็งแกร่งอย่างแน่นอน อย่างไรก็ตาม สิ่งที่คุณต้องทำคือเขียนการกำหนดค่าเล็กน้อยสำหรับนักเทียบท่าเขียนด้วย kafka (และผู้ดูแลสวนสัตว์ - ในคอนเทนเนอร์เดียว), kafdrop (หากเราต้องการดูข้อความในหัวข้อ), mongodb เราได้รับ [นักเทียบท่า-compose.yml](https://github.com/Egnod/horton/blob/562fa5ec14df952cd74760acf76e141707d2ef58/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

ไม่มีอะไรซับซ้อนที่นี่เลย ผู้ฟังสองคนได้รับการประกาศสำหรับคาฟคา: ตัวหนึ่ง (ภายใน) สำหรับการใช้งานภายในเครือข่ายคอมโพสิต และตัวที่สอง (ภายนอก) สำหรับการร้องขอจากภายนอก ดังนั้นพวกเขาจึงส่งต่อออกไปข้างนอก 2181 — ท่าเรือผู้ดูแลสวนสัตว์ ฉันคิดว่าส่วนที่เหลือมีความชัดเจน

การเตรียมโครงกระดูกของโครงการ

ในเวอร์ชันพื้นฐาน โครงสร้างของโครงการของเราควรมีลักษณะดังนี้:

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 *

*ทุกสิ่งที่ฉันสังเกต เราไม่ได้แตะต้องมัน เราแค่สร้างไฟล์เปล่า**

เราสร้างโครงสร้าง ตอนนี้เรามาเพิ่มการขึ้นต่อกันที่จำเป็น เขียนการกำหนดค่าและเชื่อมต่อกับ mongodb ฉันจะไม่ให้ข้อความเต็มของไฟล์ในบทความเพื่อไม่ให้เกิดความล่าช้า แต่ฉันจะให้ลิงก์ไปยังเวอร์ชันที่จำเป็น

เริ่มต้นด้วยการพึ่งพาและเมตาเกี่ยวกับโครงการ - pyproject.toml

ต่อไป เราจะเริ่มการติดตั้งการพึ่งพาและสร้าง virtualenv (หรือคุณสามารถสร้างโฟลเดอร์ venv ด้วยตัวเองและเปิดใช้งานสภาพแวดล้อม):

pip3 install poetry (если ещё не установлено)
poetry install

ตอนนี้เรามาสร้างกัน config.yml - ข้อมูลประจำตัวและสถานที่ที่จะเคาะ คุณสามารถวางข้อมูลสำหรับ alphavantage ได้ทันที เอาล่ะ เรามาต่อกันที่ config.py — แยกข้อมูลสำหรับแอปพลิเคชันจากการกำหนดค่าของเรา ใช่ ฉันสารภาพ ฉันใช้ lib ของฉัน - sitri.

เมื่อเชื่อมต่อกับ Mongo ทุกอย่างค่อนข้างง่าย ประกาศแล้ว คลาสลูกค้า เพื่อเชื่อมต่อและ คลาสพื้นฐาน สำหรับ cruds เพื่อให้ง่ายต่อการค้นหาคอลเลกชัน

จะเกิดอะไรขึ้นต่อไป?

บทความนี้ไม่ได้ยาวมาก เนื่องจากที่นี่ฉันแค่พูดถึงแรงจูงใจและการเตรียมตัวเท่านั้น ดังนั้นอย่าโทษฉันเลย ฉันสัญญาว่าส่วนต่อไปจะมีฉากแอ็คชั่นและกราฟิก

ดังนั้นในส่วนถัดไปนี้ เรา:

  1. มาเขียนไคลเอนต์ขนาดเล็กสำหรับ alphavantage บน aiohttp พร้อมคำขอปลายทางที่เราต้องการ
  2. เรามาสร้างตัวแทนที่จะรวบรวมข้อมูลหลักทรัพย์และราคาย้อนหลังให้พวกเขากันดีกว่า

รหัสโครงการ

รหัสสำหรับส่วนนี้

ที่มา: will.com

เพิ่มความคิดเห็น