خدمة Dart: إطار تطبيق الخادم

جدول المحتويات




تدريب



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



في هذه المقالة ، سنكتب تطبيقًا باستخدام إطار عمل Aqueduct، وتقييم أدائها واستهلاك الموارد في أوضاع مختلفة ، وكتابة مجموعة أدوات للتجميع في تطبيق أصلي لنظامي التشغيل Windows و Linux ، والتعامل مع عمليات ترحيل مخطط قاعدة البيانات لفئات تطبيق المجال ، وحتى نشر صورة عامل إرساء الأدوات لدينا إلى سجل DockerHub العام.







فائدة




تركيب قناة



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



  • قم بتنزيل الأرشيف وفك ضغطه على محرك الأقراص C:
  • , , , . . « »



  • Path . dart , , C:\dart-sdk\bin
  • , dart pub ( dart)



    dart --version






    pub -v




  • , ,
  • aqueduct CLI (command line interface)



    pub global activate aqueduct






    aqueduct




من الممكن نظريًا تثبيت خادم قاعدة بيانات PostgreSQL محليًا أيضًا . ومع ذلك ، سيسمح لنا Docker بتجنب هذه الحاجة وجعل بيئة التطوير مشابهة لوقت التشغيل على الخادم.



جيل التطبيق



لذلك ، لنفتح مجلد الخادم الخاص بنا في VsCode



code c:/docs/dart_server


بالنسبة لأولئك الذين لم أر الأولى و الثانية المواد، يمكن استنساخ شفرة المصدر من guthub مستودع :



git clone https://github.com/AndX2/dart_server.git
لنقم بإنشاء قالب تطبيق:



aqueduct create data_app






دعنا نتعرف على محتويات قالب المشروع:



  • README.md - ملاحظة تصف كيفية العمل مع مشروع قناة المياه ، وإجراء الاختبارات ، وإنشاء وثائق API ، وما إلى ذلك. ملف الدعم.
  • pubspec.yaml — pub. , , , .





  • config.yaml config.src.yaml — . .
  • analysis_options.yaml — ( ). .
  • .travis.yml — (continuous Integration). .
  • pubspec.lock .packages — pub. — , , — ().
  • .dart_tool/package_config.json — , aqueduct CLI. .
  • bin/main.dart — (, ). ( ).





  • lib/channel.dartApplicationChannel — . Aqueduct CPU RAM. ( Dart isolate) () .



  • lib/data_app.dart — . (library) dart_app





  • test/ — . -, . Postman.


ترتيب



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



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


في المجلد / lib ، قم بإنشاء عدة مجلدات والمستودع الأول للوصول إلى متغيرات







البيئة : يقرأ EnvironmentRepository في المُنشئ متغيرات البيئة من نظام التشغيل في شكل قاموس Map <String ، String> ويحفظها في المتغير الخاص _env . دعنا نضيف طريقة للحصول على جميع المعلمات في شكل قاموس: lib / service / EnvironmentService - المكون المنطقي للوصول إلى بيانات EnvironmentRepository:















حقن التبعية



هنا تحتاج إلى التوقف والتعامل مع تبعيات المكون:



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


سنحل هذه المشكلات باستخدام مكتبة GetIt . قم بتوصيل الحزمة المطلوبة بـ pubspec.yaml :







أنشئ مثيلًا لحاوية الحاقن lib / di / di_container.dart واكتب طريقة مع تسجيل المستودع والخدمة: اتصل بطريقة تهيئة حاوية DI في طريقة تحضير التطبيق:















طبقة الشبكة



lib / controller / ActuatorController - مكون شبكة HTTP. يحتوي على طرق للوصول إلى بيانات الخدمة الخاصة بالتطبيق: دعنا نعلن عن معالجات المسار لوحدات التحكم في lib / controller / Routes :















البداية الأولى



للتشغيل تحتاج:



  • قم بتعبئة التطبيق في صورة Docker ،
  • إضافة حاوية إلى النص البرمجي لإنشاء عامل الإرساء ،
  • تكوين NGINX لطلبات الوكيل.


