پرش به محتوای اصلی
SS·

شرح فنی

crypto_service

سرویس جمع‌وجور پایش بلادرنگ قیمت: ورودی WebSocket، تسک‌های Celery با زمان‌بندی پویا در میانه و ارسال push مبتنی بر Redis در خروجی.

زمینه

این پروژه را سال ۲۰۲۲، زمانی که داشتم در جنگوی رویدادمحور عمیق می‌شدم، ساختم — سرویسی عمداً جمع‌وجور که به یک سؤال، خوب پاسخ می‌دهد: چطور دادهٔ بازار را به‌صورت زنده به کلاینت‌های متصل برسانیم، بدون آن‌که هر کلاینت مدام یک API خارجی را بمباران کند؟

مسئله

کاربر می‌خواهد یک جفت‌ارز را زیر نظر بگیرد و بداند آخرین کندل یک‌دقیقه‌ای بالاتر یا پایین‌تر از قیمت هدف بسته شده است. راه سرراست — یعنی polling هر مرورگر به سمت صرافی — درخواست‌های تکراری را چند برابر می‌کند و خیلی زود به سقف rate limit می‌خورد. نسخهٔ درست، زمان‌بندی را به سمت سرور می‌برد و نتیجه را push می‌کند.

سازوکار

  • مرورگر یک WebSocket (با Django Channels) باز می‌کند و نماد و قیمت هدف را می‌فرستد.
  • Consumer یک تسک دوره‌ای Celery Beat را به‌صورت پویا ثبت می‌کند که به گروه کانال همان اتصال گره خورده است — زمان‌بندی این‌جا داده است؛ توسط اتصال ساخته و مدیریت می‌شود، نه این‌که در کد ثابت باشد.
  • هر دقیقه، یک worker سلری آخرین کندل یک‌دقیقه‌ای را از Binance API می‌گیرد و قیمت بسته‌شدن را با هدف مقایسه می‌کند.
  • نتیجه از طریق لایهٔ کانال Redis به گروه WebSocket می‌رسد و به‌صورت پیام push در مرورگر می‌نشیند — بدون هیچ polling سمت کلاینت.
  • فهرست نمادهای قابل معامله در Redis کش می‌شود تا رابط کاربری هرگز برای دادهٔ ایستا منتظر صرافی نماند.

تصمیم‌ها و محدودیت‌های صادقانه

  • زمان‌بندی به‌مثابهٔ داده. استفاده از زمان‌بندی مبتنی بر دیتابیسِ django-celery-beat یعنی می‌توان تسک‌ها را در زمان اجرا و به‌ازای هر اتصال ساخت — الگویی که از نظر مفهومی به سیستم‌های هشدارِ به‌ازای هر کاربر مقیاس می‌یابد.
  • تفکیک تمیز مسئولیت‌ها. انتقال (Channels)، پردازش (Celery) و وضعیت (Redis) هر کدام در جای خودشان می‌مانند؛ consumer هیچ‌وقت مستقیم با Binance حرف نمی‌زند.
  • محدودیت‌های شناخته‌شده، به اقتضای دامنهٔ پروژه: این یک دموی تک‌اپلیکیشنی است — نسخهٔ production باید تسک‌ها را به‌ازای هر نماد یکتا کند، زمان‌بندی‌ها را هنگام قطع اتصال پاک کند و دور کلاینت صرافی retry و backoff بگذارد. دیدن همین شکاف‌ها بخشی از چیزی است که این پروژه به من یاد داد.

چه چیزی را نشان می‌دهد

اسکلت یک سیستم مبتنی بر پیام — ورودی سوکت، کار زمان‌بندی‌شدهٔ پس‌زمینه و توزیع مبتنی بر صف — دقیقاً همان شکلی که بعدها پایپ‌لاین بلادرنگ داده‌های بازار را به‌صورت حرفه‌ای در ماهدا ساختم.