التخزين المؤقت عن بُعد

تتناول هذه الصفحة التخزين المؤقت عن بُعد وإعداد خادم لاستضافة ذاكرة التخزين المؤقت، وتشغيل الإصدارات باستخدام ذاكرة التخزين المؤقت عن بُعد.

يستخدم فريق من مطوّري البرامج و/أو نظام التكامل المستمر (CI) ذاكرة التخزين المؤقت عن بُعد لمشاركة مخرجات الإصدار. إذا كان الإصدار قابلاً للتكرار، يمكن إعادة استخدام المخرجات من أحد الأجهزة بأمان على جهاز آخر، ما يجعل الإصدارات أسرع بكثير.

نظرة عامة

تقسّم Bazel مبنى إلى خطوات منفصلة، وتُسمّى إجراءات. ويتضمن كل إجراء مدخلات وأسماء مخرجات سطر أوامر ومتغيرات بيئة. وتتم الإشارة صراحةً إلى المدخلات والمخرجات المطلوبة لكل إجراء.

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

لاستخدام التخزين المؤقت عن بُعد:

  • إعداد خادم كخلفية لذاكرة التخزين المؤقت
  • ضبط إصدار Bazel لاستخدام ذاكرة التخزين المؤقت عن بُعد
  • استخدام الإصدار 0.10.0 من Bazel أو إصدار أحدث

تخزّن ذاكرة التخزين المؤقت عن بُعد نوعين من البيانات:

  • ذاكرة التخزين المؤقت للإجراء، وهي خريطة تجزئات الإجراءات مع البيانات الوصفية لنتيجة الإجراء
  • ملف (CAS) عنوان يتضمن ملفات إخراج المحتوى.

يُرجى العِلم أنّ ذاكرة التخزين المؤقت عن بُعد تحفظ أيضًا ملفَّي stdout وstderr لكل إجراء. وبالتالي، لا يُعدّ فحص stdout/stderr of Bazel إشارة جيدة إلى تقدير نتائج ذاكرة التخزين المؤقت.

كيفية استخدام الإصدار للتخزين المؤقت عن بُعد

بعد إعداد الخادم كذاكرة تخزين مؤقت عن بُعد، يمكنك استخدام ذاكرة التخزين المؤقت بطرق متعددة:

  • القراءة والكتابة في ذاكرة التخزين المؤقت عن بُعد
  • القراءة و/أو الكتابة إلى ذاكرة التخزين المؤقت عن بُعد باستثناء أهداف معيّنة
  • القراءة من ذاكرة التخزين المؤقت عن بُعد فقط
  • عدم استخدام ذاكرة التخزين المؤقت عن بُعد على الإطلاق

عندما تشغِّل إصدارًا من Bazel يمكنه القراءة والكتابة في ذاكرة التخزين المؤقت عن بُعد، يتّبع الإصدار الخطوات التالية:

  1. ينشئ Bazel الرسم البياني للأهداف التي يجب إنشاؤها، ثم ينشئ قائمة بالإجراءات المطلوبة. وقد أعلن كل من هذه الإجراءات عن مصادر الإدخال وأسماء الملفات الصادرة.
  2. يتحقّق Bazel من جهازك المحلي بحثًا عن مخرجات الإصدار الحالية ويعيد استخدام أي نتيجة يعثر عليها.
  3. يتحقّق Bazel من ذاكرة التخزين المؤقت بحثًا عن مخرجات الإصدار الحالية. في حال العثور على الناتج، يسترد Bazel الإخراج. هذه نتيجة ذاكرة تخزين مؤقت.
  4. لتنفيذ الإجراءات المطلوبة في حال عدم العثور على النتائج، ينفِّذ Bazel الإجراءات محليًا وينشئ نتائج الإنشاء المطلوبة.
  5. يتم تحميل مخرجات الإصدار الجديد إلى ذاكرة التخزين المؤقت عن بُعد.

إعداد خادم كخلفية لذاكرة التخزين المؤقت

يجب إعداد خادم ليكون بمثابة خلفية ذاكرة التخزين المؤقت. يمكن أن يتعامل الخادم HTTP/1.1 مع بيانات Bazel&#39 كبايت غامضة، كما يمكن استخدام العديد من الخوادم الحالية كخلفية مؤقتة للتخزين المؤقت. Bazel'sبروتوكول HTTP التخزين المؤقت هو ما يدعم التخزين المؤقت عن بُعد.

