ميخائيل سالوسين. لقاء جولانغ. استخدام Go في الواجهة الخلفية لتطبيق Watch +

ميخائيل سالوسين (فيما يلي - MS): - مرحبًا بالجميع! إسمي مايكل. أنا أعمل كمطور خلفية في MC2 Software ، وسأتحدث عن استخدام Go في الواجهة الخلفية لتطبيق Watch + mobile.



هل يوجد أحد مثل الهوكي؟



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



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

ما تم استخدامه في التنمية؟


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

استخدمنا Postgres (PostgreSQL) كقاعدة بيانات. تمت كتابة واجهة المحررين في Ruby on Rails باستخدام ActiveAdmin gem. استيراد الإحصائيات من مزود الإحصائيات مكتوب أيضًا على Ruby.

بالنسبة لاختبارات API للنظام ، استخدمنا Python unittest (Python). يستخدم Memcached لخنق طلبات الدفع API ، الشيف للتحكم في التكوين ، Zabbix لجمع ومراقبة إحصاءات النظام الداخلي. Graylog2 - لجمع السجلات ، يعد Slate وثائق API للعملاء.



اختيار البروتوكول


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

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

بناءً على ذلك ، كان لدينا خياران للبروتوكول:
  1. Websockets. لكننا لم نكن بحاجة إلى قنوات من العميل إلى الخادم. نحن بحاجة فقط لإرسال التحديثات من الخادم إلى العميل ، لذلك يعد مقبس الويب خيارًا متكررًا.
  2. الأحداث المرسلة من الخادم (SSE) جاءت على حق! إنه بسيط للغاية ويفي بشكل أساسي بكل ما نحتاجه.

الأحداث المرسلة بالخادم


بضع كلمات حول كيفية عمل هذا الشيء ...

يعمل فوق اتصال http. يرسل العميل طلبًا ، ويستجيب الخادم بنوع المحتوى: نص / دفق حدث ولا يغلق الاتصال مع العميل ، ولكنه يستمر في كتابة البيانات إلى الاتصال:



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

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



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

كيف يتم تقديم الاتصال المباشر؟


  • بادئ ذي بدء ، نقوم بإنشاء قناة تأتي التحديثات من خلال المخزن المؤقت.
  • بعد ذلك ، نشترك في هذه القناة لتلقي التحديثات.
  • قم بتعيين الرأس الصحيح بحيث يعلم العميل أن كل شيء على ما يرام.
  • ping. timestamp .
  • , . timestamp, , .



كانت المشكلة الأولى التي واجهناها هي ما يلي: لكل اتصال مفتوح مع العميل ، أنشأنا مؤقتًا تم وضع علامة عليه مرة واحدة كل 15 ثانية - اتضح إذا كان لدينا 6000 اتصال بجهاز واحد (مع خادم API واحد) ، تم إنشاء 6 آلاف جهاز توقيت. هذا أدى إلى حقيقة أن الجهاز لم يحمل الحمولة اللازمة. لم تكن المشكلة واضحة لنا ، لكنهم ساعدونا قليلاً ، وقمنا بالقضاء عليها.

نتيجة لذلك ، لدينا الآن ping قادم من نفس القناة التي يأتي منها التحديث.

وفقًا لذلك ، لا يوجد سوى مؤقت واحد يتم وضع علامة عليه مرة واحدة كل 15 ثانية.

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



آلية لإرسال التحديثات


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

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



PostgreSQL: الاستماع / الإخطار


تسمح لك آلية الاستماع / الإخطار في Postgres بإخطار المشتركين بالأحداث التي تغيرت بعض الأحداث - تم إنشاء نوع من التسجيل في قاعدة البيانات. للقيام بذلك ، كتبنا



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

بالنسبة لجميع الجداول التي يجب مزامنتها مع العميل ، نحدد مشغلًا ، بعد تغيير / تحديث السجل ، يستدعي الوظيفة الموضحة في الشريحة أدناه.
كيف تشترك واجهة برمجة التطبيقات في هذه التغييرات؟

يتم إنشاء آلية Fanout - فهي ترسل رسائل إلى العميل. يجمع جميع قنوات العملاء ويرسل التحديثات التي تلقاها من خلال هذه القنوات:



هنا تقوم مكتبة pq القياسية ، التي تتصل بقاعدة البيانات وتقول أنها تريد الاستماع إلى القناة (data_updates) ، بالتحقق من أن الاتصال مفتوح وكل شيء على ما يرام. أنا أغفل تدقيق الأخطاء لتوفير مساحة (لا تحقق مشحونة).

بعد ذلك ، نقوم بتعيين Ticker بشكل غير متزامن ، والذي سيرسل الأمر ping كل 15 ثانية ، ونبدأ في الاستماع إلى القناة التي اشتركنا فيها. إذا حصلنا على ping ، فإننا ننشر هذا ping. إذا تلقينا سجلاً ، فإننا ننشر هذا السجل لجميع المشتركين في Fanout.

كيف يعمل التخرج؟


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



كيف يتم تنفيذه على Go:



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

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

هناك أيضًا طريقة اشتراك تضيف قناة إلى المستمعين:



هناك طريقة إلغاء الاشتراك التي تزيل القناة من المستمعين إذا قطع العميل ، بالإضافة إلى طريقة النشر التي تسمح لك بإرسال رسالة إلى جميع المشتركين.

سؤال: - ما الذي ينتقل عبر هذه القناة؟

م.س: - يرسل نموذج تغير أو ping (بالأساس مجرد رقم صحيح).

تصلب متعدد:- يمكنك إرسال أي شيء ، نشر أي هيكل ، يتحول فقط إلى JSON وهذا كل شيء.

