سی‌دی‌ان چیست و چه زمانی واقعاً سرعت سایت را بیشتر می‌کند

سی‌دی‌ان چیست و چه زمانی واقعاً سرعت سایت را بیشتر می‌کند

صفحه‌ی اول سایت بعد از وصل‌کردن سی‌دی‌ان سبک شد. ولی داشبورد کاربری همان‌قدر کند مانده. این شکایت را زیاد می‌شنویم، و تقصیر سی‌دی‌ان نیست؛ سی‌دی‌ان دارد دقیقاً همان کاری را می‌کند که از آن برمی‌آید و نه یک قدم بیشتر.

این نوشته برای کسی است که سرور دارد. می‌خواهد بداند سی‌دی‌ان چه چیزی را سریع می‌کند، چه چیزی را نه، و چطور با یک دستور ساده ثابت کند پاسخ از کش لبه آمده یا از سرور اصلی. در پایان هم راه‌اندازی روی سی‌دی‌ان ابریشم را گام‌به‌گام می‌آوریم.

سی‌دی‌ان دقیقاً چه کار می‌کند

سی‌دی‌ان یک شبکه‌ی کش توزیع‌شده است. یک نسخه از فایل‌های سایت شما را روی نودهایی در نقاط مختلف نگه می‌دارد و درخواست هر کاربر را به نزدیک‌ترین نود می‌فرستد. فایل از جای نزدیک می‌آید، پس هم مسافت شبکه کوتاه‌تر است هم سرور اصلی شما درگیر نمی‌شود.

کلمه‌ی کلیدی «کش» است. سی‌دی‌ان فقط چیزی را سریع می‌کند که بتواند نگه دارد و بین کاربران مختلف به اشتراک بگذارد. تصویر، فایل CSS و JS، فونت، ویدیوی استاتیک: اینها یک‌بار تولید می‌شوند و برای همه یکسان‌اند. اینجا سی‌دی‌ان می‌درخشد.

حالا صفحه‌ی داشبورد یک کاربر لاگین‌شده را در نظر بگیرید. محتوایش برای هر کاربر فرق دارد، با هر درخواست دوباره از دیتابیس ساخته می‌شود، و معمولاً کوکی نشست همراهش است. چنین پاسخی را یک کش مشترک نباید نگه دارد. RFC 9111 دستور private را همین‌طور تعریف می‌کند: پاسخ برای یک کاربر است و «کش مشترک نباید آن را ذخیره کند». پس سی‌دی‌ان آن را دست‌نخورده به سرور شما پاس می‌دهد. سرعتش همان سرعت سرور اصلی می‌ماند.

نتیجه ساده است. اگر کندی سایت شما از صفحات داینامیک و کوئری‌های سنگین دیتابیس می‌آید، سی‌دی‌ان آن را حل نمی‌کند. آن مشکل روی خودِ سرور حل می‌شود: کش نرم‌افزاری، ایندکس دیتابیس، یا یک سرور قوی‌تر.

مرورگر کاربرنود سی‌دی‌ان(کش لبه)سرور اصلیدرخواستفقط هنگام MISSHIT: پاسخ از همین نود برمی‌گردد

در HIT پاسخ از نود لبه برمی‌گردد و اصلاً به سرور اصلی نمی‌رسد. خط‌چین فقط وقتی برقرار می‌شود که فایل در کش نباشد.

کش چطور تصمیم می‌گیرد چیزی را نگه دارد

این تصمیم با شماست، نه با سی‌دی‌ان. سرور اصلی شما با هدرهای پاسخ می‌گوید هر فایل را چطور کش کنند. مهم‌ترین هدر Cache-Control است.

چند دستور که هر روز به‌کارتان می‌آید:

دستورمعنی
max-age=Nتا N ثانیه پاسخ «تازه» است و بدون پرسش از سرور قابل استفاده.
publicکش مشترک (سی‌دی‌ان) مجاز است ذخیره‌اش کند.
privateفقط کش مرورگر؛ سی‌دی‌ان نباید نگهش دارد. برای محتوای شخصی.
no-storeهیچ کشی حق ذخیره ندارد. برای پاسخ‌های حساس.
immutableتا انقضا اصلاً اعتبارسنجی نکن. برای فایل نسخه‌دار.

الگوی درست روشن است. فایل‌های ثابت که اسمشان نسخه دارد را طولانی کش کنید. طبق راهنمای web.dev برای دارایی‌های نسخه‌دار Cache-Control: public, max-age=31536000, immutable پیشنهاد می‌شود، یعنی یک سال. برای HTML و صفحات داینامیک برعکس: no-cache یا private تا هر بار اعتبارسنجی شود.

روی nginx این تفکیک چند خط است:

location ~* \.(css|js|woff2|png|jpg|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}

location /dashboard {
add_header Cache-Control "private, no-store";
}