قم بإنشاء Dockerfile في مجلد التطبيق . هذا هو البرنامج النصي لبناء وتشغيل صورة Docker: أضف حاوية التطبيق إلى البرنامج النصي docker-compose.yaml : قم بإنشاء ملف data_app.env بمتغيرات التكوين للتطبيق: أضف موقعًا جديدًا إلى NGINX debug config conf.dev.d / default.conf : قم بتشغيل التصحيح نص برمجي مع علامة ما قبل الإنشاء:



































docker-compose -f docker-compose.yaml -f docker-compose.dev.yaml up --build






تم تشغيل النص بنجاح ، ولكن هناك عدة نقاط تنذر بالخطر:



  • الصورة الرسمية للسهام من جوجل 290 ميجا بايت مؤرشفة . عند تفريغها ، ستستهلك مساحة أكبر بكثير - 754 ميجابايت. عرض قائمة بالصور وأحجامها:



    docker images
  • كان وقت تجميع الإنشاء و JIT أكثر من 100 ثانية. الكثير لتشغيل تطبيق للبيع
  • استهلاك الذاكرة في Docker dashboard 300 ميجا بايت مباشرة بعد الإطلاق



  • في اختبار تحميل (شبكة GET / api / مشغل / طلبات فقط) يكون استهلاك الذاكرة في نطاق 350-390 ميجابايت لتطبيق يعمل في عزلة واحدة





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



  • قم بإنشاء مجلد على الخادم للإصدار الجديد من التطبيق وانسخ محتويات المشروع



    ssh root@dartservice.ru "mkdir -p /opt/srv_2" && scp -r ./* root@91.230.60.120:/opt/srv_2/
  • أنت الآن بحاجة إلى نقل مشروع صفحة الويب إلى هذا المجلد / opt / srv_1 / public / والمحتويات الكاملة للمجلد / opt / srv_1 / sertbot / (يحتوي على شهادات SSL لـ NGINX ودعنا نقوم بتشفير سجلات bot) ، ونسخ المفتاح من / opt / srv_1 / dhparam /
  • قم بتشغيل مراقب مورد الخادم في وحدة تحكم منفصلة



    htop


  • لنقم بتشغيل البرنامج النصي docker-compose في المجلد / opt / srv_2 /



    docker-compose up --build -d
  • هذه هي الطريقة التي تبدو بها مجموعة التطبيق قبل الإطلاق:





  • وهكذا - أثناء العمل:







    من ذاكرة الوصول العشوائي (RAM) المتوفرة بسعة 1 جيجابايت ، يستهلك تطبيقنا 1.5 جيجابايت "يشغل" ملف الترحيل المفقود. نعم ، لقد بدأ التطبيق ، لكننا لا نتحدث عن أي سعة تحميل.
  • دعنا نتوقف عن النص:



    docker-compose down


AOT



لدينا ثلاث مهام لحلها:



  • تقليل استهلاك ذاكرة الوصول العشوائي عن طريق تطبيق dart ،
  • تقليل وقت بدء التشغيل ،
  • تقليل حجم حاوية عامل التحميل للتطبيق.


سيكون الحل هو التخلي عن dart في وقت التشغيل. منذ الإصدار 2.6 ، تدعم تطبيقات dart التحويل البرمجي إلى كود تنفيذي أصلي . يدعم Aqueduct التجميع بدءًا من الإصدار 4.0.0-b1.



لنبدأ بإزالة قناة CLI محليًا:



pub global deactivate aqueduct


قم بتثبيت الإصدار الجديد:



pub global activate aqueduct 4.0.0-b1


دعنا نرفع التبعيات في pubspec.yaml: لنقم ببناء







التطبيق الأصلي:



aqueduct build


ستكون النتيجة تجميع ملف واحد data_app.aot بحجم 6 ميغابايت تقريبًا. يمكنك تشغيل هذا التطبيق فورًا باستخدام معلمات ، على سبيل المثال:



data_app.aot --port 8080 --isolates 2


استهلاك الذاكرة مباشرة بعد الإطلاق أقل من 10 ميجا بايت.



دعونا نرى تحت الحمل. معلمات الاختبار: طلبات GET / مشغل الشبكة ، 100 موضوع بأقصى سرعة متاحة ، 10 دقائق. النتيجة:







الإجمالي: متوسط ​​السرعة - 13 ألف طلب في الثانية لجسم استجابة JSON 1.4 كيلو فولت ، متوسط ​​وقت الاستجابة - 7 مللي ثانية ، استهلاك الذاكرة (لمثيلتين) 42 ميجا بايت. لا توجد أخطاء.



عندما نكرر الاختبار مع ست مثيلات للتطبيق ، فإن متوسط ​​السرعة بالطبع يرتفع إلى 19 كيلو / ثانية ، لكن استخدام المعالج يصل إلى 45٪ عندما يكون استهلاك الذاكرة 64 ميجا بايت.

هذه نتيجة ممتازة.



تعبئة الحاويات



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



سيكون الحل هنا عبارة عن منصة رصيف وسيطة ، تستخدم فقط لبناء تطبيقات أصلية لـ Ubuntu. دعنا نكتبها / dart2native / Dockerfile : لنقم الآن ببنائها في صورة عامل إرساء تسمى aqueduct_builder: 4.0.0-b1 ، للكتابة فوق الإصدارات القديمة ، إن وجدت:











docker build --pull --rm -f "dart2native\Dockerfile" -t aqueduct_builder:4.0.0-b1 "dart2native"


دعونا تحقق:



docker images






لنكتب نصًا برمجيًا للبناء للتطبيق الأصلي docker-compose.dev.build.yaml : قم بتشغيل البرنامج النصي للبناء:











docker-compose -f docker-compose.dev.build.yaml up






الملف data_app.aot المترجم لـ Ubuntu يأخذ بالفعل 9 ميغابايت. عند بدء التشغيل ، يستخدم 19 ميغابايت من ذاكرة الوصول العشوائي (لحالتين). دعونا نجري اختبار الحمل المحلي بنفس الشروط ، ولكن في حاوية بها وكلاء NGINX (GET ، 100 موضوع):







في المتوسط ​​، 5.3 ألف طلب في الثانية. في نفس الوقت لم يتجاوز استهلاك ذاكرة الوصول العشوائي 55 ميجا بايت. انخفض حجم الصورة مقارنة بالقناة والقناة المثبتة من 840 ميجا بايت إلى 74 ميجا بايت على القرص. لنكتب



نصًا جديدًا docker-compose.aot.yaml لتشغيل التطبيق. للقيام بذلك ، سنستبدل كتلة وصف data_app عن طريق تثبيت الصورة الأساسية "فارغة" Ubuntu: 20.10. لنقم بتركيب ملف التجميع وتغيير أمر التشغيل:







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



  • التسجيل في سجل عام مثل DockerHub ،
  • تسجيل الدخول محليًا بنفس تسجيل الدخول



    docker login 
  • أعد تسمية الصورة التي تم تحميلها باستخدام تسجيل الدخول / العنوان: مخطط العلامات



    docker image tag a365ac7f5bbb andx2/aqueduct:4.0.0-b1
  • تفريغ الصورة في التسجيل



    docker push andx2/aqueduct:4.0.0-b1


    https://hub.docker.com/repository/docker/andx2/aqueduct/general



الآن يمكننا تعديل نص البناء الخاص بنا لاستخدام الصورة العامة







اتصال قاعدة البيانات



يحتوي Aqueduct بالفعل على ORM مدمج للعمل مع قاعدة بيانات PostgreSQL. لاستخدامه تحتاج:



  • إنشاء كائنات المجال التي تصف السجلات في قاعدة البيانات.
  • . : , , . Aqueduct , , ManagedObject ( ), , . .
  • . , , .
  • , aqueduct, , seed() — - .
  • aqueduct CLI.


لنبدأ بتوصيل حاوية عامل إرساء جديدة بقاعدة بيانات PostgreSQL في البرنامج النصي docker-compose.aot.yaml. صورة جاهزة تعتمد على Linux Alpine (إصدار "مضغوط" من Linux للتطبيقات المضمنة): هنا تحتاج إلى الانتباه إلى ملف متغير البيئة data_db.env . الحقيقة هي أن الصورة مهيأة مسبقًا لاستخدام هذه المتغيرات كاسم مستخدم ومضيف ومنفذ وكلمة مرور للوصول. دعنا نضيف هذه المتغيرات إلى الملف: القيم معطاة بشروط. سنقوم أيضًا بتركيب المجلد المضيف ./data_db/ في حاوية لتخزين بيانات قاعدة البيانات. بعد ذلك ، في تطبيق data_app ، أضف فئة / service / DbHelper للاتصال بقاعدة البيانات باستخدام متغيرات البيئة:





























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















































aqueduct db generate
ستكون النتيجة إنشاء ملفات ترحيل في مجلد المشروع: أنت الآن بحاجة إلى حل مشكلة الخدمة: يجب تطبيق عمليات الترحيل من نظام يحتوي على قناة مائية (وسهام) مثبتة على قاعدة بيانات تعمل في حاوية ، ويجب أن يتم ذلك أثناء التطوير المحلي وعلى الخادم. في هذه الحالة ، سوف نستخدم الصورة التي تم إنشاؤها ونشرها مسبقًا لتجميع AOT. دعنا نكتب البرنامج النصي لترحيل قاعدة بيانات docker-compose المقابل: التفاصيل المثيرة للاهتمام هي سلسلة اتصال قاعدة البيانات. عند تشغيل البرنامج النصي ، يمكنك تمرير ملف بمتغيرات البيئة كوسيطة ، ثم استخدام هذه المتغيرات للاستبدال في البرنامج النصي:























docker-compose -f docker-compose.migrations.yaml --env-file=./data_app.env --compatibility up --abort-on-container-exit


دعنا ننتبه أيضًا إلى أعلام الإطلاق:



  • - التوافق - التوافق مع إصدارات عامل الإرساء من البرامج النصية 2.x. سيسمح هذا باستخدام خيارات النشر لتقييد استخدام الموارد بواسطة الحاوية ، والتي يتم تجاهلها في الإصدارات 3.x. حددنا استهلاك ذاكرة الوصول العشوائي (RAM) بـ 200 ميجابايت واستخدام وحدة المعالجة المركزية إلى 50٪
  • --abort-on-container-exit - تحدد هذه العلامة وضع تنفيذ البرنامج النصي بحيث يتم إنهاء جميع الحاويات الأخرى عند توقف إحدى حاويات البرنامج النصي. لذلك ، عند تنفيذ أمر ترحيل مخطط قاعدة البيانات وتوقف الحاوية التي تحتوي على قناة مائية ، سينهي عامل الإرساء أيضًا حاوية قاعدة البيانات.


النشر



للتحضير لنشر التطبيق ، يجب عليك:



  • data_app.env data_db.env. , POSTGRES_PASSWORD=postgres_password
  • docker-compose.aot.yaml docker-compose.yaml.
  • /api/actuator. .


انسخ مجلد التطبيق ./data_app/ إلى الخادم . ستكون النقطة المهمة هنا هي التبديل -p (نسخ مع الاحتفاظ بسمات الملف) في أمر copy. دعني أذكرك أنه عند إنشاء التطبيق الأصلي ، قمنا بتعيين حقوق التنفيذ إلى ملف data_app.aot :



scp -rp ./data_app root@dartservice.ru:/opt/srv_1


لنقم أيضًا بنسخ:



  • تم تغيير تكوين NGINX ./conf.d/default.conf
  • البرامج النصية لبدء التشغيل والترحيل docker-compose.yaml ، docker-compose.migrations.yaml
  • الملفات ذات متغيرات البيئة data_app.env و data_db.env


أضف المجلد / opt / srv_1 / data_db على الخادم . هذا هو حجم نظام ملفات المضيف الذي سيتم تحميله في حاوية قاعدة البيانات. سيتم حفظ جميع بيانات PostgreSQL هنا.



mkdir /opt/srv_2/data_db


دعنا ننفذ البرنامج النصي لترحيل مخطط قاعدة البيانات:



docker-compose -f docker-compose.migrations.yaml --env-file=./data_app.env up --abort-on-container-exit


لنقم بتشغيل البرنامج النصي للتطبيق:



docker-compose up -d


-> شفرة المصدر جيثب



بدلا من الاستنتاج



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



All Articles