الخلاصة

  • Age تقدير بالثواني منذ أن أنشأ الأصل الاستجابة أو تحقق منها بنجاح، وليس تاريخ إنشاء المورد أو الوثيقة أو البايتات التي تعرضها.
  • يضم المخبأ قيمة Age الواردة إلى Date وتوقيت الطلب والاستجابة والتأخير ومدة الإقامة المحلية، ثم يستبدل الحقل بقيمة current_age واحدة عندما يعيد استخدام الاستجابة من دون تحقق.
  • الحداثة حساب مستقل: يقارن العمر الحالي بعمر صلاحية مصدره توجيهات التخزين أو Expires أو قاعدة تقديرية مسموحة. لا يثبت الرقم تحققاً ولا يمنح وحده إذن إعادة الاستخدام.

قد تكون الاستجابة حديثة والنص قديماً

لنفترض أن دليلاً نُشر قبل أربع سنوات وبقيت كلماته كما هي. سأل المخبأ خادم الأصل قبل دقيقتين إن كانت نسخته ما تزال صالحة، فأكدها الأصل. عندئذ تكون Age: 120 صحيحة للاستجابة المقترحة لإعادة الاستخدام، لكنها لا تصلح وصفاً لعمر الدليل.

يأتي الالتباس من اللغة اليومية التي تنسب العمر إلى الشيء. في HTTP ينسب الحقل إلى الاستجابة. قد يكون المورد أقدم من الخادم، وقد تمر البايتات نفسها بتحققات كثيرة، وقد تُستبدل خانة التخزين أو تُحدّث. لا يحفظ العدد تاريخ أي من هذه الطبقات.

احتاجت المخابئ إلى حقيقة أضيق: كم مضى من الوقت الذي يجب احتسابه قبل اتخاذ قرار استخدام رد مخزن. وإذا بدأ كل وسيط العد من الصفر، صارت الاستجابة أصغر عمراً كلما عبرت وسيطاً جديداً. أما الاعتماد على Date وحده فيجعل اختلاف الساعات جزءاً من القرار.

لم يحمل HTTP/1.0 زمن المخبأ السابق

عرّفت مواصفة HTTP/1.0 سنة 1996 التخزين المؤقت والتاريخ والانتهاء، لكن قائمة ترويسات الاستجابة فيها لم تشمل Age، ولم توجد خوارزمية مشتركة تنقل الزمن المتراكم. كان في وسع كل تطبيق استعمال Date وExpires ووقت وصوله، لكنه لم يتلق رقماً معيارياً يصف إقامة الاستجابة عند غيره.

إذا احتفظ المخبأ الأول بالاستجابة ثمانين ثانية ثم أرسلها إلى مخبأ ثان، ضاعت تلك الثواني إن أعاد الثاني العد. وإذا طرح الثاني تاريخ الأصل من ساعته، فقد ينتج عن انحراف الساعتين عمر سالب أو مبالغ فيه.

أدخل HTTP/1.1 ترويسة Age سنة 1997. يرسل المخبأ تقديره، ويصححه المستقبل ويضيف إليه. وقد وضعت المواصفة المبكرة حداً مهماً: بعد نجاح إعادة التحقق يصبح القياس مرتبطاً بوقت التحقق، لا بالضرورة بوقت الاستجابة الأولى. لذلك لم يكن الحقل يوماً تاريخ نشر.

جمع الحساب رؤيتين ناقصتين

يحسب المخبأ أولاً عمراً ظاهراً من وقت الاستلام وDate:

apparent_age = max(0, response_time - date_value)

يمنع الصفر ساعة أصل متقدمة من إنتاج عمر سالب، لكن الحساب يظل معتمداً على ساعتين مختلفتين.

وتأتي الرؤية الثانية من Age الموروث مضافاً إليه زمن الطلب والاستجابة المحلي:

response_delay = response_time - request_time

corrected_age_value = age_value + response_delay

لا تحتاج هذه الطريقة إلى طرح ساعتين بعيدتين، لكنها تعتمد على أن تكون المخابئ السابقة قد أدرجت Age على الوجه الصحيح. قد يخفي وسيط قديم جزءاً من الزمن.

للتوافق المحافظ يمكن أخذ القيمة الأكبر:

corrected_initial_age = max(apparent_age, corrected_age_value)

تسمح المواصفة الحالية بالقيمة المصححة مباشرة حين لا تكون التطبيقات القديمة مصدر قلق. لم يعيّن البروتوكول ساعة ذات سيادة؛ بل أعطى الشفرة المحلية قاعدة حتمية لموازنة دليلين غير كاملين.

لا يعرف زمن الإقامة إلا من عاشه

بعد وصول الاستجابة قد تبقى في المخبأ دقائق أو ساعات. لا يستطيع السابق معرفة ذلك مسبقاً. يحسبه المخبأ المحلي عند الطلب التالي:

resident_time = now - response_time

