كيفية البدء في مشروع الحيوانات الأليفة وعدم الحصول على فوائد

كيفية البدء في مشروع الحيوانات الأليفة وعدم الحصول على فوائد


TL ؛ د

توضح المقالة استخدام مشروع الحيوانات الأليفة كوسيلة للحفاظ على المهارات وتحسينها. أنشأ المؤلف مكتبة PHP لتثبيت FIAS من ملفات XML.


هدف


نادراً ما أقوم بتغيير الوظائف ، وبناءً على الرغبة الطبيعية لكل مؤسسة في العمليات الثابتة ، تتحول أي مهمة إلى روتين. من ناحية ، من المفيد للشركة الحفاظ على مثل هذه الحالة ، من ناحية أخرى ، هذا يعني بالنسبة لي إما خسارة كاملة أو تقادم المهارات. PHP يتطور بسرعة ، وبالتالي ، فإن الفجوة المحتملة تنمو بسرعة أيضًا. أخيرًا ، نعلم جميعًا أنه من الصعب اليوم على المبرمج العثور على وظيفة جيدة دون معرفة Elasticsearch و RabbitMQ و Kafka وغيرها من التقنيات التي لا تظهر غالبًا في عملي اليومي.


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


اختيار المهمة


تبين أن اختيار المهمة هو أصعب جزء من المهمة. لم يتبادر إلى الذهن أي شيء مميز: بعض الخدمات ، مثل محلل الوظائف الذي يمكن تنفيذه بسهولة على حزمة مألوفة. لقد تخلت عن فكرة المشروع لعدة أشهر ، حتى رأيت عن طريق الخطأ الأخبار المتعلقة باختراق وزارة المالية. اقترح استخدام أحد مصادر مصادر البيانات المفتوحة لإنشاء خدمة. من بين أمور أخرى ، تمت الإشارة إلى نظام عناوين المعلومات الفيدرالي (FIAS) أيضًا. لسوء الحظ ، فإن hackathon قد انتهت بالفعل بحلول ذلك الوقت.


لقد تعلمت عن FIAS لأول مرة ، لكن المهمة بدت مثيرة للاهتمام. الحكم على نفسك: حوالي 30 جيجابايت من ملفات XML ، وحوالي 60 مليون سطر في قاعدة البيانات ، وعلاوة على ذلك ، يمكن أن تثبت المكتبة لاحقًا أنها مفيدة في العمل. كانت هناك بعض الحلول الجاهزة على جيثب ، لكن هذا لم يمنعني. على العكس من ذلك ، بناءً على تحليلهم ، قمت بتقديم متطلبات إضافية من شأنها تسليط الضوء على عملي.


بالنظر إلى المستقبل ، لاحظت أنني واجهت صعوبات أقل بكثير مما توقعت.


بيان المهمة


90 ٪ من النجاح هو البيان الصحيح للمشكلة. بعد عدة سنوات من عمل القالب ، كان من الصعب للغاية أن تجعل نفسك يصوغ المشكلة بوضوح. أردت فقط أن أبدأ العمل ، لكن بالفعل في هذه العملية كان من الممكن أن يتخلص كل شيء من تلقاء نفسه. بعد ساعة من الصراع مع التسويف ، كتبت أخيرًا: إنشاء مكتبة في PHP لاستيراد بيانات FIAS.


في وقت لاحق ، بعد الذوق ، أضفت بعض المتطلبات الإضافية:


  • في PHP دون استخدام أدوات مساعدة من طرف ثالث ، رمز حصري في PHP وملحقات من PECL ،
  • استيراد جميع البيانات من مجموعة FIAS ،
  • دورة التثبيت والتحديث الكاملة: البحث عن الإصدار الضروري ، استلام الأرشيف ، التفريغ ، الكتابة إلى قاعدة البيانات ،
  • أقصى قدر من المرونة: القدرة على تغيير موقع التخزين ، وتعديل البيانات قبل التسجيل ، وتصفية ما يلزم ، وما إلى ذلك ،
  • يجب دمج المكتبة بسهولة في المشروعات القائمة.