تقع على عاتقك مسؤولية اختيار خادم الخلفية الذي سيخزّن النتائج المخزنة مؤقتًا وإعداده وصيانته. عند اختيار خادم، يجب مراعاة ما يلي:

  • سرعة الاتصال بالشبكات. على سبيل المثال، إذا كان فريقك في المكتب نفسه، يمكنك تشغيل الخادم المحلي الخاص بك.
  • الأمان. ستتضمن ذاكرة التخزين المؤقت البعيد برامجك الثنائية ولذلك يجب أن تكون آمنة.
  • سهولة الإدارة. على سبيل المثال، Google Cloud Storage هي خدمة مُدارة بالكامل.

هناك العديد من الخلفيات التي يمكن استخدامها لذاكرة التخزين المؤقت عن بُعد. وتتضمن بعض الخيارات:

NGinx

nginx هو خادم ويب مفتوح المصدر. بفضل [وحدة WebDAV]، يمكن استخدامها كذاكرة تخزين مؤقت عن بُعد لتطبيق Bazel. في Debian وUbuntu، يمكنك تثبيت الحزمة nginx-extras. تتوفّر على نظام التشغيل macOS nginx من خلال Homebrew:

brew tap denji/nginx
brew install nginx-full --with-webdav

في ما يلي مثال على إعداد nginx. لاحِظ أنّه عليك تغيير /path/to/cache/dir إلى دليل صالح حيث يكون لدى NGinx إذن الكتابة والقراءة. قد تحتاج إلى تغيير الخيار client_max_body_size إلى قيمة أكبر إذا كانت لديك ملفات إخراج أكبر. سيتطلب الخادم تهيئة أخرى، مثل المصادقة.

مثال على ضبط قسم server في nginx.conf:

location /cache/ {
  # The path to the directory where nginx should store the cache contents.
  root /path/to/cache/dir;
  # Allow PUT
  dav_methods PUT;
  # Allow nginx to create the /ac and /cas subdirectories.
  create_full_put_path on;
  # The maximum size of a single file.
  client_max_body_size 1G;
  allow all;
}

عن بُعد

bazel-remote هي ذاكرة تخزين مؤقت مفتوحة المصدر لإصدار عن بُعد يمكنك استخدامها على بنيتك الأساسية. وقد تم استخدامه في الإنتاج في العديد من الشركات منذ أوائل عام 2018. يُرجى العِلم أنّ مشروع Bazel لا يوفّر دعمًا فنيًا للتطبيق عن بُعد.

تخزّن ذاكرة التخزين المؤقت هذه المحتوى على القرص، كما تقدم أيضًا مجموعة من البيانات غير المرغوب فيها لفرض حد أقصى لمساحة التخزين وإزالة العناصر غير المستخدمة. وتتوفّر ذاكرة التخزين المؤقت كصورة [Doker] ورمزها متاح على GitHub. يتم دعم كل من واجهة برمجة تطبيقات REST وgRPC لذاكرة التخزين المؤقت عن بُعد.

ارجع إلى صفحة GitHub للحصول على تعليمات عن كيفية استخدامها.

Google Cloud Storage

[Google Cloud Storage] هو متجر مُدار بشكل كامل يوفّر واجهة برمجة تطبيقات HTTP تتوافق مع بروتوكول التخزين المؤقت عن بُعد Bazel' . يتطلب ذلك أن يكون لديك حساب على Google Cloud مع تفعيل الفوترة.

لاستخدام Cloud Storage كذاكرة تخزين مؤقت:

  1. أنشئ حزمة مساحة تخزين. تأكّد من اختيار موقع جغرافي الأقرب لك، لأن معدل نقل البيانات للشبكة مهم لذاكرة التخزين المؤقت عن بُعد.

  2. أنشِئ حساب خدمة لتطبيق Bazel للمصادقة على Cloud Storage. يُرجى الاطّلاع على إنشاء حساب خدمة.

  3. يمكنك إنشاء مفتاح JSON سري ثم تمريره إلى Bazel للمصادقة. عليك تخزين المفتاح بشكل آمن، حيث يمكن لأي شخص لديه المفتاح قراءة البيانات العشوائية وكتابتها إلى حزمة GCS.

  4. يمكنك الربط بخدمة Cloud Storage من خلال إضافة العلامات التالية إلى الأمر Bazel:

    • أدخِل عنوان URL التالي إلى Bazel باستخدام العلامة: --remote_cache=https://storage.googleapis.com/bucket-name حيث يكون bucket-name هو اسم حزمة مساحة التخزين.
    • تمرير مفتاح المصادقة باستخدام العلامة: --google_credentials=/path/to/your/secret-key.json أو --google_default_credentials لاستخدام مصادقة التطبيق.
  5. يمكنك ضبط خدمة Cloud Storage لحذف الملفات القديمة تلقائيًا. لإجراء ذلك، يُرجى الاطّلاع على إدارة مراحل نشاط العنصر.