یک نکته‌ی عملی: اگر فایل‌های ثابت را با max-age طولانی کش می‌کنید، حتماً اسمشان را نسخه‌دار کنید (مثل app.v3.css). وگرنه بعد از آپدیت، کاربران تا یک سال نسخه‌ی قدیمی را می‌بینند.

ETag و پاسخ ۳۰۴

وقتی عمر یک فایل در کش تمام می‌شود، لازم نیست کل فایل دوباره دانلود شود. سرور یک ETag می‌دهد، یعنی یک اثر انگشت از نسخه‌ی فعلی فایل. کش دفعه‌ی بعد همان مقدار را در هدر If-None-Match پس می‌فرستد. اگر فایل عوض نشده باشد، سرور فقط 304 Not Modified می‌دهد، بدون بدنه. چند بایت به‌جای چند صد کیلوبایت.

چرا نرخ hit مهم‌ترین عدد است

نرخ hit یعنی چند درصد درخواست‌ها از کش لبه پاسخ گرفتند و به سرور شما نرسیدند. این عدد تمام ارزش سی‌دی‌ان را خلاصه می‌کند. hit بالا یعنی کاربر سریع پاسخ گرفت و سرور اصلی بیکار ماند. hit پایین یعنی سی‌دی‌ان فقط یک واسطه‌ی اضافه شده و تقریباً هیچ.

نرخ hit پایین معمولاً یک علت دارد: هدرهای سرور شما به سی‌دی‌ان اجازه‌ی کش نمی‌دهند. یا همه‌جا private فرستاده‌اید، یا کوکی را روی فایل‌های ثابت هم ست کرده‌اید. کلادفلر در مستنداتش می‌گوید اگر پاسخ مبدأ Set-Cookie داشته باشد یا هدرهایش غیرقابل‌کش باشند، وضعیت BYPASS می‌شود؛ یعنی فایل از کنار کش رد شد و مستقیم از سرور آمد. پس قبل از اینکه سی‌دی‌ان را مقصر بدانید، هدرهای خودتان را نگاه کنید.

با curl ببین پاسخ از کش آمده یا از سرور

اینجا جایی است که حدس تبدیل به واقعیت می‌شود. یک درخواست فقط-هدر بزنید:

curl -I https://example.com/assets/app.v3.css

خروجی چیزی شبیه این است:

HTTP/2 200
cache-control: public, max-age=31536000, immutable
etag: "7f3a1c9"
age: 842
cf-cache-status: HIT

سه چیز را بخوانید. اول وضعیت کش: اینجا cf-cache-status: HIT یعنی فایل از نود لبه آمد. نام این هدر بسته به سی‌دی‌ان فرق دارد؛ ممکن است cf-cache-status باشد یا x-cache. دوم هدر age: طبق RFC 9111 این «تخمین زمان سپری‌شده از وقتی پاسخ تولید شده» است. عدد بزرگ‌تر از صفر یعنی این نسخه مدتی است در کش نشسته. سوم cache-control: همان چیزی که سرور شما گفته و کش به آن عمل کرده.

حالا یک صفحه‌ی داینامیک را تست کنید:

curl -I https://example.com/dashboard
HTTP/2 200
cache-control: private, no-store
cf-cache-status: DYNAMIC
set-cookie: sid=...; HttpOnly

وضعیت DYNAMIC یعنی سی‌دی‌ان تشخیص داد این پاسخ قابل‌کش نیست و دست‌نخورده از سرور رد کرد. این خطا نیست؛ این دقیقاً رفتار درست برای یک صفحه‌ی شخصی است. اگر اینجا HIT می‌دیدید، باید نگران می‌شدید که داشبورد یک کاربر به کاربر دیگری نشان داده شود.

اعتبارسنجی ۳۰۴ را هم می‌شود دستی آزمود. ETag را از پاسخ قبلی بردارید و پس بفرستید:

curl -I -H 'If-None-Match: "7f3a1c9"' https://example.com/assets/app.v3.css

اگر فایل عوض نشده باشد، جواب HTTP/2 304 است، بدون بدنه. این یعنی زنجیره‌ی اعتبارسنجی سالم کار می‌کند.

یک تست مفید دیگر: همان URL ثابت را دوبار پشت سر هم بزنید. بار اول ممکن است MISS ببینید (هنوز در کش آن نود نبود) و بار دوم HIT. اگر همیشه MISS می‌ماند، هدرهای Cache-Control مبدأ را بازبینی کنید.

راه‌اندازی روی سی‌دی‌ان ابریشم، گام‌به‌گام