FIAS


لدى FIAS موقع إلكتروني رسمي يعطينا تعريف وغرض إنشاء نظام


نظام عناوين المعلومات الفيدرالي (FIAS) هو نظام معلومات الحالة الفيدرالي الذي يوفر تكوين وصيانة واستخدام سجل عناوين الولاية.

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

المواد ذات الوصف كافية تمامًا على موقع FIAS وعلى Habré ، لذلك لن أركز على ذلك.


باختصار. FIAS يأتي في شكلين: FIAS و KLADR. تم إهمال الثاني ولم يعد قيد الاستخدام. يتم تخزين المعلومات إما في DBF أو في XML. كل تغيير في تكوين FIAS يتميز بنسخة جديدة. يمكنك طلب إما حزمة تحتوي على بيانات كاملة حالية في الوقت الحالي ، أو تحتوي فقط على تغييرات بين الإصدارين. توفر الروابط خدمة SOAP. الحزمة عبارة عن أرشيف RAR يحتوي على ملفات ذات أسماء مشكلة بشكل خاص. وهي تتكون من بادئة واسم مجموعة بيانات وتاريخ الإنشاء. يوجد نوعان من البادئات: AS_ للملفات التي يجب إضافة بيانات منها إلى قاعدة البيانات ، و AS DEL للملفات التي يجب حذف بياناتها من قاعدة البيانات.


FIAS يحتوي على البيانات التالية:


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

وكذلك العديد من القواميس
  • قائمة بالقيم المحتملة لفترات المنازل (العادية ، حتى ، الفردية) ،
  • قائمة بأوضاع ملاءمة إدخال عنصر العنوان بواسطة مصنف KLADR4.0 ،
  • قائمة الحالات ذات الصلة لإدخال عنصر العنوان وفقا ل FIAS ،
  • قائمة بالأسماء الكاملة والمختصرة لأنواع عناصر العنوان ومستويات التصنيف الخاصة بها ،
  • قائمة أنواع المباني ،
  • قائمة الأنواع المحتملة للملكية
  • قائمة رموز العمليات مع الكائنات عنونة ،
  • قائمة بالظروف المحتملة للعقار
  • قائمة أنواع المباني أو المكاتب ،
  • قائمة أنواع الغرف ،
  • قائمة بالحالات المحتملة (مراكز) لعناوين عناوين الوحدات الإدارية ،
  • أنواع الوثائق التنظيمية.

يوصف هيكل البيانات في المستند ، والذي يمكن العثور عليه في قسم التحديثات .


في النهاية ، لدينا خوارزمية تثبيت FIAS بسيطة وخطية إلى حد ما:


  • الحصول على ارتباط من الأرشيف ورقم الإصدار الحالي من خدمة SOAP ،
  • تحميل الأرشيف ،
  • فك،
  • الكتابة إلى قاعدة البيانات جميع البيانات من الملفات مع البادئة AS_ ،
  • حذف جميع البيانات من الملفات من قاعدة البيانات AS DEL من قاعدة البيانات (نعم ، هذا صحيح ، أثناء التثبيت ، عليك أيضًا حذف بعض البيانات) ،
  • اكتب رقم الإصدار المثبت.

ولا تقل خوارزمية التحديث البسيطة:


  • الحصول على قائمة من خدمة SOAP مع أرقام الإصدارات وارتباطات إلى الملفات ذات التغييرات ،
  • إذا كان الإصدار الحالي في قاعدة البيانات المحلية هو الأحدث ، ثم توقف عن التنفيذ ،
  • الحصول على رابط إلى الأرشيف مع التغييرات على الإصدار التالي ،
  • تحميل الأرشيف ،
  • فك،
  • الكتابة إلى قاعدة البيانات جميع البيانات من الملفات مع البادئة AS_ ،
  • إزالة كافة البيانات من قاعدة البيانات من الملفات باستخدام البادئة AS DEL ،
  • اكتب رقم الإصدار المحدّث ،
  • العودة إلى الخطوة الأولى.

