Repository navigation
FA Serverless
زبان: English · فارسی
pulsecheck روی Vercel (cron job بهعلاوهی تابع پایتون) و Cloudflare Workers (cron trigger بهعلاوهی Python Worker) اجرا میشود. هر دو محیط محدودند و بعضی قابلیتها در آنها نیست. این صفحه میگوید چه چیزی کار میکند، محدودیتهای مهم چیست (هم از مستندات خود پلتفرمها و هم از deployهای واقعی) و چطور راه بیندازیدش.
کپی deployشدهی خودتان را خصوصی نگه دارید. تنظیماتی که deploy میکنید نام سرورهای شما را دارد. از یک مخزن خصوصی یا یک پوشهی محلی deploy کنید، نه از قالب عمومی.
-
Cloudflare: با
cf deploydeploy شد و از cron trigger خودش هر ۵ دقیقه اجرا شد. سایتها را بررسی کرد، وضعیت را در KV نوشت، یک یادآوری را از راه وبهوک فرستاد (HTTP 200) و در Workers Logs لاگ زد. یک هشدار به ntfy.sh جواب 429 گرفت و بدون اینکه اجرا متوقف شود بهصورتnotify failedلاگ شد. -
Vercel: deploy شد؛ endpoint بدون secret جواب 401 داد و با secret درست تنظیمات را خواند. یک تابع هم shoutrrr واقعی را دانلود و اجرا کرد و پیام فرستاد. با یک Upstash Redis واقعی، دو اجرای اجباری هر دو سایت را بررسی کردند، وضعیت بین اجراها ماند، هشدار از راه وبهوک رفت و
/api/statusوضعیت را از Redis خواند (?format=textو?tag=). - handler مربوط به Vercel و خود Worker در تستهای خودکار هم با دادهی ساختگی اجرا میشوند.
| قابلیت | CLI / CI / cron | Vercel | Cloudflare Worker |
|---|---|---|---|
| بررسی HTTP | بله | بله | بله |
| انقضای گواهی TLS | بله | بله |
خیر (fetch گواهی را نشان نمیدهد) |
| بررسی TCP | بله | بله | خیر (رد میشود) |
ip_version (اجبار IPv4 یا IPv6) |
بله | بله، اگر تابع آن اتصال را داشته باشد (تست نشده) | خیر (این سایتها رد میشوند) |
| بررسی ping | بله |
خیر (تابع برنامهی ping ندارد) |
خیر (رد میشود) |
| هشدار | همهی سرویسهای shoutrrr | ارسالکنندهی داخلی برای ۱۲ سرویس، و برای بقیه shoutrrr واقعی که در اولین استفاده دانلود میشود | فقط ارسالکنندهی داخلی برای ۱۲ سرویس (فهرست) |
| ذخیرهی وضعیت | فایل SQLite | Upstash Redis (REST) | Workers KV |
status |
دستور | GET /api/status |
GET /status |
خروجی OpenTelemetry، messages، برچسب، یادآوری، maintenance |
بله | بله | بله |
| گزارش با p95 | بله | خیر (درصد آپتایم و میانگین؛ ۹۰ روز) | خیر (همان) |
سایتهایی که رد میشوند در لاگ اجرا فهرست میشوند. روی Cloudflare max_redirects نادیده گرفته میشود، چون fetch ریدایرکت را با حد خودش دنبال میکند.
| محدودیت | مقدار | کاری که کردهایم |
|---|---|---|
| تناوب cron | Hobby: روزی یکبار، در هر لحظهی آن ساعت. Pro و Enterprise: هر دقیقه |
vercel.json با زمانبندی روزانه میآید تا روی هر پلنی deploy شود. روی Pro مقدار */5 * * * * را بگذارید. روی Hobby از workflow گیتهاب trigger-vercel.yml استفاده کنید (پایینتر). |
| تحویل cron | تضمینی نیست: ممکن است اجرایی از دست برود یا دوبار انجام شود؛ تلاش مجدد ندارد و ریدایرکت را دنبال نمیکند | اجراها تکرارپذیرند، اما گاهی فاصلهی بیاجرا ممکن است. |
| پایتون | Vercel نسخههای ۳٫۱۲ (پیشفرض)، ۳٫۱۳ و ۳٫۱۴ را دارد. .python-version ما (۳٫۱۵) build را خراب کرد (No interpreter found for Python 3.15). خود تابع روی ۳٫۱۲٫۱۴ اجرا شد |
در vercel.json مقدار build.env.UV_PYTHON=3.14 گذاشته شده. کد روی ۳٫۱۲ هم کار میکند. |
| مدت اجرا، حافظه، حجم بسته | پیشفرض ۳۰۰ ثانیه (حداکثر Hobby برابر ۳۰۰ و Pro برابر ۸۰۰)؛ ۲ گیگ (در Pro تا ۴ گیگ)؛ ۵۰۰ مگابایت برای بستهی پایتون | برای این کار بیش از کافی است. |
| File descriptor | ۱۰۲۴ عدد، مشترک بین همهی اجراهای همزمان | بررسیها دستههای ۲۰ تایی اجرا میشوند. |
دیسک، Docker، ping
|
/tmp قابل نوشتن است؛ Docker و برنامهی ping نیست |
وضعیت در Redis میماند؛ shoutrrr فقط وقتی آدرس هشداری لازمش داشته باشد در /tmp دانلود میشود (با بررسی SHA-256). |
| حجم deploy | یک فایل ۲۰ مگابایتی در بسته باعث شد vercel deploy روی یک اتصال کند بیش از ۲۵ دقیقه گیر کند |
چیز بزرگی آپلود نمیشود؛ فایل اجرایی هنگام اجرا دانلود میشود. |
| IP خروجی | پویا | بدون IP ثابتِ پولی Vercel نمیشود IP مانیتور را در allow-list گذاشت. |
vercel dev |
cron job اجرا نمیکند | endpoint را خودتان صدا بزنید. |
پلن رایگان Upstash ماهی ۵۰۰ هزار دستور و ۲۵۶ مگابایت میدهد. هر اجرا ۲ دستور مصرف میکند، یعنی با زمانبندی ۵ دقیقهای حدود ۱۷ هزار دستور در ماه.
| محدودیت | مقدار | کاری که کردهایم |
|---|---|---|
| ابزار deploy | CLI جدید cf (بتا) هنوز نمیتواند Python Worker بسازد، چون بستهی dev server پایتونش منتشر نشده. cf deploy --prebuilt اما خروجی دستساز را قبول میکند |
deploy/cloudflare/build.py خروجی Build Output را مینویسد و cf deploy --prebuilt آن را آپلود میکند. |
| ماژولها | در Python Worker فقط ماژول اصلی import میشود؛ فایلها و بستههای دیگر در محیط واقعی import نشدند |
build.py کل پکیج را در یک entry.py میگذارد. |
| بستهها | Pyodide (پایتون ۳٫۱۳ روی WebAssembly). نمایهی بستههای Pyodide از بعضی شبکهها در دسترس نبود | Worker هیچ بستهی شخص ثالثی ندارد. YAML هنگام build به JSON تبدیل میشود. |
scheduled(controller, env, ctx) |
آرگومان env هنگام اجرا None است (در لاگها دیده شد) |
Worker از self.env استفاده میکند. |
| thread، subprocess، socket | قابل استفاده نیست | فقط asyncio و fetch هست؛ پس بررسی TCP، ping و انقضای TLS ندارد. |
| CPU | مستندات: رایگان ۱۰ میلیثانیه برای هر اجرای cron، پولی ۳۰ ثانیه. اجرای دو سایت حدود ۲۴ میلیثانیه CPU مصرف کرد و بدون خطا تمام شد | حسابی که با آن تست کردیم بدون مشکل اجرا کرد (پلن آن را بررسی نکردیم). برای استفادهی واقعی پلن پولی (۵ دلار در ماه) را در نظر بگیرید. |
| راهاندازی | هنگام deploy بین ۰٫۶ تا ۱٫۱ ثانیه گزارش شد | فقط در هر cold start یکبار است، نه برای هر سایت. |
| subrequest | رایگان ۵۰، پولی ۱۰٬۰۰۰ در هر اجرا | هر سایت، هشدار، فراخوانی KV و ارسال تلمتری یکی حساب میشود. در پلن رایگان زیر حدود ۴۰ سایت بمانید. |
| اتصال همزمان | ۶ | بررسیها دستههای ۶ تایی اجرا میشوند. |
| cron trigger | رایگان ۵ تا برای کل حساب، پولی ۲۵۰ تا؛ به وقت UTC؛ اعمال تغییرها ممکن است چند دقیقه طول بکشد | – |
| KV | رایگان: ۱۰۰۰ نوشتن در روز (هر اجرا یک نوشتن دارد؛ cron پنجدقیقهای ۲۸۸ نوشتن در روز میشود و cron یکدقیقهای پلن پولی میخواهد) | – |
| workers.dev | درخواستها از ماشین تست به Worker میرسید (لاگ میزد) ولی پاسخ برنمیگشت؛ برای همین /status و /run فقط با دادهی ساختگی تست شدند |
از دامنهی خودتان استفاده کنید، یا از شبکهی دیگری امتحان کنید. |
- در یک fork یا clone خصوصی از کل مخزن (قالب حداقلی فایلهای Vercel و Cloudflare را ندارد)،
pulsecheck.example.ymlرا بهpulsecheck.ymlکپی کنید، ویرایشش کنید (برای رمزها${VAR}) و commit بزنید. - دستور
vercelرا اجرا کنید (یا مخزن را در داشبورد import کنید). Vercel خودشapp.pyرا پیدا میکند. - ذخیرهساز وضعیت:
vercel integration add upstash/upstash-kv. بار اول لینکی که چاپ میشود را باز کنید، شرایط Upstash را بپذیرید و دستور را دوباره اجرا کنید. این کارKV_REST_API_URLوKV_REST_API_TOKENرا به پروژه اضافه میکند (UPSTASH_REDIS_REST_URLوUPSTASH_REDIS_REST_TOKENهم پذیرفته میشود). - متغیرهای محیطی:
CRON_SECRET(تصادفی و دستکم ۱۶ کاراکتر؛ Vercel آن را بهشکلAuthorization: Bearer …میفرستد و endpointها هر درخواست دیگری را رد میکنند) و هر${VAR}که در YAML به کار بردهاید. - زمانبندی:
vercel.jsonرا ویرایش کنید. روی Pro:"schedule": "*/5 * * * *". روی Hobby همان زمانبندی روزانه را نگه دارید و از.github/workflows/trigger-vercel.ymlاستفاده کنید (متغیر گیتهابVERCEL_CRON_URLبرابرhttps://<project>.vercel.app/api/cronو secret به نامCRON_SECRET). -
vercel --prodرا اجرا کنید و بعدcurl -H "Authorization: Bearer $CRON_SECRET" https://<project>.vercel.app/api/cronرا بزنید (با?force=1یا?tag=x). وضعیت در/api/status?format=mdاست. اگر Deployment Protection جلوی curl را گرفت، ازvercel curl /api/cronاستفاده کنید.
-
npm install --global cfو بعدcf auth login.uvهم لازم است. -
pulsecheck.example.ymlرا بهpulsecheck.ymlکپی و ویرایش کنید (سایتهای HTTP؛ آدرسهای هشدار از فهرست داخلی). - هر
${VAR}که YAML به کار برده را export کنید، و اگر/statusو/runرا میخواهیدSTATUS_TOKENرا هم. -
deploy/cloudflare/deploy.sh pulsecheck.ymlرا اجرا کنید (گزینهها:--cron "*/5 * * * *"و--name pulsecheck). اولین deploy فضای KV به اسم<name>-stateرا میسازد و deployهای بعدی از همان استفاده میکنند. secretها در هر deploy از محیط شما آپلود میشوند. - لاگها:
cf o11y telemetry query --query-id q --view events --limit 20 --timeframe-from <ms> --timeframe-to <ms> --parameters-datasets cloudflare-workers --parameters-order-by-value timestamp --parameters-order-by-order desc. - وضعیت:
cf kv keys get pulsecheck --namespace-id <id> --text. اگر اجرایی کرش کند، دلیلش زیر کلیدpulsecheck-errorمیماند. - endpointها (با هدر
Authorization: Bearer $STATUS_TOKEN):GET /status?format=text|md|json&tag=xوGET /run?force=1&tag=x.
داخل mappingهای درونخطی { ... } هر مقداری که ${VAR} دارد را در کوتیشن بگذارید: {name: api, url: "https://x.example.com/${TOKEN}"}.