سی‌دی‌ان ابریشم نودهایی در شیراز و تهران برای ترافیک داخلی و نودهایی در انگلستان، سوئد و هلند دارد، و در نسخه‌ی بتا پلن رایگان ارائه می‌شود. مسیر راه‌اندازی:

  1. دامنه را در پنل اضافه کنید. سی‌دی‌ان رکوردهای DNS فعلی شما را به‌صورت خودکار مهاجرت می‌دهد، پس چیزی را دستی از نو نمی‌سازید.
  2. nameserver دامنه را به مقدار اعلام‌شده در پنل تغییر دهید. تا انتشار کامل DNS صبر کنید.
  3. صدور SSL رایگان را بررسی کنید. گواهی برای دامنه‌ی شما صادر و تمدید می‌شود، بدون هزینه. تا سبزشدن وضعیت گواهی صبر کنید.
  4. هدرهای کش را روی سرور اصلی تنظیم کنید. همان الگوی nginx بالا: ثابت‌ها public, max-age، صفحات شخصی private یا no-store. این مهم‌ترین قدم است و روی خود سرور شما انجام می‌شود.
  5. با curl تست کنید. یک فایل ثابت باید در بار دوم HIT بدهد؛ یک صفحه‌ی لاگین‌شده باید DYNAMIC بماند.
  6. بعد از هر آپدیت، کش را پاک کنید. پنل دکمه‌ی پاک‌سازی یک‌کلیکی دارد. اگر فایل‌ها را نسخه‌دار کرده باشید، حتی به این هم کمتر نیاز دارید.


یک هشدار صادقانه: اگر کل سایت شما پشت لاگین است و هیچ فایل ثابت قابل‌اشتراکی ندارد، سی‌دی‌ان سرعت محسوسی به شما نمی‌دهد. در آن حالت سراغ تقویت سرور بروید، نه سی‌دی‌ان.

کجا اجرا کنیم

اگر مخاطب شما داخل ایران است، نودهای داخلی مهم‌اند؛ سی‌دی‌ان ابریشم با نودهای شیراز و تهران فایل‌های ثابت را از داخل کشور سرو می‌کند و فشار را از سرور اصلی برمی‌دارد. ولی سی‌دی‌ان جای یک سرور مبدأ خوب را نمی‌گیرد. بخش داینامیک همچنان روی مبدأ اجرا می‌شود، و اگر مخاطب داخلی دارید، یک سرور مجازی ایران در شیراز آن پاسخ‌های کش‌نشدنی را هم نزدیک کاربر نگه می‌دارد. برای سنجش تأخیر همین مسیر، راهنمای ما درباره‌ی کاهش پینگ و تأخیر سرور مجازی کمک می‌کند.

منابع

  1. HTTP caching - MDN Web Docs (unknown)
  2. RFC 9111: HTTP Caching (2022-06)
  3. Cache responses (CF-Cache-Status) - Cloudflare Docs (unknown)
  4. Prevent unnecessary network requests with the HTTP Cache - web.dev (unknown)

پرسش‌های پرتکرار

سی‌دی‌ان چیست و چه کاری می‌کند؟

سی‌دی‌ان یک شبکه‌ی کش توزیع‌شده است که نسخه‌ای از فایل‌های ثابت سایت (تصویر، CSS، JS، فونت) را روی نودهای نزدیک کاربر نگه می‌دارد. درخواست هر کاربر به نزدیک‌ترین نود می‌رود، پس هم مسافت شبکه کوتاه‌تر است هم سرور اصلی کمتر درگیر می‌شود.

چرا سی‌دی‌ان صفحه‌ی لاگین‌شده را سریع نمی‌کند؟

محتوای صفحه‌ی لاگین‌شده برای هر کاربر فرق دارد و با هر درخواست از دیتابیس ساخته می‌شود، معمولاً با کوکی نشست. طبق RFC 9111 چنین پاسخی private است و کش مشترک نباید آن را ذخیره کند. سی‌دی‌ان آن را دست‌نخورده به سرور شما پاس می‌دهد، پس سرعتش همان سرعت مبدأ می‌ماند.

چطور بفهمم پاسخ از کش آمده یا از سرور؟

با دستور curl -I آدرس را بزنید و هدرها را بخوانید. وضعیت کش را در هدری مثل cf-cache-status یا x-cache می‌بینید: HIT یعنی از کش لبه، MISS یا DYNAMIC یعنی از سرور. هدر age بزرگ‌تر از صفر هم نشان می‌دهد پاسخ مدتی در کش نشسته است.

نرخ hit پایین است، تقصیر سی‌دی‌ان است؟

معمولاً نه. اغلب هدرهای سرور مبدأ اجازه‌ی کش نمی‌دهند: یا همه‌جا private فرستاده‌اید یا روی فایل‌های ثابت Set-Cookie دارید که باعث وضعیت BYPASS می‌شود. اول Cache-Control پاسخ‌های خودتان را بازبینی کنید.

فایل‌های ثابت را چقدر کش کنم؟

برای دارایی‌های نسخه‌دار (مثل app.v3.css) راهنمای web.dev مقدار public, max-age=31536000, immutable یعنی یک سال را پیشنهاد می‌کند. شرطش این است که اسم فایل نسخه داشته باشد تا بعد از آپدیت کاربر نسخه‌ی قدیمی را تا یک سال نبیند.

سفارش سرور مجازی بازگشت به وبلاگ →