FIAS يترك انطباعات متضاربة. من ناحية: أتمتة كاملة للعملية برمتها ، تنسيقات مفتوحة ، وثائق جيدة. من ناحية أخرى: قرار غريب باستخدام RAR الملكية للبيانات المفتوحة ؛ الاختلافات بين الوثائق والواقع (تتعلق أساسًا بالسمات الإلزامية) ، والتي تسبب العديد من المشكلات الصغيرة ولكن غير السارة ؛ في بعض الأحيان تأتي الأرشيفات التي لا يمكن تفريغها في نظام Linux ؛ بعض دلتا بين الإصدارات تشغل 4-5 غيغابايت.


هندسة معمارية


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


بالإضافة إلى العمليات ، قمت بإنشاء العديد من الخدمات التي يمكن نقلها باستخدام DI. إنها تتيح لك إعادة استخدام الرمز ، واستبدال التطبيق بسهولة لمهام النظام منخفضة المستوى (تنزيل ملف ، تفريغ أرشيف ، الكتابة إلى قاعدة بيانات وغيرها) وتوفير تغطية اختبار جيدة بفضل mocks.


نتيجة لذلك ، تحتوي المكتبة على أربعة أنواع رئيسية من الكائنات ، يتم تحديد مجال المسؤولية لكل منها بوضوح:


  • خدمات - توفر أدوات لأداء مهام النظام منخفضة المستوى ،
  • كائن الحالة - يخزن المعلومات للنقل بين العمليات ،
  • العمليات - باستخدام الخدمات والدولة التي تنفذ فيها الجزء الذري من منطق الأعمال ،
  • سلسلة العمليات - ينفذ العمليات وينقل الحالة بينهما.

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


الأطر


مع فترات راحة طويلة وإعادة البناء المستمر ، عملت في المكتبة لمدة عام ونصف.


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


بالطبع ، رفضها زملاؤها بلا رحمة.


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


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


النقطة الأساسية هي النموذج. تحديث مجموعات غير متجانسة باستمرار من الكائنات في عدة مستودعات لا تريد. في الوقت نفسه ، في العمل الرئيسي ، حصلت على مشروع على Symfony. بعد التعرف السريع عليها ، قررت أن الميزة الأكثر فائدة في SF هي إنشاء الشفرة وستحل كل مشاكلي. لقد قمت بإنشاء ملف yaml في الحزمة الرئيسية ، والذي يحتوي على وصف تعريفي لبيانات FIAS. ثم أضفت مولدات الشفرة التي تنشئ فئات محددة للنماذج بناءً على هذا الوصف: كيانات العقيدة لكائنات Symfony و Eloquent لـ Laravel. خلال تطوير المولدات الكهربائية ، أدركت أن قوالب الأغصان لم تكن مناسبة لذلك ، واستقرت على حل متخصص - Nette PHP Generator .


كدليل على المفهوم ، قمت بإنشاء حزم لارافيل و Symfony . منذ أن عملت لفترة أطول مع الثانية ، سوف أصف كل شيء لاحق في سياقها.


البنية التحتية


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



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


نتائج التعلم


PHP 7


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


RAR


من المستغرب ، في PECL كان هناك حزمة للعمل مع RAR . عادةً ، لا يتم الوثوق بمثل هذه الامتدادات وأحاول تجنبها. لقد ثبت أنها مستقرة بشكل مثير للريبة: لقد تم تثبيتها في 7.2 دون مشاكل ، وتمكنت من فك المحفوظات الضخمة بسرعة نسبية مع انخفاض استهلاك ذاكرة الوصول العشوائي (يتم تفريغ 6 جيجابايت في 10-20 دقيقة حسب موارد النظام المتاحة). ما زلت أخشى أن هذا هو بعض مظاهر قانون مورفي.


XmlReader


