كيف يرفع Braze روبي على نطاق واسع

نشرت: 2022-08-18

إذا كنت مهندسًا يقرأ Hacker News أو Developer Twitter أو أي مصادر معلومات أخرى مماثلة ، فمن المؤكد أنك صادفت آلاف المقالات بعناوين مثل "Speed ​​of Rust vs C" و "What Makes Node. js أسرع من Java؟ "، أو" لماذا يجب عليك استخدام Golang وكيفية البدء. " توضح هذه المقالات بشكل عام أن هناك لغة معينة هي الخيار الواضح لقابلية التوسع أو السرعة - وأن الشيء الوحيد الذي عليك فعله هو تبنيها.

بينما كنت في الكلية وسنتي الأولى أو الثانية كمهندس ، كنت أقرأ هذه المقالات وأقوم على الفور بتدوير مشروع الحيوانات الأليفة لتعلم اللغة الجديدة أو إطار عمل du jour. بعد كل شيء ، كان مضمونًا للعمل "على نطاق عالمي" و "أسرع من أي شيء رأيته على الإطلاق" ، ومن يستطيع مقاومة ذلك؟ في النهاية اكتشفت أنني لست بحاجة في الواقع إلى أي من هذه الأشياء المحددة جدًا لمعظم مشاريعي. ومع تقدم حياتي المهنية ، أدركت أنه لا توجد لغة أو خيار إطار عمل من شأنه أن يمنحني هذه الأشياء مجانًا.

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

هنا في Braze ، نعمل على نطاق عالمي هائل. ونعم ، نستخدم Ruby و Rails كاثنتين من أدواتنا الأساسية للقيام بذلك. ومع ذلك ، لا توجد قيمة تكوين "global_scale = true" تجعل كل ذلك ممكنًا - إنها نتيجة بنية مدروسة جيدًا تمتد بعمق داخل التطبيقات وصولاً إلى طوبولوجيا النشر. يدرس المهندسون في Braze باستمرار الاختناقات المتدرجة ويكتشفون كيفية جعل نظامنا أسرع ، والإجابة عادة ليست "الابتعاد عن روبي": من المؤكد أنه سيكون تغييرًا في البنية.

لذلك دعونا نلقي نظرة على كيفية تعزيز Braze للهندسة المعمارية المدروسة لحل مشكلة السرعة والنطاق العالمي الهائل - وأين تناسبها Ruby و Rails (ولا تناسبها)!

قوة الهندسة المعمارية الأفضل في فئتها

طلب ويب بسيط

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

  1. يبدأ بمحلل DNS الخاص بالعميل (عادة ما يكون مزود خدمة الإنترنت) الذي يكتشف عنوان IP الذي يجب أن ينتقل إليه ، بناءً على المجال في عنوان URL لموقع الويب الخاص بك.

  2. بمجرد حصول العميل على عنوان IP ، سيرسل الطلب إلى موجه البوابة الخاص به ، والذي سيرسله إلى جهاز التوجيه "الخطوة التالية" (والذي قد يحدث عدة مرات) ، حتى يشق الطلب طريقه إلى عنوان IP الوجهة.

  3. من هناك ، سيعالج نظام التشغيل على الخادم الذي يتلقى الطلب تفاصيل الشبكة ويخطر عملية انتظار خادم الويب باستلام طلب وارد على المقبس / المنفذ الذي كان يستمع عليه.

  4. سيقوم خادم الويب بكتابة الاستجابة (المورد المطلوب ، ربما index.html) إلى هذا المقبس ، والذي سينتقل للخلف عبر أجهزة التوجيه إلى العميل.

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

أول الأنظمة التي تدعم الميزان

عادةً لا تتطلب خوادم DNS وخوادم الأسماء قدرًا كبيرًا من الاهتمام في معظم الحالات. من المحتمل أن يكون لخادم اسم المجال ذي المستوى الأعلى بعض الإدخالات لتعيين "yourwebsite.com" إلى خوادم الأسماء لمجالك ، وإذا كنت تستخدم خدمة مثل Amazon Route 53 أو Azure DNS ، فسوف يتعاملون مع الاسم خوادم لنطاقك (مثل إدارة A أو CNAME أو أي نوع آخر من السجلات). لا يتعين عليك عادةً التفكير في توسيع نطاق هذا الجزء ، حيث سيتم التعامل مع ذلك تلقائيًا بواسطة الأنظمة التي تستخدمها.

ومع ذلك ، يمكن أن يصبح جزء التوجيه من التدفق ممتعًا. هناك عدد قليل من خوارزميات التوجيه المختلفة ، مثل Open Shortest Path First أو بروتوكول معلومات التوجيه ، وكلها مصممة للعثور على أسرع / أقصر طريق من العميل إلى الخادم. نظرًا لأن الإنترنت عبارة عن رسم بياني عملاق متصل (أو شبكة تدفق بالتناوب) ، فقد تكون هناك مسارات متعددة يمكن الاستفادة منها ، كل منها بتكلفة أعلى أو أقل مقابلة. سيكون من المحظور القيام بالعمل للعثور على المسار الأسرع المطلق ، لذلك تستخدم معظم الخوارزميات أساليب الاستدلال المعقولة للحصول على مسار مقبول. أجهزة الكمبيوتر والشبكات ليست موثوقة دائمًا ، لذلك نحن نعتمد على Fastly لتعزيز قدرة عملائنا على التوجيه إلى خوادمنا بشكل أسرع.

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

