pgxpool مجمّع الاتصالات الخاص به. ستتعلّم في هذا الدليل كيفية ربط خدمة مكتوبة بلغة Go بـ ClickHouse Managed Postgres عبر اتصال TLS مع التحقق من الشهادة، وإنشاء جدول todos من خلال عملية ترحيل باستخدام golang-migrate، ثم معالجة طلبات الإنشاء والقراءة والتحديث والحذف عبر خادم net/http.
المتطلبات الأساسية
- Go الإصدار 1.25 أو أحدث. اختُبر هذا الدليل باستخدام Go 1.27.1 وpgx 5.11.0 وgolang-migrate 4.20.1.
- حساب على ClickHouse Cloud
psql، لإنشاء قاعدة البيانات. ويمكنك أيضًا تنفيذ عبارةCREATE DATABASEفي SQL console.
إنشاء خدمة ClickHouse Managed Postgres
في وحدة تحكم ClickHouse Cloud، انقر على New service ثم اختر Postgres. سيكون المثيل جاهزًا في غضون بضع دقائق. راجع دليل البدء السريع للاطلاع على شرح مفصّل للخطوات.الحصول على بيانات الاتصال
انقر على Connect في الشريط الجانبي الأيسر لخدمتك. أبقِ الخيار Directly محددًا وفعّل Use SSL. سيصبح عنوان URL للاتصال في علامة التبويب url مستخدمًا للمنفذ5432 ومنتهيًا بـ sslmode=verify-full&sslrootcert=<service-name>-ca-certificate.pem. انقر على Download CA certificate. ويمكنك أيضًا تنزيلها لاحقًا من Settings → CA Certificate. هذه الشهادة فريدة لمثيلك، ولذلك يستطيع pgx استخدامها للتحقق من أنه يتصل بالخادم الخاص بك فعلًا.
يتصل هذا الدليل مباشرةً بـ Postgres عبر المنفذ 5432، سواء لعمليات الترحيل أو للتطبيق. فخدمة Go عملية طويلة الأمد، وتحتفظ pgxpool فيها أصلًا بمجمّع اتصالات، لذا لا حاجة إلى وسيط تجميع اتصالات ثانٍ. أما إذا كنت تشغّل مثيلات عديدة من الخدمة وتحتاج إلى عدد من اتصالات العملاء يتجاوز ما يسمح به Postgres، فاستخدم PgBouncer المضمّن (via PgBouncer، المنفذ 6432) للتطبيق؛ راجع استخدام PgBouncer، إذ يتطلب ذلك إعداد اتصال إضافيًا واحدًا.
إعداد المشروع
أنشئ وحدة Go، وأضف pgx، ثم ثبّت واجهة سطر الأوامرmigrate مع مشغّل pgx:
-tags 'pgx5' على تصريف واجهة سطر الأوامر migrate مع مشغّل pgx v5 الخاص بها، والذي يستخدم مخطط URL pgx5://. يضع الأمر go install الملف التنفيذي في $GOBIN، أو في $(go env GOPATH)/bin إذا لم يكن GOBIN معيّنًا، لذا تأكد من إضافة هذا الدليل إلى PATH لديك.
تهيئة الاتصال
انقل شهادة CA التي نزّلتها إلى دليل المشروع، ثم أعد تسميتها إلىca-certificate.pem.
أنشئ قاعدة بيانات للتطبيق، ثم استبدل <PASSWORD> والمضيف بالقيم الظاهرة في النافذة المنبثقة Connect:
guide_go نفسها، ولا يختلفان إلا في مخطط URL؛ إذ يقرأ التطبيق المتغير DATABASE_URL، بينما تستخدم واجهة سطر الأوامر migrate المتغير MIGRATE_URL:
libpq. فعند ضبط sslmode=verify-full، يحمّل ملف CA من sslrootcert ويتحقق من سلسلة الشهادات واسم المضيف معًا، لذا لا حاجة إلى كتابة أي شيفرة خاصة بـ TLS. يُحسب مسار sslrootcert نسبةً إلى الدليل الذي تشغّل منه الأوامر. وإذا احتوت كلمة المرور على محارف خاصة مثل @ أو / أو #، فرمّزها بترميز URL.
إنشاء المخطط باستخدام الترحيل
أنشئ ملفات الترحيل:up:
migrations/000001_create_todos.up.sql
down التي تُلغي هذه التغييرات:
migrations/000001_create_todos.down.sql
migrate الإصدار الحالي في جدول schema_migrations، ولا تطبّق في المرات اللاحقة إلا عمليات الترحيل الأحدث. ثبّت دليل migrations مع الشيفرة الخاصة بك.
شغّل
migrate دائمًا عبر الاتصال المباشر (المنفذ 5432)، إذ تحتفظ الأداة طوال تشغيلها بقفل استشاري على مستوى الـ session، كي لا تنفّذ عمليتا نشر الترحيل في الوقت نفسه. أما عبر PgBouncer، فقد يُنفَّذ القفل وفكّ القفل على اتصالَي Postgres مختلفين، فيظل القفل قائمًا، وتتوقف عمليات تشغيل migrate اللاحقة عن الاستجابة أو تفشل مع الخطأ timeout: can't acquire database lock.الاستعلام من قاعدة البيانات
أنشئ الملفdb.go. يُنشئ هذا الملف مجمّع الاتصالات انطلاقًا من DATABASE_URL، ويتحقق من الاتصال عند بدء التشغيل بالاستعلام من Postgres عن إصدار TLS الذي تستخدمه الـ session:
db.go
todos.go الذي يتضمن معالجات HTTP. ينفّذ كل معالج استعلامًا واحدًا ذا معلمات عبر مجمّع الاتصالات، وتتولى الدالتان pgx.CollectRows وpgx.CollectExactlyOneRow فحص الصفوف وتعبئتها في البنية Todo بحسب اسم العمود:
todos.go
$1) بدلاً من دمجها داخل string الـ SQL إلى منع هجمات حقن SQL، إذ يرسلها pgx بمعزل عن نص الاستعلام. ولا حاجة إلى التحقق من error الذي تُعيده pool.Query على حدة، لأن pgx.CollectRows وpgx.CollectExactlyOneRow تُعيدانه.
أنشئ الملف main.go. يُنشئ هذا الملف مجمّع اتصالات واحداً للعملية بأكملها، ويخدم المسارات على المنفذ 3114، ويُغلق مجمّع الاتصالات عند الضغط على Ctrl+C. أما إذا كان لديك تطبيق قائم، فاستدعِ newPool مرة واحدة عند بدء التشغيل، ثم استدعِ registerTodoRoutes على http.ServeMux الخاص بك بدلاً من ذلك:
main.go
التشغيل والتحقق
أضف التبعيات المتبقية الخاصة بـpgxpool إلى الملفين go.mod وgo.sum، ثم شغّل الخادم:
TLSv1.3 من pg_stat_ssl على الخادم، ما يؤكد أن الـ session مشفّرة. وإذا وجّهت sslrootcert إلى أي شهادة أخرى، فلن يبدأ الخادم وسيسجّل الخطأ x509: certificate signed by unknown authority، ما يُثبت أن الشهادة تخضع للتحقق فعلًا.
في طرفية ثانية، أنشئ مهمتين، ثم علّم الأولى على أنها مكتملة، واحذف الثانية:
PATCH الصفَّ المُحدَّث:
http://localhost:3114/todos في متصفحك لعرض المهام المتبقية. تُعيد pgx قيم timestamptz وفق المنطقة الزمنية المحلية لديك. وتبدو الاستجابة كما يلي:
Shutting down ثم يُغلق مجمّع الاتصالات.
لعرض البيانات في وحدة التحكم، افتح SQL console من الشريط الجانبي الأيسر لخدمتك، ووسّع guide_go ثم public، ثم انقر على جدول todos. أما جدول schema_migrations المجاور له، فيحتفظ بإصدار الترحيل. ويحتوي جدول todos على الصف المتبقي:
استخدام PgBouncer
لتمرير استعلامات التطبيق عبر PgBouncer المضمَّن، اختر via PgBouncer في نافذة Connect، وغيّر المنفذ فيDATABASE_URL إلى 6432، ثم أضف default_query_exec_mode=cache_describe. واحرص على إبقاء MIGRATE_URL على المنفذ 5432:
default_query_exec_mode من URL ولا ترسله إلى الخادم. لا حاجة إلى أي تغييرات في الشيفرة، وتظل شهادة CA نفسها صالحة. يعرض سجل بدء التشغيل الآن TLS: none، لأن pg_stat_ssl يُبلغ عن اتصال PgBouncer نفسه بـ Postgres. أما اتصال تطبيقك بـ PgBouncer فلا يزال يخضع للتحقق، إذ يفشل الاتصال بالطريقة نفسها عند استخدام شهادة CA خاطئة.
يعمل PgBouncer في وضع تجميع المعاملات، لذا قد تُنفَّذ كل معاملة على اتصال Postgres مختلف:
- تعمل المعاملات المُنشأة باستخدام
pool.Beginأوpgx.BeginFuncكالمعتاد. - لا تبقى إعدادات session المضبوطة باستخدام
SETمرتبطة باتصالك، وقد تتسرّب إلى عملاء آخرين. استخدمSET LOCALداخل معاملة بدلًا من ذلك. كما يرفض PgBouncer المعاملsearch_pathفي URL الاتصال مع الخطأunsupported startup parameter: search_path؛ لذا اكتب أسماء الجداول مسبوقة باسم المخطط بدلًا من ذلك. - لا تعمل الأوامر
PREPAREوEXECUTEعلى مستوى SQL، ولاLISTEN، ولا الأقفال الاستشارية على مستوى session.
الخطوات التالية
- الاتصال: سلاسل الاتصال، وPgBouncer، وTLS
- الإعدادات: معلمات Postgres وPgBouncer، مثل
max_connections - النسخ المتماثلة للقراءة: وجّه الاستعلامات المخصصة للقراءة فقط إلى نسخة متماثلة باستخدام
pgxpool.Poolثانٍ - الأمان: قوائم التحكم في الوصول حسب عناوين IP، والشبكات الخاصة