current_age = corrected_initial_age + resident_time

وعندما يجيب من التخزين بلا تحقق، يولد Age جديداً ويستبدل القيمة القديمة بعمره الحالي. لا يضيف قائمة بأسماء الوسطاء ولا يحتفظ بسلسلة قيم. يرث المخبأ التالي المجموع ثم يضيف التأخير والإقامة اللذين يراهما.

يحفظ العدد المدة ويهمل الطريق. قد ينتج مخبآن بطيئان الرقم نفسه الذي تنتجه عشرة مخابئ سريعة. لا يمكن استنتاج عدد القفزات أو هوياتها أو ترتيب الحيازة أو إيصالات التسليم. إنه مدخل حساب، لا سلسلة مصدر.

هذا التقليل متعمد: يستطيع المستقبل متابعة القرار من دون الوصول إلى سجلات الجميع. لكنه يعني أيضاً أن التحقيق يحتاج إلى سجلات محلية أغنى من الرقم المنشور.

الحداثة مقارنة بين حسابين

لا تعني Age: 120 أن مئة وعشرين ثانية باقية، ولا أنها مدة الحداثة. العمر هو ما مضى؛ أما عمر الصلاحية فيحدد المدة التي يُسمح فيها بإعادة الاستخدام من دون تحقق:

response_is_fresh = (freshness_lifetime > current_age)

قد يأتي الحد من s-maxage أو max-age أو الفرق بين Expires وDate، أو من تقدير مسموح. يكون العمر 120 حديثاً أمام حد 300، وقديماً في منطق المخبأ أمام حد 60.

ولا تعني stale أن المحتوى كاذب أو ضار أو قديم تحريرياً. إنها نتيجة فشل مقارنة الحداثة العادية. يمكن للتحقق أن يجدد أساس الاستخدام، وقد تسمح توجيهات أو حالة انقطاع بخدمة استجابة stale. وفي المقابل قد تكون استجابة صغيرة العمر غير قابلة للتخزين أو تخص متغيراً آخر.

اختيار الاستجابة وحساب العمر وعمر الصلاحية وإذن الاستخدام أربع مسائل. تحويل رقم واحد إلى حل لها جميعاً يضيف سلطة لم يحددها البروتوكول.

أعاد التحقق ضبط المرجع لا التاريخ

يمكن أن يحتفظ المخبأ بالبايتات نفسها بعد أن يؤكد الأصل صلاحيتها. يصبح أساس عمر الاستجابة هو التحقق الناجح، من دون أن تتغير الوثيقة. لذلك لا يثبت انخفاض Age أن المحتوى عُدّل، كما لا يثبت ارتفاعه أن الأصل متوقف.

لا يحمل الحقل ETag الذي قورن، ولا حالة جواب التحقق، ولا الترويسات التي حُدثت. يجب حفظ معاملة التحقق مستقلة. وجود Age يسمح باستنتاج أضيق: الاستجابة ليست مباشرة من الأصل، بل أنشأها مخبأ من حالة مخزنة. ولا يكشف الحقل وحده هل تحقق ذلك المخبأ لدى الأصل أثناء هذا الطلب أم اعتمد على تحقق سابق. أما غيابه فلا يثبت الاتصال بالأصل؛ فقد يغفله مخبأ قديم أو تطبيق مخالف أو نظام جمع ناقص.

قيمة التشبع ليست قياساً تاريخياً

القيمة عدد صحيح غير سالب بالثواني، وعلى المخبأ تجاهل الصيغة غير الصالحة. إذا تجاوز العدد أو الحساب قدرة التمثيل، تحتفظ المواصفات باتفاق 2147483648 أو أكبر عدد موجب مناسب.

يمثل ذلك ما يشبه اللانهاية العملية، أكثر من 68 سنة، كي لا يحول الفيض زمناً ضخماً إلى عدد صغير أو سالب. لا يشهد بأن الاستجابة أقامت هذه المدة بدقة.

لا يكفي الناتج لتفسير القرار

يجب أن يحتفظ سجل التحقيق بمفتاح المخبأ والمتغير المختار، وDate وAge والتوجيهات والمحققات الواردة، وأوقات الطلب والاستجابة والقرار على الساعة المحلية نفسها، وكل قيمة وسيطة، ومصدر عمر الصلاحية. ويسجل أيضاً التحقق ونتيجته وهل كان الاستخدام حديثاً أو بعد تحقق أو stale مسموحاً أو فشلاً.

الاحتفاظ بالعدد الأخير وحده يمحو الفرق بين إقامة سابقة وعبور وإقامة محلية وتصحيح ساعة. رفض HTTP إنشاء سلطة زمنية مركزية؛ الأصل يرسل بياناته، وكل مخبأ يختار ويقيس ويحسب ويتحمل نتيجة الاستخدام، ثم يواصل التالي. نسق الحقل التنسيق الأدنى، ولم يملك الكائن أو حقيقته.

المصادر