الباب الأمامي للنحاس

حسنًا ، لقد ذهب طلب عملائنا عبر الطريق السريع Fastly وهو يقع مباشرة عند الباب الأمامي لمنصة Braze - ماذا يحدث بعد ذلك؟

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

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

خوادم الويب

أخيرًا ، نصل إلى الجزء المثير (روبي): خادم الويب. نحن نستخدم Ruby on Rails ، ولكن هذا مجرد إطار عمل ويب - خادم الويب الفعلي هو Unicorn. يعمل Unicorn من خلال بدء عدد من العمليات العاملة على الجهاز ، حيث تستمع كل عملية عاملة إلى مقبس OS للعمل. إنه يتعامل مع إدارة العمليات لنا ، ويؤجل موازنة تحميل الطلبات إلى نظام التشغيل نفسه. نحتاج فقط إلى كود Ruby الخاص بنا لمعالجة الطلبات في أسرع وقت ممكن ؛ تم تحسين كل شيء آخر بشكل فعال خارج Ruby بالنسبة لنا.

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

تستغرق دورة الطلب / الاستجابة حوالي 10 مللي ثانية حتى تتم معالجة كود روبي — ويتم إنفاق جزء منها في انتظار Memcached و Redis. حتى لو أعدنا كتابة كل هذا بلغة أخرى ، فليس من الممكن حقًا الضغط على المزيد من الأداء للخروج من هذا. وفي النهاية ، فإن بنية كل ما قرأته حتى الآن هي التي تمكننا من توسيع نطاق عملية استيعاب البيانات هذه لتلبية احتياجات عملائنا المتزايدة باستمرار.

قوائم انتظار العمل

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

العمال

هذا بالتأكيد هو الجزء الأكثر إثارة للاهتمام — كيف نجعل العمال يتوسعون؟

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

هذا هو المكان الذي قد تبدأ فيه في رؤية أهمية اختيار إطار العمل أو اللغة. في النهاية ، سيكون العامل الأكثر كفاءة قادرًا على القيام بمزيد من العمل بسرعة أكبر. تميل اللغات المجمعة مثل C أو Rust إلى أن تكون أسرع بكثير في المهام الحسابية من اللغات المفسرة مثل Ruby ، ​​وقد يؤدي ذلك إلى موظفين أكثر كفاءة لبعض أعباء العمل. ومع ذلك ، أقضي وقتًا طويلاً في البحث عن الآثار ، والمعالجة الأولية لوحدة المعالجة المركزية هي كمية صغيرة بشكل مدهش منها في الصورة الكبيرة في Braze. نقضي معظم وقت المعالجة في انتظار الردود من مخازن البيانات أو الطلبات الخارجية ، وليس معالجة الأرقام ؛ لا نحتاج إلى كود C مُحسَّن بشكل كبير لذلك.

مخازن البيانات

حتى الآن ، كل ما قمنا بتغطيته قابل للتطوير. لذلك دعونا نأخذ دقيقة ونتحدث عن المكان الذي يقضي فيه موظفونا معظم وقتهم - مخازن البيانات.

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

كائنات البيانات المستقلة

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

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

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

الاتساق في نهاية المطاف

تستفيد Braze أيضًا من الاتساق النهائي كعقيدة لمعظم عمليات القراءة. يتيح لنا ذلك الاستفادة من القراءة من كل من الأعضاء الأساسيين والثانويين لمجموعات النسخ المتماثلة لـ MongoDB في معظم الحالات ، مما يجعل بنيتنا المعمارية أكثر كفاءة. يسمح لنا هذا المبدأ في نموذج البيانات الخاص بنا باستخدام التخزين المؤقت في جميع أنحاء مكدسنا بشكل كبير.

نحن نستخدم نهجًا متعدد الطبقات باستخدام Memcached - بشكل أساسي ، عند طلب مستند من قاعدة البيانات ، سنتحقق أولاً من عملية Memcached المحلية للجهاز مع وقت منخفض جدًا للعيش (TTL) ، ثم تحقق من مثيل Memcached البعيد (باستخدام TTL أعلى) ، قبل أن تطلب قاعدة البيانات مباشرة. يساعدنا هذا في تقليل عمليات قراءة قاعدة البيانات بشكل كبير للمستندات الشائعة ، مثل إعدادات العملاء أو تفاصيل الحملة. قد تبدو كلمة "أخيرًا" مخيفة ، لكنها في الواقع بضع ثوانٍ فقط ، واتباع هذا النهج يخفض قدرًا هائلاً من حركة المرور من مصدر الحقيقة. إذا كنت قد درست في أي وقت مضى فصلًا دراسيًا عن هندسة الكمبيوتر ، فقد تتعرف على مدى تشابه هذا النهج مع كيفية عمل نظام ذاكرة التخزين المؤقت لوحدات المعالجة المركزية L1 و L2 و L3!

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

