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

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

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

هل يوجد أحد هنا يحب الهوكي؟

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

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

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

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

ماذا استخدمت في التطوير؟

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

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

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

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

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

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

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

وبناءً على ذلك، كان لدينا خياران للبروتوكول:

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

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

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

يتم تشغيله فوق اتصال http. يرسل العميل طلبًا، ويستجيب الخادم باستخدام Content-Type: text/event-stream ولا يغلق الاتصال مع العميل، ولكنه يستمر في كتابة البيانات إلى الاتصال:

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

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

الآن دعونا نتحدث عن كيفية عمل التفاعل نفسه.

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

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

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

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

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

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

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

ونتيجة لذلك، يأتي الآن اختبار الاتصال لدينا من نفس القناة التي يأتي منها التحديث.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

كيف يعمل Fan-out؟

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

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

كيف يتم تنفيذها في Go:

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

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

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

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

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

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

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

السيدة: - النموذج الذي تم تغييره أو إرسال أمر ping (في الأساس مجرد رقم، عدد صحيح).

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

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

بنية التحتية

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

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

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

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

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

إيجابيات الذهاب

بعد أن عملنا على هذا التطبيق، ظهرت المزايا الواضحة لـ Go.

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

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

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

الأسئلة

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

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

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

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

В: – هل يتلقى العملاء تحديثات بشأن المباريات التي لا يهتمون بها؟

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

В: – لماذا قمت بإنشاء ORM الخاص بك؟

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

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

В: – كم عدد الأشخاص الذين شاركوا؟

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

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

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

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

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

В: - ماذا استخدمت لتصحيح الأخطاء؟

السيدة: - تم إجراء التصحيح إلى حد كبير باستخدام الاختبارات. لم نستخدم أي مصحح أخطاء أو GOP.

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

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

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

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

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

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

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

السيدة: - استخدمنا الذهاب ديب.

В: – كان هناك شيء يتعلق بالفيديو في موضوع التقرير، ولكن لم يكن هناك شيء يتعلق بالفيديو في التقرير.

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

В: – قلت أنه يتم بثه للعملاء؟..

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

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

بعض الاعلانات 🙂

أشكركم على البقاء معنا. هل تحب مقالاتنا؟ تريد أن ترى المزيد من المحتوى المثير للاهتمام؟ ادعمنا عن طريق تقديم طلب أو التوصية للأصدقاء ، Cloud VPS للمطورين يبدأ من 4.99 دولارًا, تناظرية فريدة من خوادم المستوى المبتدئ ، اخترعناها من أجلك: الحقيقة الكاملة حول VPS (KVM) E5-2697 v3 (6 Cores) 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.6 جيجا هرتز 14C 64 جيجا بايت DDR4 4x960 جيجا بايت SSD 1 جيجابت في الثانية 100 تلفزيون من 199 دولارًا في هولندا! Dell R420 - 2x E5-2430 2.2 جيجا هرتز 6C 128 جيجا بايت DDR3 2x960 جيجا بايت SSD 1 جيجا بايت في الثانية 100 تيرا بايت - من 99 دولارًا! أقرأ عن كيفية بناء شركة البنية التحتية. فئة مع استخدام خوادم Dell R730xd E5-2650 v4 بقيمة 9000 يورو مقابل فلس واحد؟

المصدر: www.habr.com

إضافة تعليق