م.س: - نحصل على إشعار من Postgres - يحتوي على اسم الجدول ومعرفه. بواسطة اسم الجدول الذي نحصل عليه والمعرف نحصل على السجل الذي نحتاجه ، وقد تم بالفعل إرسال هذه البنية للنشر.

بنية تحتية


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



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

هناك أيضا مستورد للإحصاءات. هناك الرقيق DB الذي يتم عمل النسخ الاحتياطية بشكل دوري. هناك Pigeon Pusher - التطبيق الذي يرسل الدفعات للعملاء ، بالإضافة إلى أشياء البنية التحتية: Zabbix و Graylog2 و Chef.

في الواقع ، هذه البنية التحتية زائدة عن الحاجة ، لأنه يمكن تقديم 100 ألف خادم أقل. ولكن كان هناك حديد - استخدمناه (قيل لنا أنه من الممكن - لماذا لا).

إيجابيات Go


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




نحن نبحث عن مطورين! إذا أراد أحد - من فضلك.

الأسئلة


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

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

س: - هل يمكن أن ترسل على الفور للاستماع / إعلام سجل ، وليس جدول معرف؟

تصلب متعدد:- حد الاستماع / الإخطار بحد أقصى 8 آلاف بايت لكل تحميل مسبق يرسله. من حيث المبدأ ، سيكون من الممكن الإرسال إذا كنا نتعامل مع كمية صغيرة من البيانات ، ولكن يبدو لي أن الطريقة [كما نفعل] هي ببساطة أكثر موثوقية. القيود في Postgres نفسها.

س: - هل يتلقى العملاء تحديثات على المباريات التي لا يهتمون بها؟

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

س: - لماذا جعلت ORM الخاص بك؟

أليكسي (أحد مطوري "Watch +"):- في ذلك الوقت (كان ذلك قبل عام) كان ORM أقل من الآن ، عندما يكون هناك الكثير منهم. من بين أغلبية ORMs الحالية ، فإن أكثر ما يعجبني هو أن معظمها يعمل على واجهات فارغة. أي أن الطرق التي في ORMs هذه جاهزة للتعامل مع أي شيء: الهيكل ، مؤشر الهيكل ، العدد ، أي شيء غير ذي صلة على الإطلاق ...

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

س: - كم شخص شارك؟

م.س .: - في المرحلة الأولية ، شارك شخصان. في مكان ما في يونيو ، بدأنا ، في أغسطس كان الجزء الرئيسي جاهزًا (الإصدار الأول). في سبتمبر كان هناك بيان.

في:- عندما تصف SSE ، لا تستخدم المهلة. لماذا هذا؟

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

س: - ما هي المرافق الإضافية التي استخدمتها؟

تصلب متعدد:- الأكثر نشاطا استخدمنا الحكومة والمشيقة ، بحيث تم توحيد النمط ، وكذلك gofmt. لم يستخدموا أي شيء آخر.

س: - بماذا قمت بتصحيحه؟

م.س: على العموم ، تم إجراء التصحيح باستخدام الاختبارات. لا مصحح أخطاء ، الحزب الجمهوري لم نستخدمها.

س: - هل يمكنك إرجاع الشريحة حيث تم تنفيذ وظيفة النشر؟ أسماء المتغيرات ذات الحرف الواحد لا تزعجك؟

م.س: - لا. لديهم نطاق "ضيق" إلى حد ما. لا يتم استخدامها في أي مكان آخر (باستثناء هنا) (باستثناء الأجزاء الداخلية من هذه الفئة) ، وهي مضغوطة جدًا - فهي تأخذ 7 خطوط فقط.

س: - بطريقة ما لا تزال غير بديهية ...

MS:- لا ، لا ، هذا رمز حقيقي! لا يتعلق الأمر بالأناقة. إنها مجرد فئة نفعية صغيرة جدًا - هناك 3 حقول فقط داخل الفصل ...



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

س: - هل هناك أي حزم طرف ثالث لإدارة التبعية؟

مايكل: - لقد استخدمنا الذهاب dep.

س: - كان هناك شيء حول الفيديو في موضوع التقرير ، ولكن لا يوجد شيء حول الفيديو في التقرير.

م.س .: - لا ، ليس لدي أي شيء في موضوع الفيديو. يطلق عليه "Look +" - هذا هو اسم التطبيق.

في:- قلت إنك تبث إلى العملاء؟ ..

م.س: - لم نقم ببث الفيديو. تم ذلك بالكامل بواسطة مكبر الصوت. نعم ، لم أقل أن التطبيق مكبر صوت.

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


القليل من الدعاية :)


أشكركم على البقاء معنا. هل تحب مقالاتنا؟ هل تريد رؤية مواد أكثر إثارة للاهتمام؟ ادعمنا عن طريق تقديم طلب أو التوصية لأصدقائك VPS القائم على السحابة للمطورين من $ 4.99 ، وهو نظير فريد من نوعه لخوادم مستوى الدخول التي اخترعناها لك: الحقيقة الكاملة عن VPS (KVM) E5-2697 v3 (6 نوى) 10GB DDR4 480GB SSD 1Gbps من $ 19 أو كيفية تقسيم الخادم؟ (تتوفر الخيارات مع RAID1 و RAID10 ، حتى 24 مركزًا و 40 جيجابايت DDR4).

Dell R730xd أرخص مرتين في مركز بيانات Equinix Tier IV في أمستردام؟ فقط لدينا 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV من 199 دولارًا في هولندا!Dell R420 - 2x E5-2430 2.2 جيجا هرتز 6C 128 جيجا بايت DDR3 2x960GB SSD 1Gbps 100TB - من 99 دولار! اقرأ عن كيفية بناء مبنى البنية التحتية الفئة c باستخدام خوادم Dell R730xd E5-2650 v4 بتكلفة 9000 يورو مقابل سنت واحد؟

All Articles