قراءة ملفات XML العملاقة ليست مهمة تافهة. ومرة أخرى ، جاء امتداد PECL للإنقاذ - XmlReader . لم أكن أدرك على الفور كل قوتها ، لكنني في عدة طرق قمت بتكييفها بالاقتران مع برنامج التسلسل Symfony للحصول على البيانات بسرعة وبشكل اقتصادي من ملفات FIAS. على جانب المكتبة ، يقوم كائن القارئ بتطبيق واجهة التكرار ، والتي تقوم بإرجاع سلاسل XML بالتسلسل المقابلة لسجل واحد في الملف. باستخدام متسلسل Symfony ، يتم تحويل هذه السلاسل إلى كائنات. يمكن قراءة ملف 20 جيجابايت في 3 إلى 4 دقائق أثناء استخدام أكثر من 50 ميغابايت من ذاكرة الوصول العشوائي.


الكتابة إلى قاعدة البيانات


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


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


تحسين ادراج البيانات


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


أولاً ، قمت بالتبديل إلى أعمدة من نوع ugid للمفاتيح الأساسية المضمنة في PostgreSql . الكتابة إلى عمود uuid مع فهرس أسرع بكثير من الكتابة إلى سلسلة.


بعد ذلك ، تخلت عن جميع الفهارس غير الهامة والمفاتيح الخارجية ، لأن الاهتمام بسلامة البيانات يقع بالكامل في فريق FIAS.


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


على الرغم من هذه التغييرات ، تجاوز وقت الاستيراد 30 ساعة. هناك حاجة لتغيير جذري في النهج.


عمليات موازية


الإنترنت مليء بمقالات حول عدم التزامن في PHP. سقط خياري على أمبير . لم ينجح الأمر بشكل متزامن. أولاً ، تحولت الشفرة بسرعة إلى صفحة مرعبة من عمليات الاسترجاعات والمكالمات غير المرئية (ربما يكون هذا خطأي ، وليس النهج غير المتزامن). ثانياً ، كان علي أن أتخلى عن استخدام ORMs القياسية لأن هناك حاجة إلى حظر المكالمات إلى قاعدة البيانات من خلال إطار خاص . ثالثًا ، على الرغم من وجود شروط يمكن لـ PostgreSql إدراج صفوف فيها بشكل متوازٍ ، إلا أنه من الصعب للغاية تحقيقها. نتيجةً لذلك ، بعد 5 ساعات من العملية ، شاهدت كيف تم "مزامنة" جميع طلباتي غير المتزامنة بالقوة من جانب قاعدة البيانات.


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


أول قررت لمحاولة تمديد الموازي . له عيب واحد قاتل - يجب أن يتم إنشاء المترجم الشفهي مع دعم ZTS (أمان Zend Thread Safety). نظرًا لأن ZTS لا يعمل في البرامج النصية العادية للويب ، يجب أن يكون لدى المرء نسختان مختلفتان من المترجم الشفهي. واحد ، بدون ZTS ، للويب ، والثاني ، مع ZTS ، لتثبيت FIAS. تفوقت زيادة الأداء المحتملة على هذا الإزعاج ، خاصة بالنظر إلى مدى سهولة تجميع حاوية Docker جديدة واستخدامها مع الحاوية القديمة. لسوء الحظ ، تسبب بدء Symfony داخل خيط جديد في تجاوز سعة مكدس PHP ، ولم أكن على استعداد لرفض حاوية DI وتكوين مناسب.


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


بسبب عدم وجود خبرة في العمليات المتوازية ، يبدو أنني ارتكبت جميع أخطاء مبتدئ.


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


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


بعد هذه التعديلات ، تمكنت من استيراد الإصدار الكامل من FIAS خلال 16-20 ساعة ، اعتمادًا على موارد الخادم. ليست جيدة كما نود ، لكنني مستمر في العمل على التحسين. والخطوة التالية هي الرفض الكامل ل PostgreSql لصالح Elasticsearch.


النتائج


هل كان يستحق كل هذا العناء؟ سنتان من العمل في مكتبة لم تدخل في أي مشروع قتالي؟


نعم تماما.


لقد غيرت وظيفتي على أي حال. خلال جولة في عشرات المقابلات ، أجبت على العديد من الأسئلة الصعبة فقط بفضل مشروعي للحيوانات الأليفة.


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


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

Source: https://habr.com/ru/post/ar479122/


All Articles