الخوادم الأخرى

يمكنك إعداد أي خادم HTTP/1.1 يتوافق مع PUT وGET كخلفية لذاكرة التخزين المؤقت. أبلغ المستخدمون عن نجاح العملية باستخدام خزائن مؤقتة مثل Hazelcast وApache httpd وAWS S3.

المصادقة

بدءًا من الإصدار 0.11.0، تمت إضافة المصادقة عبر بروتوكول HTTP الأساسي إلى Bazel. يمكنك تمرير اسم مستخدم وكلمة مرور إلى Bazel من خلال عنوان URL لذاكرة التخزين المؤقت عن بُعد. البنية هي https://username:password@hostname.com:port/path. تجدُر الإشارة إلى أنّ "بروتوكول HTTP الأساسي" ينقل اسم المستخدم وكلمة المرور إلى نص عادي على الشبكة، وبالتالي يكون من المهم استخدامها مع HTTPS دائمًا.

بروتوكول التخزين المؤقت في HTTP

يدعم Bazel التخزين المؤقت عن بُعد عبر HTTP/1.1. والبروتوكول بسيط من الناحية النظرية: يتم تحميل البيانات الثنائية (BLOB) من خلال طلبات PUT ويتم تنزيلها من خلال طلبات GET. يتم تخزين البيانات الوصفية لنتيجة الإجراء ضمن المسار /ac/، ويتم تخزين ملفات الإخراج ضمن المسار /cas/.

على سبيل المثال، جرِّب استخدام ذاكرة تخزين مؤقت عن بُعد ضمن http://localhost:8080/cache. سيظهر طلب Bazel لتنزيل البيانات الوصفية لنتيجة الإجراء لأحد الإجراءات باستخدام تجزئة SHA256 01ba4719... على النحو التالي:

GET /cache/ac/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b HTTP/1.1
Host: localhost:8080
Accept: */*
Connection: Keep-Alive

سيظهر طلب Bazel لتحميل ملف إخراج يتضمّن تجزئة SHA256 15e2b0d3... إلى CAS على النحو التالي:

PUT /cache/cas/15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 HTTP/1.1
Host: localhost:8080
Accept: */*
Content-Length: 9
Connection: Keep-Alive

0x310x320x330x340x350x360x370x380x39

تشغيل Bazel باستخدام ذاكرة التخزين المؤقت عن بُعد

بعد إعداد الخادم كذاكرة تخزين مؤقت عن بُعد، يمكنك إضافة علامات إلى أمر Bazel لاستخدام ذاكرة التخزين المؤقت عن بُعد. يمكنك الاطّلاع أدناه على قائمة بعمليات الضبط وعلاماتها.

قد تحتاج أيضًا إلى إعداد المصادقة، أي معلومات خاصة بالخادم الذي تم اختياره.

قد ترغب في إضافة هذه العلامات في ملف .bazelrc حتى لا تحتاج إلى تحديدها في كل مرة يتم فيها تشغيل Bazel. بناءً على العوامل الديناميكية للمشروع والفريق، يمكنك إضافة علامات إلى ملف .bazelrc بما يلي:

  • على جهازك المحلي
  • في مساحة عمل المشروع الخاصة بك، تمت مشاركتها مع الفريق
  • على نظام CI

القراءة والكتابة في ذاكرة التخزين المؤقت عن بُعد

اختَر من يمكنه الكتابة في ذاكرة التخزين المؤقت عن بُعد. قد تحتاج فقط إلى السماح لنظام CI بالكتابة في ذاكرة التخزين المؤقت عن بُعد.

يمكنك استخدام العلامة التالية للقراءة والكتابة في ذاكرة التخزين المؤقت عن بُعد:

build --remote_cache=http://your.host:port

وبالإضافة إلى HTTP، يمكن أيضًا استخدام البروتوكولات التالية: HTTPS وgrpc وgrpcs.

استخدِم العلامة التالية بالإضافة إلى العلامة الواردة أعلاه للقراءة فقط من ذاكرة التخزين المؤقت عن بُعد:

build --remote_upload_local_results=false

استثناء استهدافات محددة من استخدام ذاكرة التخزين المؤقت عن بُعد

لاستبعاد استهدافات معيّنة من استخدام ذاكرة التخزين المؤقت عن بُعد، ضَع علامة على الاستهداف باستخدام no-cache. مثلاً:

java_library(
    name = "target",
    tags = ["no-cache"],
)

حذف المحتوى من ذاكرة التخزين المؤقت عن بُعد

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

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