حيث تناسب روبي وريلز

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

كان لدى Ruby and Rails سجل حافل في مساعدة الفرق على التكرار بسرعة عندما بدأت Braze في عام 2011 - وما زالت تستخدم من قبل GitHub و Shopify وغيرهما من العلامات التجارية الرائدة لأنها تستمر في جعل ذلك ممكنًا. يستمر تطويرها بنشاط من قبل مجتمعات Ruby و Rails ، على التوالي ، ولا يزال لدى كلاهما مجموعة كبيرة من المكتبات مفتوحة المصدر المتاحة لمجموعة متنوعة من الاحتياجات. يعتبر الزوج خيارًا رائعًا للتكرار السريع ، نظرًا لأنه يتمتع بقدر هائل من المرونة ، ويحافظ على قدر كبير من البساطة في حالات الاستخدام الشائعة. نجد أن هذا صحيح إلى حد كبير كل يوم نستخدمه.

الآن ، هذا لا يعني أن Ruby on Rails هو الحل الأمثل الذي سيعمل بشكل جيد للجميع. ولكن في Braze ، وجدنا أنه يعمل بشكل جيد للغاية لتشغيل جزء كبير من خط أنابيب استيعاب البيانات ، وخط أنابيب إرسال الرسائل ، ولوحة القيادة التي تواجه العملاء ، وكلها تتطلب تكرارًا سريعًا وهي أساسية لنجاح Braze النظام الأساسي ككل.

عندما لا نستخدم روبي

لكن انتظر! ليس كل ما نقوم به في Braze موجودًا في Ruby. هناك عدد قليل من الأماكن على مر السنين حيث قمنا بالدعوة لتوجيه الأمور نحو لغات وتقنيات أخرى لمجموعة متنوعة من الأسباب. دعنا نلقي نظرة على ثلاثة منهم ، فقط لتقديم نظرة ثاقبة إضافية حول متى نفعل ذلك ولا نعتمد على روبي.

1. خدمات المرسل

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

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

2. موصلات التيارات

تتيح ميزة تصدير البيانات كبيرة الحجم من Braze Currents لعملاء Braze دفق البيانات باستمرار إلى واحد أو أكثر من شركاء البيانات العديدين لدينا. يتم تشغيل المنصة بواسطة Apache Kafka ، ويتم البث عبر Kafka Connectors. يمكنك كتابتها تقنيًا بلغة Ruby ، ​​لكن الطريقة المدعومة رسميًا هي باستخدام Java. وبسبب الدرجة العالية من دعم Java ، فإن كتابة هذه الموصلات أسهل بكثير في القيام بها في Java عنها في Ruby.

3. تعلم الآلة

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

عندما تهم اللغة

من الواضح أن لدينا بعض الأمثلة الرائعة أعلاه حيث لم يكن روبي هو الخيار المثالي. هناك العديد من الأسباب التي قد تجعلك تختار لغة مختلفة - فيما يلي بعض الأسباب التي نعتقد أنها مفيدة بشكل خاص للنظر فيها.

بناء أشياء جديدة دون تبديل التكاليف

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

النظام البيئي اللغوي وبيئة العمل الخاصة بالمهام

بعض المهام أسهل بكثير مع لغة أو إطار عمل معين - نحن نحب بشكل خاص Rails و Grape لتطوير وظائف لوحة القيادة ، لكن كود التعلم الآلي سيكون كابوسًا مطلقًا للكتابة في Ruby ، ​​نظرًا لأن الأدوات مفتوحة المصدر غير موجودة. قد ترغب في استخدام إطار عمل أو مكتبة معينة لتنفيذ نوع من الوظائف أو التكامل ، وفي بعض الأحيان سيتأثر اختيارك للغة بذلك ، لأنه سيؤدي بالتأكيد إلى تجربة تطوير أسهل أو أسرع.

سرعة التنفيذ

في بعض الأحيان ، تحتاج إلى تحسين سرعة التنفيذ الأولية ، وستؤثر اللغة المستخدمة بشكل كبير على ذلك. هناك سبب وجيه لوجود الكثير من منصات التداول عالية التردد وأنظمة القيادة المستقلة مكتوبة بلغة C ++ ؛ يمكن أن تكون التعليمات البرمجية المجمعة محليًا سريعة للغاية! تستغل خدمات المرسل لدينا مبدأ التوازي / التزامن في Golang والذي لا يتوفر ببساطة في Ruby لهذا السبب بالذات.

معرفة المطور

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

افكار اخيرة

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

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

هل أنت مهتم بالعمل في Braze؟ نحن نوظف مجموعة متنوعة من الأدوار عبر فرق الهندسة وإدارة المنتجات وتجربة المستخدم. تحقق من صفحة الوظائف لدينا لمعرفة المزيد حول الأدوار المفتوحة وثقافتنا.