مرحبا بالجميع! في 28 أيار (مايو) ، نطلق المجموعة الأولى في دورة
Golang Developer . واليوم نشارك معك أول منشور مخصص لإطلاق هذه الدورة. دعنا نذهب.
مقتطفات رئيسية- كانت مجلة الإيكونومست بحاجة إلى مزيد من المرونة لتوزيع المحتوى على قناة رقمية متنوعة بشكل متزايد. لتحقيق هذا الهدف والمحافظة على مستوى عالٍ من الأداء والموثوقية ، انتقلت المنصة من بنية متجانسة إلى بنية ميكروسيرفيس.
- كانت الأدوات المكتوبة في Go مكونًا رئيسيًا للنظام الجديد الذي مكّن The Economist من توفير خدمات قابلة للتطوير وعالية الأداء وإنشاء منتجات جديدة بسرعة.
- Go ، التي تهدف إلى دعم التزامن وواجهة برمجة التطبيقات ، بالإضافة إلى إنشاء لغة ثابتة مجمعة ، سهلت تطوير أنظمة معالجة الأحداث الموزعة التي يمكن أن تتسع. وكان اختبار الدعم أيضا زائد.
- بشكل عام ، كانت تجربة فريق The Economist مع Go إيجابية ، وكان هذا أحد العوامل الحاسمة التي ساعدت في توسيع نطاق Content Platform.
- لن يكون Go دائمًا أداة مناسبة ، وهذا أمر طبيعي. لدى The Economist منصة متعددة اللغات وتستخدم لغات مختلفة حيث يكون ذلك منطقيًا.
انضممت إلى فريق تطوير
The Economist كمطور دروبال. ومع ذلك ، كانت مهمتي الحقيقية هي المشاركة في مشروع من شأنه أن يغير بشكل جذري تكنولوجيا إيصال المحتوى الإيكونوميست. في الأشهر القليلة الأولى التي قضيتها في تعلم Go ، عملت لعدة أشهر مع مستشار خارجي لإنشاء MVP (الحد الأدنى من المنتج القابل للتطبيق) ، ثم انضممت إلى الفريق مرة أخرى للإشراف على الانغماس في Go.
نشأ هذا التحول في التكنولوجيا عن طريق مهمة The Economist لتوسيع جمهورها الرقمي ، حيث ابتعد استهلاك الأخبار عن الوسائط المطبوعة. كانت مجلة الإيكونومست بحاجة إلى مزيد من المرونة لتقديم المحتوى إلى المزيد من القنوات الرقمية المتنوعة. لتحقيق هذا الهدف والمحافظة على مستوى عالٍ من الأداء والموثوقية ، انتقلت المنصة من بنية متجانسة إلى بنية ميكروسيرفيس. كانت الأدوات المكتوبة في Go مكونًا رئيسيًا للنظام الجديد الذي مكّن The Economist من توفير خدمات قابلة للتطوير وعالية الأداء وإنشاء منتجات جديدة بسرعة.
تطبيق Go in The Economist:
- سمح للمهندسين بتطوير وتنفيذ وظائف جديدة بسرعة.
- أفضل الممارسات المعتمدة لخدمات سريعة الفشل مع معالجة الأخطاء الذكية.
- يوفر دعمًا موثوقًا للتزامن والتشغيل الشبكي في نظام موزع.
- لقد أظهر نقصًا في النضج والدعم في بعض المناطق اللازمة للمحتوى والوسائط.
- سهلت منصة التي يمكن أن مقياس للنشر الرقمي.
لماذا اختارت الإيكونوميست Go؟للإجابة على هذا السؤال ، سيكون من المفيد إبراز الهيكل العام للمنصة الجديدة. النظام الأساسي ، المسمى Content Platform ، هو نظام لمعالجة الأحداث. يستجيب للأحداث من مختلف منصات تأليف المحتوى ويطلق دفقًا من العمليات المنفذة في خدمات مصغرة تعمل بشكل منفصل. تؤدي هذه الخدمات وظائف مثل توحيد البيانات ، وتحليل العلامات الدلالية ، والفهرسة في ElasticSearch ، وإرسال المحتوى إلى منصات خارجية مثل Apple News أو Facebook. يحتوي النظام الأساسي أيضًا على واجهة برمجة تطبيقات RESTful ، والتي تعد ، بالإضافة إلى GraphQL ، نقطة الدخول الرئيسية للعملاء والمنتجات الأمامية.
في تطوير بنية مشتركة ، حقق الفريق في اللغات التي تناسب احتياجات المنصة. تمت مقارنة Go مع Python و Ruby و Node و PHP و Java. على الرغم من أن كل لغة لها نقاط قوتها الخاصة ، إلا أن تطبيق Go هو الأنسب لهندسة المنصة. Go ، التي تهدف إلى دعم التزامن وواجهة برمجة التطبيقات ، بالإضافة إلى إنشاء لغة ثابتة مجمعة ، سهلت تطوير أنظمة معالجة الأحداث الموزعة التي يمكن أن تتسع. بالإضافة إلى ذلك ، فإن بناء جملة Go البسيط نسبيًا جعل من السهل المشاركة في التطوير والبدء في كتابة التعليمات البرمجية للعمل ، والتي وعدت بفوائد فورية لفريق يمر بمثل هذا التحول التكنولوجي الكبير. بشكل عام ، تم تحديد أن Go هي اللغة الأكثر ملاءمة لقابلية الاستخدام والكفاءة في نظام السحابة الموزعة.
بعد ثلاث سنوات: هل تواكب هذه الأهداف الطموحة؟كانت بعض عناصر تصميم المنصة متوافقة بشكل جيد مع لغة Go. يعد Failing Fast جزءًا هامًا من النظام لأنه يتكون من خدمات مستقلة موزعة. وفقًا لمبادئ تطبيق Twelve-Factor ("التطبيق المكون من 12 عاملًا") ، يجب أن يبدأ التطبيق بسرعة وفشل سريعًا (فشل سريع). يوفر تصميم Go كلغة ثابتة ومترجمة أوقات بدء تشغيل سريعة ، كما أن أداء برنامج التحويل البرمجي يتحسن باستمرار ولم يمثل أبدًا مشكلة في التصميم أو النشر. بالإضافة إلى ذلك ، سمح تصميم Go لمعالجة الأخطاء بأن تفشل التطبيقات ليس فقط بشكل أسرع ، ولكن أيضًا أذكى.
خطأ في التعاملالميزة التي يلاحظها المهندسون بسرعة في Go هي أنها من النوع Error بدلاً من نظام استثناء. في Go ، كل الأخطاء هي قيم. نوع الخطأ محدد مسبقًا وهو واجهة. تعد الواجهة في Go عبارة عن مجموعة محددة من الطرق ، ويمكن لأي نوع مستخدم آخر تلبية واجهة ما إذا كانت لديها نفس الأساليب. نوع الخطأ هو واجهة يمكن أن تصف نفسها على أنها سلسلة.
type error interface { Error() string }
هذا يعطي المهندسين المزيد من التحكم والوظائف في معالجة الأخطاء. عن طريق إضافة طريقة خطأ تقوم بإرجاع سلسلة في أي وحدة مستخدم ، يمكنك إنشاء الأخطاء الخاصة بك وإنشاءها ، على سبيل المثال ، باستخدام وظيفة جديدة أدناه ، والتي تأتي من حزمة الأخطاء.
type errorString struct { s string } func (e *errorString) Error() string { return es }
ماذا يعني هذا في الممارسة العملية؟ في Go ، تسمح الوظائف بقيم إرجاع متعددة ، لذلك إذا لم تنجح وظيفتك ، فسترجع على الأرجح قيمة خطأ. تشجعك اللغة على التحقق من الأخطاء بشكل صريح عند حدوثها (على عكس الاستثناء والقبض عليه) ، لذلك يجب أن تتضمن الشفرة عادةً علامة "if err!" = لا شيء " في البداية ، قد تبدو معالجة الأخطاء المتكررة هذه رتابة. ومع ذلك ، فإن الخطأ كقيمة يتيح لك استخدام Error لتبسيط معالجة الأخطاء. على سبيل المثال ، في النظام الموزع ، يمكنك بسهولة تنفيذ محاولات إعادة محاولة الاستعلامات من خلال التفاف الأخطاء.
سوف تحدث مشكلات الشبكة دائمًا في النظام ، سواء كان ذلك بإرسال البيانات إلى خدمات داخلية أخرى أو نقلها إلى أدوات تابعة لجهات أخرى. يوضح مثال حزمة Net كيف يمكنك استخدام الخطأ كنوع لتمييز أخطاء الشبكة المؤقتة عن الأخطاء الدائمة. استخدم فريق الإيكونوميست غلاف خطأ مماثل لإنشاء محاولات إعادة تزايدي عند إرسال محتوى إلى واجهات برمجة التطبيقات الخارجية.
package net type Error interface { error Timeout() bool
يعتقد مؤلفو الذهاب أن الاستثناءات ليست كلها استثنائية. من المرجح أن يستعيد المهندسون بذكاء من الأخطاء أكثر من تعطل التطبيق. بالإضافة إلى ذلك ، تتيح لك معالجة الأخطاء في Go التحكم بشكل أفضل في الأخطاء ، والتي يمكن أن تحسن جوانب مثل تصحيح الأخطاء أو قابليتها للاستخدام. ضمن Content Platform ، سمحت ميزة التصميم هذه في Go للمطورين باتخاذ قرارات مستنيرة فيما يتعلق بالأخطاء ، مما أدى إلى زيادة موثوقية النظام ككل.
اتساق البياناتاتساق البيانات هو عامل حاسم في منصة المحتوى. المحتوى في The Economist هو أساس العمل ، والهدف من Content Platform هو ضمان إمكانية نشر المحتوى مرة واحدة ومتاح في كل مكان. لذلك ، من المهم أن يكون لكل منتج ومستهلك ثبات البيانات مع Content Platform API. تستخدم المنتجات بشكل أساسي طلبات GraphQL لواجهة برمجة التطبيقات ، والتي تتطلب نظامًا ثابتًا ، والذي يعد بمثابة نوع من العقود بين المستهلكين والنظام الأساسي. يجب أن يكون المحتوى الذي تتم معالجته بواسطة النظام الأساسي متسقًا مع هذا المخطط. ساعدت اللغة الساكنة في تنفيذ ذلك وجعلت من السهل تحقيق تناسق البيانات.
اختبار مع الذهابميزة أخرى تعزز التناسق هي مجموعة اختبار Go. أتاح وقت التجميع السريع لـ Go ، بالإضافة إلى الاختبار من الدرجة الأولى كميزة من سمات اللغة ، للفريق دمج طرق اختبار فعالة في سير عمل التصميم وفشل سريع في خطوط أنابيب التجميع. أدوات اختبار Go تجعل من السهل الإعداد والتشغيل. سيؤدي تشغيل "go test" إلى تشغيل جميع الاختبارات في الدليل الحالي ، وسيحتوي أمر test على العديد من العلامات المفيدة. توفر علامة الغلاف تقرير تغطية تفصيليًا للرمز. يقوم اختبار مقاعد البدلاء بإجراء اختبارات القياس ، والتي تتم الإشارة إليها عن طريق تشغيل اسم وظيفة الاختبار بكلمة "مقعد" بدلاً من "اختبار". توفر وظيفة TestMain طرقًا لإعداد اختبار إضافي ، مثل خادم مصادقة وهمية.
بالإضافة إلى ذلك ، تتمتع Go بالقدرة على إنشاء اختبارات جدولية بهياكل مجهولة بذرة وكعب مع واجهات ، مما يؤدي إلى تحسين تغطية الاختبار. على الرغم من أن الاختبار ليس جديدًا فيما يتعلق بميزات اللغة ، فإن تطبيق Go يجعل من السهل إنشاء اختبارات قوية ودمجها بسهولة في مهام سير العمل. منذ البداية ، تمكن مهندسو الإيكونوميست من إجراء الاختبارات كجزء من خطوط أنابيب التجميع دون تكوين خاص ، بل وقاموا بإضافة Git Hooks لتشغيل الاختبارات قبل دفع الكود إلى Github.
ومع ذلك ، فإن المشروع لم يكن دون جهد في تحقيق اتساق البيانات. كانت المشكلة الرئيسية الأولى للمنصة هي إدارة المحتوى الديناميكي من نهايات خلفية غير متوقعة. يستهلك النظام الأساسي المحتوى من أنظمة CMS الأصلية بشكل أساسي من خلال نقاط النهاية JSON ، حيث لا يمكن ضمان البنية وأنواع البيانات. هذا يعني أن النظام الأساسي لا يمكنه استخدام حزمة Go القياسية لتفسير json ، والذي يدعم إلغاء تسلسل JSON إلى هياكل ، ولكنه يبدو ناقوسًا إذا لم تتطابق أنواع الحقول الهيكلية وبيانات الإدخال.
للتغلب على هذه المشكلة ، كانت هناك حاجة إلى طريقة خاصة لتعيين جزء الخادم بالتنسيق القياسي. بعد عدة تكرارات للنهج الذي تم اختياره ، قدم الفريق عملية إلغاء التسلسل الخاصة به. على الرغم من أن هذا النهج يشبه إلى حد ما إعادة صياغة حزمة مكتبة قياسية ، إلا أنه منح المهندسين السيطرة الكاملة على معالجة البيانات المصدر.
دعم الشبكةكانت قابلية التوسع في مقدمة النظام الأساسي الجديد ، وقد تم توفير ذلك بواسطة مكتبات Go القياسية للشبكات وواجهات برمجة التطبيقات. في Go ، يمكنك بسرعة تنفيذ نقاط النهاية HTTP قابلة للتحجيم دون الحاجة إلى الأطر. في المثال أدناه ، يتم استخدام حزمة مكتبة net / http القياسية لتكوين معالج يقبل كاتب الطلب والاستجابة. عند تطبيق Content Platform API لأول مرة ، استخدم إطار عمل API. تم استبداله في النهاية بمكتبة قياسية ، حيث أقر الفريق بأنها تلبي جميع احتياجات شبكتها دون أي تنازلات إضافية غير ضرورية. مقياس معالجات Golang HTTP لأن كل طلب إلى المعالج يتم تنفيذه بالتوازي في Goroutine ، وهو مؤشر ترابط خفيف الوزن دون الحاجة إلى التخصيص.
package main import ( "fmt" "log" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) }
نموذج التزامنيوفر طراز التزامن Go مزايا متعددة في تحسين الأداء عبر النظام الأساسي. ينطوي العمل مع البيانات الموزعة على تداعيات الضمانات الموعودة للمستهلكين. وفقًا لنظرية CAP ، لا يمكن تقديم أكثر من ضمانين من الضمانات الثلاثة التالية في نفس الوقت: تناسق البيانات. توفر. مقاومة للفصل. في نظام الإيكونوميست ، تم اعتماد الاتساق في النهاية ، مما يعني أن القراءة من مصادر البيانات ستكون في نهاية المطاف متسقة ، والتأخير المعتدل في جميع مصادر البيانات التي تصل إلى حالة متسقة مقبول. طريقة واحدة لتقليل هذه الفجوة هي استخدام Goroutines.
Goroutines هي مؤشرات ترابط خفيفة يتم إدارتها بواسطة وقت التشغيل Go لمنعها من النفاد. يسمح Goroutines بتحسين المهام غير المتزامنة على النظام الأساسي. على سبيل المثال ، أحد مستودعات بيانات النظام الأساسي هو Elasticsearch. عندما يتم تحديث المحتوى على النظام ، يتم تحديث المحتوى الذي يشير إلى هذا العنصر في Elasticsearch وإعادة توصيفه. بفضل تطبيق Goroutines ، تم تقليل وقت المعالجة ، مما يضمن الاتساق السريع للعناصر. يوضح هذا المثال كيفية إعادة معالجة العناصر المناسبة لإعادة المعالجة في Goroutine.
func reprocess(searchResult *http.Response) (int, error) { responses := make([]response, len(searchResult.Hits)) var wg sync.WaitGroup wg.Add(len(responses)) for i, hit := range searchResult.Hits { wg.Add(1) go func(i int, item elastic.SearchHit) { defer wg.Done() code, err := reprocessItem(item) responses[i].code = code responses[i].err = err }(i, *hit) } wg.Wait return http.StatusOK, nil }
تصميم النظم هو أكثر من مجرد برمجة. يحتاج المهندسون إلى فهم أي الأدوات مناسبة ومتى. على الرغم من أن Go كانت أداة قوية لمعظم احتياجات The Contentist's Content Platform ، إلا أن بعض القيود كانت تتطلب حلولًا أخرى.
إدارة التبعيةعندما تم إصدار Go ، لم يكن لديها نظام لإدارة التبعية. داخل المجتمع ، تم تطوير العديد من الأدوات لتلبية هذه الحاجة. استخدمت الإيكونوميست وحدات Git الفرعية ، والتي كانت منطقية في الوقت الذي كان فيه المجتمع يعمل بنشاط على الترويج لأداة موحدة لإدارة التبعية. اليوم ، على الرغم من أن المجتمع أصبح بالفعل أقرب إلى نهج متماسك لإدارة التبعية ، إلا أنه غير موجود. لم يطرح نهج الإيكونوميست الذي يستخدم وحدات فرعية مشاكل خطيرة ، ولكن كان من الصعب على مطوري Go الآخرين ، ويجب أن يؤخذ ذلك في الاعتبار عند التبديل إلى Go.
كانت هناك أيضًا متطلبات النظام الأساسي التي لم تكن ميزات Go أو تصميمها هي الحل الأمثل. نظرًا لأن النظام الأساسي أضاف دعمًا للمعالجة الصوتية ، فإن أدوات Go لاستخراج البيانات الوصفية كانت محدودة في ذلك الوقت ، وبالتالي اختار الفريق Exiftool Python بدلاً من ذلك. تعمل خدمات النظام الأساسي في حاويات الإرساء ، مما سمح بتثبيت Exiftool وتشغيله من تطبيق Go.
func runExif(args []string) ([]byte, error) { cmdOut, err := exec.Command("exiftool", args...).Output() if err != nil { return nil, err } return cmdOut, nil }
سيناريو آخر شائع للمنصة هو استقبال كود HTML غير العامل من أنظمة CMS المصدر ، تحليل كود HTML لصحة وشفرة كود HTML. في البداية ، تم استخدام Go لهذه العملية ، ولكن بما أن مكتبة HTML القياسية في Go تتطلب HTML صحيحًا ، فقد تطلبت قدرًا كبيرًا من التعليمات البرمجية المخصصة لتحليل HTML قبل المعالجة. سرعان ما أصبح هذا الرمز هشًا وتخطى الحالات الحدودية ، لذلك تم تطبيق حل جديد في Javascript. لقد وفرت Javascript مرونة كبيرة وقدرة على التكيف للتحكم في عملية التحقق من HTML وتعقيمه.
كان Javascript أيضًا اختيارًا شائعًا لتصفية الأحداث وتوجيهها في النظام الأساسي. يتم تصفية الأحداث باستخدام AWS Lambdas ، وهي وظائف خفيفة الوزن تعمل فقط عند استدعائها. حالة استخدام واحدة هي تصفية الأحداث على نطاقات مختلفة ، مثل السرعة والبطء. يستند هذا التصفية إلى حقل بيانات تعريف واحد في كائن JSON الخاص بمعالج الأحداث. استخدم تطبيق التصفية حزمة مؤشر JSON Javascript لالتقاط عنصر في كائن JSON. كان هذا النهج أكثر فاعلية مقارنةً بتفكيك JSON بالكامل التي يحتاجها Go. بينما يمكن تحقيق وظائف من هذا النوع مع Go ، إلا أن استخدام Javascript كان أسهل للمهندسين وقدم أبسط اللمدات.
بأثر رجعي الذهاببعد تنفيذ "منصة الاتصال" ودعمها في الإنتاج ، إذا كنت سأجري بأثر رجعي من Go و Content Platform ، فإن تعليقاتي ستكون كما يلي:
ما هو جيد بالفعل؟
- عناصر تصميم اللغة الرئيسية للأنظمة الموزعة.
- نموذج التزامن سهل التنفيذ نسبيًا.
- الترميز لطيفة والمرح المجتمع.
ما يمكن تحسينه؟
- مزيد من التقدم في معايير التحكم في الإصدار والبيع.
- لا يكفي النضج في بعض المناطق.
- تفاصيل لحالات المستخدم المحددة.
بشكل عام ، كانت تجربة إيجابية ، و Go هي واحدة من أهم العناصر التي سمحت بتوسيع منصة المحتوى. لن يكون Go دائمًا أداة مناسبة ، وهذا أمر طبيعي. لدى The Economist منصة متعددة اللغات وتستخدم لغات مختلفة حيث يكون ذلك منطقيًا. من المحتمل ألا يكون Go هو الخيار الأفضل عندما تحتاج إلى العبث بكائنات نصية ومحتوى ديناميكي ، لذلك لا يزال Javascript في صندوق الأدوات. ومع ذلك ، فإن نقاط القوة لدى Go هي الأساس الذي يسمح للنظام بالنمو والنمو.
عند التفكير فيما إذا كان Go مناسبًا لك أم لا ، فكر في المشكلات الرئيسية لتصميم النظام:
- ما هي مهام نظامك؟
- ما الضمانات التي تقدمها للمستهلكين؟
- ما العمارة والأنماط المناسبة لنظامك؟
- كيف ينبغي أن مقياس النظام الخاص بك؟
إذا كنت تقوم بتطوير نظام يعالج تحديات البيانات الموزعة ، وسير العمل غير المتزامن ، والأداء العالي والقابلية للتوسعة ، فنوصيك بمراعاة Go وقدراته على تسريع أهداف النظام.
أيها الأصدقاء ، نحن ننتظر تعليقاتكم وندعو الجميع إلى
الندوة المفتوحة على الإنترنت ، والتي ستعقد يوم 16 من قبل المطور الأول في ياندكس ، وبالاشتراك مع
مدرسنا هو
ديمتري سمال .