قد تحتاج إلى حذف المحتوى من ذاكرة التخزين المؤقت إلى:

  • إنشاء ذاكرة تخزين مؤقت نظيفة بعد تسمم ذاكرة التخزين المؤقت
  • تقليل مقدار مساحة التخزين المُستخدَمة من خلال حذف المخرجات القديمة

مفاتيح يونكس

تتيح ذاكرة التخزين المؤقت عن بُعد لـ HTTP الاتصال عبر مقابس نطاق Unix. ويشبه هذا السلوك علامة --unix-socket curl's. استخدم ما يلي لضبط مقبس Unix للنطاق:

   build --remote_cache=http://your.host:port
   build --remote_cache_proxy=unix:/path/to/socket

هذه الميزة غير متاحة على نظام التشغيل Windows.

ذاكرة التخزين المؤقت على القرص

يستطيع Bazel استخدام دليل على نظام الملفات كذاكرة تخزين مؤقت عن بُعد. ويكون ذلك مفيدًا لمشاركة عناصر الإصدار عند تبديل الفروع و/أو العمل في مساحات عمل متعددة بالمشروع نفسه، مثل عمليات الدفع المتعددة. وبما أنّ Bazel لا يتولّى جمع الأدلة بشكل غير مرغوب فيه، ننصحك بتنظيف الدليل بشكل دوري. فعِّل ذاكرة التخزين المؤقت على القرص كما يلي:

build --disk_cache=path/to/build/cache

يمكنك تمرير مسار خاص بالمستخدم إلى العلامة --disk_cache باستخدام العنوان البديل للبريد الإلكتروني ~ (سيحل Bazel محل الدليل الرئيسي للمستخدم الحالي.) ويكون ذلك مفيدًا عند تفعيل ذاكرة التخزين المؤقت على القرص لجميع مطوّري المشروع عبر المشروع الذي تم تسجيله في ملف .bazelrc.

المشاكل المعروفة

تعديل ملف الإدخال أثناء الإصدار

عندما يتم تعديل ملف الإدخال أثناء الإصدار، قد يحمّل Bazel نتائج غير صالحة إلى ذاكرة التخزين المؤقت عن بُعد. يمكنك تفعيل اكتشاف التغيير باستخدام العلامة --experimental_guard_against_concurrent_changes. لا توجد مشاكل معروفة، وسيتم تفعيله تلقائيًا في الإصدارات المستقبلية. يمكنك الاطّلاع على [المشكلة رقم 3360] لمعرفة آخر الأخبار. وبشكل عام، تجنّب تعديل ملفات المصدر أثناء إصدارها.

تسرّب متغيّرات البيئة في أحد الإجراءات

يحتوي تعريف الإجراء على متغيّرات بيئة. وقد يشكّل هذا مشكلة في مشاركة نتائج ذاكرة التخزين المؤقت عن بُعد على جميع الأجهزة. على سبيل المثال، البيئات التي تحتوي على متغيّرات $PATH مختلفة لن تشارك نتائج ذاكرة التخزين المؤقت. يتم تضمين متغيّرات البيئة فقط في القائمة البيضاء بشكل صريح من خلال --action_env في تعريف الإجراء. حزمة Bazel's Debian/Ubuntu المُستخدمة لتثبيت /etc/bazel.bazelrc في القائمة البيضاء لمتغيرات البيئة، بما في ذلك $PATH. إذا كنت تتلقى نتائج أقل من المتوقع لذاكرة التخزين المؤقت، تأكد من أن بيئتك لا تتضمن ملف /etc/bazel.bazelrc قديمًا.

لا يتتبّع تطبيق Bazel الأدوات خارج مساحة العمل

لا يتتبّع Bazel حاليًا الأدوات خارج مساحة العمل. وقد يمثّل ذلك مشكلة إذا كان الإجراء، مثلاً، يستخدم مجمِّعًا من /usr/bin/. وبعد ذلك، سيشارك مستخدمان اثنان من برامج التجميع المختلفة بشكل خاطئ نتائج ذاكرة التخزين المؤقت لأن المُخرجات مختلفة، ولكن لها تجزئة الإجراء نفسها. يمكنك الاطّلاع على المشكلة رقم 4558 لمعرفة آخر الأخبار.

يتم فقد حالة الذاكرة المتزايدة عند تشغيل الإصدارات داخل حاويات الإرساء يستخدم Bazel بنية الخادم/العميل حتى عند تشغيله في حاوية إرساء واحدة. على جهة الخادم، يعمل Bazel على حالة الذاكرة، ما يؤدي إلى تسريع عمليات الإنشاء. عند تشغيل المباني داخل حاويات الإرساء كما هو الحال في CI، يتم فقدان حالة الذاكرة ويتعيّن على Bazel إعادة إنشائها قبل استخدام ذاكرة التخزين المؤقت البعيد.