todos باستخدام عملية ترحيل، ثم تعالج طلبات الإنشاء والقراءة والتحديث والحذف من خلال عرض JSON بسيط. ويستخدم كل اتصال بروتوكول TLS مع التحقق الكامل من الشهادة.
المتطلبات الأساسية
- بايثون 3.12 أو إصدار أحدث، كما يتطلب Django 6. اختُبر هذا الدليل باستخدام بايثون 3.13 وDjango 6.1.1 وpsycopg 3.3.6.
- حساب على ClickHouse Cloud
psql، لإنشاء قاعدة البيانات. ويمكنك أيضًا تنفيذ عبارةCREATE DATABASEفي SQL console.
إنشاء خدمة ClickHouse Managed Postgres
في وحدة تحكم ClickHouse Cloud، انقر على New service ثم اختر Postgres. سيصبح المثيل جاهزًا في غضون دقائق قليلة. للاطلاع على شرح مفصّل للخطوات، راجع دليل البدء السريع.احصل على بيانات الاتصال
انقر على Connect في الشريط الجانبي الأيسر لخدمتك. تعرض النافذة المنبثقة اسم المستخدم وكلمة المرور والخادم والمنفذ، كما تحتوي على مفتاح تبديل بين Directly وvia PgBouncer. يربط هذا الدليل Django عبر PgBouncer المضمَّن على المنفذ6432. عادةً ما يشغّل تطبيق Django في بيئة الإنتاج عدة عمليات عامل على عدة أجهزة، وتفتح كلٌّ منها اتصالاتها الخاصة. يعمل PgBouncer في وضع تجميع المعاملات، فيتيح لجميع هذه العمليات أن تتشارك عددًا محدودًا من اتصالات Postgres. ويتطلب Django بعض الإعدادات ليعمل مع تجميع المعاملات، وقد تضمّنها هذا الدليل وشرحها في قسم إعدادات PgBouncer لـ Django.
اختر via PgBouncer لعرض بيانات الاتصال عبر التجميع. سيتغيّر المنفذ إلى 6432، وستتضمن سلسلة الاتصال sslmode=verify-full.
في النافذة المنبثقة، انقر على Download CA certificate. ويمكنك أيضًا تنزيلها من Settings → CA Certificate. هذه الشهادة خاصة بمثيلك وحده، لذا يستطيع المشغّل استخدامها للتحقق من أنه يتصل بخادمك فعلًا.
إعداد المشروع
أنشئ دليلًا للمشروع يحتوي على بيئة افتراضية، ثم ثبّت Django وpsycopg 3، وأنشئ مشروع Django يضم تطبيقtodos:
psycopg[binary] إصدارًا حديثًا من libpq، لذا لن تحتاج إلى تثبيت PostgreSQL محليًا.
تهيئة الاتصال
انقل شهادة CA التي نزّلتها إلى دليل المشروع، بجوارmanage.py، وأعد تسميتها إلى ca-certificate.pem.
أنشئ قاعدة بيانات للتطبيق، مع استبدال <PASSWORD> والمضيف بالقيم الظاهرة في النافذة المنبثقة Connect:
mysite/settings.py، وأضف import os أسفل from pathlib import Path، ثم استبدل الإعداد DATABASES بما يلي:
mysite/settings.py
OPTIONS إلى psycopg، الذي يسلّمها بدوره إلى libpq. وعند ضبط sslmode على verify-full، يتحقق libpq من أن شهادة الخادم موقّعة من الـ CA الخاص بخدمتك وأنها تطابق اسم المضيف. أما BASE_DIR فيجعل مسار الشهادة مطلقًا، فيعمل الإعداد أيًّا كان الدليل الذي تشغّل Django منه.
إذا كان
sslrootcert يشير إلى CA غير صحيح، يفشل الاتصال برسالة الخطأ SSL error: certificate verify failed. وفي غياب sslrootcert، يفشل برسالة الخطأ root certificate file ".../.postgresql/root.crt" does not exist، لأن libpq يلجأ حينها إلى موقع الـ CA الافتراضي الخاص به. وإذا اتصلت باستخدام عنوان IP بدلًا من اسم المضيف، يفشل برسالة الخطأ server certificate for "..." does not match host name.إنشاء نموذج وتنفيذ عمليات الترحيل
أضف التطبيقtodos إلى INSTALLED_APPS في الملف mysite/settings.py:
mysite/settings.py
Todo في الملف todos/models.py:
todos/models.py
todos_todo، ينشئ الأمر migrate جداول تطبيقات Django المدمجة، مثل auth_user وdjango_session، ويسجّل عمليات الترحيل المطبّقة في django_migrations. أما في تطبيق قائم، فتخطَّ إنشاء نموذج todos واكتفِ بتنفيذ python manage.py migrate، الذي ينشئ جميع جداول تطبيقك في قاعدة البيانات الجديدة.
لا يحصل migrate على قفل استشاري على مستوى الـ session، لذا يعمل عبر PgBouncer دون مشكلات. لكنه في المقابل لا يمنع التشغيل المتزامن، لذا نفّذ عمليات الترحيل من مكان واحد فقط، كخطوة واحدة ضمن عملية النشر.
إضافة نقطة نهاية JSON
استبدل محتوىtodos/views.py بدالتَي عرض (views) تتوليان إنشاء المهام واستعراضها وتحديثها وحذفها باستخدام Django أداة ربط الكائنات بقواعد البيانات:
todos/views.py
mysite/urls.py لتوجيه المسارين /todos و/todos/<id> إلى دوال العرض:
mysite/urls.py
التشغيل والتحقق
شغّل خادم التطوير:PATCH الصفَّ المُحدَّث:
http://localhost:3111/todos في المتصفح لعرض المهام المتبقية. ستظهر الاستجابة على النحو التالي:
guide_django يليه public، وانقر على الجدول todos_todo. سيظهر لك أن الجدول يحتوي على الصف المتبقي:
إعدادات PgBouncer لـ Django
يعمل PgBouncer في وضع تجميع المعاملات: إذ يمكن تنفيذ كل معاملة، أو كل عبارة خارج معاملة، على اتصال Postgres مختلف. وفيما يلي كيف يؤثر ذلك في الإعدادات السابقة وفي ميزات Django الأخرى:DISABLE_SERVER_SIDE_CURSORS: يقرأQuerySet.iteratorالصفوف على شكل مقاطع عبر مؤشر من جهة الخادم. وخارج المعاملة، يُعرِّف Django المؤشر بصيغةWITH HOLDويجلب كل مقطع على حدة، لذا قد يصل طلب الجلب عند المرور عبر PgBouncer إلى اتصال Postgres لا يحتوي على المؤشر، فيفشل مع الخطأcursor "_django_curs_..." does not exist. ولا يحدث ذلك إلا عندما يستخدم عملاء آخرون مجمّع الاتصالات في الوقت نفسه، ولهذا كثيرًا ما لا يظهر أثناء التطوير. وعند تفعيل هذا الإعداد، يستخدم.iterator()مؤشرًا عاديًا، ويُحمِّل psycopg النتيجة كاملةً في الذاكرة. ولبثّ جدول كبير جدًا، شغِّل تلك الشيفرة عبر الاتصال المباشر على المنفذ5432مع تعطيل الإعداد.CONN_MAX_AGE: افتراضيًا (0)، يفتح Django اتصالًا جديدًا لكل طلب. ويتطلب فتح اتصال TLS عدة رحلات ذهاب وإياب عبر الشبكة، سواء عبر PgBouncer أو مباشرةً، لذا فإن إعادة استخدام الاتصالات تُسرّع الطلبات كثيرًا. وفي اختبار أُجري من حاسوب محمول بأربعة عمّال Gunicorn، أدى ضبطCONN_MAX_AGEعلى600إلى خفض الزمن الوسيط للطلب من نحو 670 ms إلى 95 ms. وعبر PgBouncer، لا يحتجز اتصال Django المفتوح اتصال Postgres بين المعاملات، لذا لا تستنفد الاتصالات الدائمة الحدmax_connections. ويجعلCONN_HEALTH_CHECKSنظام Django يتحقق من الاتصال المُعاد استخدامه في بداية كل طلب، ويعيد الاتصال إذا كان قد أُغلق.- مجمّع الاتصالات: يوفّر المجمّع المدمج في Django (
"pool": TrueضمنOPTIONS، ويتطلبpip install "psycopg[binary,pool]") تسريعًا مماثلًا، ويعمل كذلك عبر PgBouncer. ويشترط ضبطCONN_MAX_AGEعلى0، ويُبقي أربعة اتصالات مفتوحة على الأقل لكل عملية. ومع PgBouncer، يكفيCONN_MAX_AGEلمعظم التطبيقات؛ أما الخوادم متعددة الخيوط أو خوادم ASGI فيُستحسن أن تستخدم المجمّع. - العبارات المُحضَّرة: لا حاجة إلى أي إعداد. إذ يضبط Django قيمة
prepare_thresholdفي psycopg علىNoneويربط معلمات الاستعلام لدى العميل افتراضيًا، فلا يُنشئ عبارات مُحضَّرة من جهة الخادم. وإذا فعّلت"server_side_binding": Trueوضبطت"prepare_threshold"ضمنOPTIONS، فستعمل العبارات المُحضَّرة أيضًا عبر PgBouncer، لأنpsycopg[binary]يتضمنlibpq18 ويحرّر العبارات برسالةCloseعلى مستوى البروتوكول. أما مع psycopg المبني علىlibpq16 أو أقدم، فيفشل تحرير العبارة داخل المعاملة مع الخطأprepared statement "_pg3_0" does not exist. وللتحقق من إصدارك، شغِّلpython -c "import psycopg; print(psycopg.pq.version())"؛ إذ يلزمك الإصدار170000أو أحدث. - حالة الجلسة: لا تسري عبارة
SET، مثلSET search_path، إلا على اتصال Postgres الذي نفّذها، لذا قد لا تراها الاستعلامات اللاحقة، بينما قد يراها عملاء آخرون. ويرفض PgBouncer إعداد Django"options": "-c search_path=..."مع الخطأunsupported startup parameter in options: search_path. لذا اضبط القيم الافتراضية على مستوى قاعدة البيانات بدلًا من ذلك، مثلًا باستخدامALTER DATABASE guide_django SET search_path = myschema, public;. ولا تستخدم الخيارassume_roleلأنه ينفّذSET ROLE. أما معالجة Django الخاصة لـTIME_ZONEوالخيارisolation_levelفيعملان عبر PgBouncer دون مشكلات.
PORT على 5432 واحذف DISABLE_SERVER_SIDE_CURSORS. عندئذٍ يحتفظ كل عامل Django باتصال Postgres خاص به، لذا احرص على أن يبقى العدد الإجمالي للعمّال أقل من max_connections.
الخطوات التالية
- الاتصال: سلاسل الاتصال وPgBouncer وTLS
- الإعدادات: معلمات Postgres وPgBouncer، مثل
max_connections - النسخ المتماثلة للقراءة: توجيه عمليات القراءة إلى نسخة متماثلة بالاستفادة من دعم Django لـقواعد البيانات المتعددة
- الأمان: قوائم التحكم في الوصول عبر عناوين IP والشبكات الخاصة