میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

میخائیل سالوسین (از این پس - ام اس): - سلام به همه! اسم من مایکل است. من به‌عنوان توسعه‌دهنده بک‌اند در MC2 Software کار می‌کنم و در مورد استفاده از Go در باطن اپلیکیشن موبایل Look+ صحبت خواهم کرد.

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

کسی اینجا هاکی دوست داره؟

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

سپس این برنامه برای شما مناسب است. این برای اندروید و iOS است و برای تماشای پخش آنلاین و ضبط شده رویدادهای ورزشی مختلف استفاده می شود. این برنامه همچنین شامل آمارهای مختلف، پخش متن، جداول کنفرانس ها، مسابقات و سایر اطلاعات مفید برای طرفداران است.

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

همچنین در برنامه چیزی به عنوان لحظات ویدیویی وجود دارد، یعنی می توانید مهمترین لحظات مسابقات (گل، دعوا، تیراندازی و غیره) را تماشا کنید. اگر نمی خواهید کل پخش را تماشا کنید، می توانید فقط جالب ترین ها را تماشا کنید.

از چه چیزی در توسعه استفاده کردید؟

قسمت اصلی در Go نوشته شده است. API که مشتریان موبایل با آن ارتباط برقرار می کردند در Go نوشته شده بود. سرویس ارسال پوش نوتیفیکیشن به تلفن همراه نیز در Go نوشته شد. ما همچنین مجبور شدیم ORM خودمان را بنویسیم، که ممکن است روزی در مورد آن صحبت کنیم. خب، چند سرویس کوچک در Go نوشته شد: تغییر اندازه و بارگذاری تصاویر برای ویرایشگرها...

ما از PostgreSQL به عنوان پایگاه داده استفاده کردیم. رابط ویرایشگر به زبان Ruby on Rails با استفاده از جواهر ActiveAdmin نوشته شده است. واردات آمار از یک ارائه دهنده آمار نیز به زبان روبی نوشته شده است.

برای تست های API سیستم، ما از Python unittest استفاده کردیم. Memcached برای کاهش تماس های پرداخت API استفاده می شود، "Chef" برای کنترل پیکربندی استفاده می شود، Zabbix برای جمع آوری و نظارت بر آمار سیستم داخلی استفاده می شود. Graylog2 برای جمع آوری گزارش ها است، Slate اسناد API برای مشتریان است.

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

انتخاب پروتکل

اولین مشکلی که با آن مواجه شدیم: بر اساس نکات زیر باید پروتکلی را برای تعامل بین باطن و کلاینت های موبایل انتخاب کنیم...

  • مهمترین نیاز: داده های مربوط به مشتریان باید در زمان واقعی به روز شوند. یعنی همه کسانی که در حال حاضر پخش را تماشا می کنند باید تقریباً فوراً به روز رسانی ها را دریافت کنند.
  • برای ساده‌تر کردن کارها، فرض کردیم داده‌هایی که با کلاینت‌ها همگام‌سازی می‌شوند، حذف نمی‌شوند، اما با استفاده از پرچم‌های خاص پنهان می‌شوند.
  • همه انواع درخواست های نادر (مانند آمار، ترکیب تیم، آمار تیم) توسط درخواست های GET معمولی به دست می آیند.
  • به علاوه، این سیستم مجبور بود به راحتی 100 هزار کاربر را همزمان پشتیبانی کند.

بر این اساس، ما دو گزینه پروتکل داشتیم:

  1. سوکت های وب اما ما نیازی به کانال از کلاینت به سرور نداشتیم. ما فقط نیاز به ارسال به روز رسانی از سرور به مشتری داشتیم، بنابراین یک وب سوکت یک گزینه اضافی است.
  2. رویدادهای ارسال شده توسط سرور (SSE) به درستی مطرح شد! این بسیار ساده است و اساساً همه چیزهایی را که ما نیاز داریم برآورده می کند.

رویدادهای ارسال شده توسط سرور

چند کلمه در مورد نحوه عملکرد این ...

در بالای یک اتصال http اجرا می شود. کلاینت درخواستی ارسال می کند، سرور با Content-Type: text/event-stream پاسخ می دهد و ارتباط با مشتری را نمی بندد، اما به نوشتن داده ها در اتصال ادامه می دهد:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

داده ها را می توان در قالب توافق شده با مشتریان ارسال کرد. در مورد ما، ما آن را به این شکل ارسال کردیم: نام ساختار تغییر یافته (شخص، بازیکن) به فیلد رویداد ارسال شد و JSON با فیلدهای جدید و تغییر یافته برای بازیکن به فیلد داده ارسال شد.

حالا بیایید در مورد نحوه عملکرد خود تعامل صحبت کنیم.

  • اولین کاری که مشتری انجام می دهد تعیین آخرین زمانی است که همگام سازی با سرویس انجام شده است: به پایگاه داده محلی خود نگاه می کند و تاریخ آخرین تغییر ثبت شده توسط آن را تعیین می کند.
  • درخواستی با این تاریخ ارسال می کند.
  • در پاسخ، ما تمام به‌روزرسانی‌هایی را که از آن تاریخ تاکنون رخ داده است، برای او ارسال می‌کنیم.
  • پس از آن، به کانال زنده متصل می شود و تا زمانی که به این به روز رسانی ها نیاز نداشته باشد، بسته نمی شود:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

ما لیستی از تغییرات را برای او ارسال می کنیم: اگر کسی گلی را به ثمر رساند، امتیاز مسابقه را تغییر می دهیم، اگر مصدوم شود، این نیز به صورت بلادرنگ ارسال می شود. بنابراین، مشتریان فوراً داده‌های به‌روز را در فید رویداد مسابقه دریافت می‌کنند. به طور دوره ای، برای اینکه مشتری بفهمد سرور از بین نرفته است، هیچ اتفاقی برای آن نیفتاده است، ما هر 15 ثانیه یک مهر زمانی ارسال می کنیم - تا بداند همه چیز مرتب است و نیازی به اتصال مجدد نیست.

سرویس اتصال زنده چگونه است؟

  • اول از همه، ما یک کانال ایجاد می کنیم که در آن به روز رسانی های بافر دریافت می شود.
  • پس از آن، برای دریافت به روز رسانی، این کانال را مشترک می کنیم.
  • ما هدر صحیح را تنظیم می کنیم تا مشتری بداند همه چیز خوب است.
  • اولین پینگ را ارسال کنید. ما به سادگی زمان اتصال فعلی را ثبت می کنیم.
  • پس از آن از کانال به صورت حلقه ای می خوانیم تا کانال آپدیت بسته شود. کانال به صورت دوره ای یا مهر زمانی فعلی یا تغییراتی را که ما قبلاً برای باز کردن اتصالات می نویسیم دریافت می کند.

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

اولین مشکلی که با آن مواجه شدیم این بود: برای هر اتصالی که با کلاینت باز می شد، یک تایمر ایجاد کردیم که هر 15 ثانیه یک بار علامت می زد - معلوم می شود که اگر 6 هزار اتصال با یک دستگاه (با یک سرور API) باز داشتیم، 6 مورد هزار تایمر ایجاد شد. این امر منجر به عدم تحمل بار مورد نیاز دستگاه شد. مشکل برای ما چندان واضح نبود، اما کمی کمک گرفتیم و آن را برطرف کردیم.

در نتیجه حالا پینگ ما از همان کانالی می آید که آپدیت از آن می آید.

بر این اساس، تنها یک تایمر وجود دارد که هر 15 ثانیه یک بار تیک می زند.

چندین عملکرد کمکی در اینجا وجود دارد - ارسال هدر، پینگ و خود ساختار. یعنی نام جدول (نفر، مسابقه، فصل) و اطلاعات مربوط به این ورودی در اینجا مخابره می شود:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

مکانیزم برای ارسال به روز رسانی

اکنون کمی در مورد اینکه تغییرات از کجا آمده است. ما چندین نفر، سردبیر، داریم که پخش را به صورت واقعی تماشا می کنند. آنها همه رویدادها را ایجاد می کنند: یک نفر اخراج شد، یک نفر مجروح شد، یک نوع تعویض...

با استفاده از CMS، داده ها وارد پایگاه داده می شوند. پس از این، پایگاه داده با استفاده از مکانیزم Listen/Notify سرورهای API را در این مورد مطلع می کند. سرورهای API قبلاً این اطلاعات را به مشتریان ارسال می کنند. بنابراین، ما اساساً فقط چند سرور متصل به پایگاه داده داریم و بار خاصی روی پایگاه داده وجود ندارد، زیرا مشتری به هیچ وجه مستقیماً با پایگاه داده تعامل ندارد:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

PostgreSQL: گوش دادن/اطلاع رسانی

مکانیسم Listen/Notify در Postgres به شما امکان می‌دهد تا به مشترکین رویداد اطلاع دهید که برخی رویدادها تغییر کرده است - مقداری رکورد در پایگاه داده ایجاد شده است. برای انجام این کار، ما یک تریگر و تابع ساده نوشتیم:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

هنگام درج یا تغییر یک رکورد، تابع notify را در کانال data_updates فراخوانی می کنیم و نام جدول و شناسه رکورد تغییر یا درج شده را به آنجا منتقل می کنیم.

برای همه جداول که باید با مشتری همگام شوند، ماشه ای تعریف می کنیم که پس از تغییر / به روز رسانی رکورد، تابع نشان داده شده در اسلاید زیر را فراخوانی می کند.
چگونه API مشترک این تغییرات می شود؟

مکانیزم Fanout ایجاد می شود - پیام هایی را به مشتری ارسال می کند. تمام کانال‌های مشتری را جمع‌آوری می‌کند و به‌روزرسانی‌های دریافتی خود را از طریق این کانال‌ها ارسال می‌کند:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

اینجا کتابخانه استاندارد pq که به دیتابیس وصل میشه و میگه میخواد به کانال گوش کنه (data_updates) چک میکنه که کانکشن باز باشه و همه چی درست باشه. برای صرفه جویی در فضا، بررسی خطا را حذف می کنم (بررسی نکردن خطرناک است).

در مرحله بعد، Ticker را به صورت ناهمزمان تنظیم می کنیم، که هر 15 ثانیه یک پینگ ارسال می کند و شروع به گوش دادن به کانالی که در آن مشترک شده ایم، می کنیم. اگر پینگ دریافت کنیم، این پینگ را منتشر می کنیم. اگر نوعی ورودی دریافت کنیم، آنگاه این ورودی را برای همه مشترکین این Fanout منتشر می کنیم.

فن اوت چگونه کار می کند؟

در روسی این به عنوان "شکاف" ترجمه می شود. ما یک شی داریم که مشترکینی را که می خواهند برخی به روز رسانی ها را دریافت کنند، ثبت می کند. و به محض رسیدن به روز رسانی به این شی، این به روز رسانی را بین تمام مشترکین خود توزیع می کند. به اندازه کافی ساده:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

نحوه پیاده سازی آن در Go:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

ساختاری وجود دارد، با استفاده از Mutexes هماهنگ می شود. دارای یک فیلد است که وضعیت اتصال Fanout به پایگاه داده را ذخیره می کند، یعنی در حال حاضر در حال گوش دادن است و به روز رسانی ها را دریافت می کند، همچنین لیستی از همه کانال های موجود - نقشه که کلید آن کانال و ساختار است به شکل مقادیر (در اصل به هیچ وجه استفاده نمی شود).

دو روش - Connected و Disconnected - به ما این امکان را می دهد که به Fanout بگوییم که ما یک اتصال به پایه داریم، ظاهر شده است و اتصال به پایه قطع شده است. در حالت دوم، باید تمام کلاینت ها را قطع کنید و به آنها بگویید که دیگر نمی توانند به چیزی گوش دهند و دوباره وصل می شوند زیرا ارتباط با آنها بسته شده است.

همچنین یک روش اشتراک وجود دارد که کانال را به "شنوندگان" اضافه می کند:

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

یک روش لغو اشتراک وجود دارد که در صورت قطع ارتباط مشتری، کانال را از شنوندگان حذف می‌کند، و همچنین یک روش انتشار وجود دارد که به شما امکان می‌دهد برای همه مشترکین پیام ارسال کنید.

سوال: - چه چیزی از طریق این کانال منتقل می شود؟

ام‌اس: – مدلی که تغییر کرده یا پینگ ارسال می شود (در اصل فقط یک عدد، عدد صحیح).

ام‌اس: - می توانید هر چیزی را ارسال کنید، هر ساختاری را ارسال کنید، آن را منتشر کنید - فقط به JSON تبدیل می شود و تمام.

ام‌اس: - ما یک اعلان از Postgres دریافت می کنیم - شامل نام جدول و شناسه است. بر اساس نام و شناسه جدول، رکورد مورد نیاز را دریافت می کنیم و سپس این ساختار را برای انتشار ارسال می کنیم.

شالوده

این از منظر زیرساخت چگونه به نظر می رسد؟ ما 7 سرور سخت افزاری داریم: یکی از آنها به طور کامل به پایگاه داده اختصاص داده شده است، شش مورد دیگر ماشین های مجازی را اجرا می کنند. 6 نسخه از API وجود دارد: هر ماشین مجازی با API روی یک سرور سخت افزار جداگانه اجرا می شود - این برای قابلیت اطمینان است.

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

ما دو فرانت اند داریم که Keepalived برای بهبود دسترسی نصب شده است، به طوری که اگر اتفاقی بیفتد، یکی از جلوها بتواند جایگزین دیگری شود. همچنین - دو نسخه از CMS.

وارد کننده آمار هم هست. یک DB Slave وجود دارد که به صورت دوره ای از آن نسخه پشتیبان تهیه می شود. Pigeon Pusher وجود دارد، برنامه‌ای که اعلان‌های فشار را به مشتریان و همچنین زیرساخت‌های Zabbix، Graylog2 و Chef ارسال می‌کند.

در واقع این زیرساخت زائد است، زیرا 100 هزار با سرورهای کمتر قابل ارائه است. اما آهن وجود داشت - ما از آن استفاده کردیم (به ما گفتند که ممکن است - چرا که نه).

جوانب مثبت Go

پس از کار بر روی این برنامه، چنین مزایای آشکار Go ظاهر شد.

  • کتابخانه http جالب. با آن می توانید چیزهای زیادی از جعبه ایجاد کنید.
  • به علاوه، کانال هایی که به ما امکان می دهند مکانیسمی برای ارسال اعلان به مشتریان را به راحتی پیاده سازی کنیم.
  • چیز شگفت انگیز Race Detector به ما این امکان را داد که چندین باگ مهم (زیرساخت مرحله بندی) را حذف کنیم. هر چیزی که روی مرحله‌بندی کار می‌کند، با کلید Race کامپایل می‌شود. و بر این اساس، می توانیم به زیرساخت های صحنه سازی نگاه کنیم تا ببینیم چه مشکلات بالقوه ای داریم.
  • مینیمالیسم و ​​سادگی زبان.

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

ما به دنبال توسعه دهندگان هستیم! اگه کسی خواست لطفا

پرسش

سوال از حضار (از این پس - ب): - به نظر من یک نکته مهم در مورد فن اوت را از قلم انداختید. آیا درک درستی از این موضوع دارم که وقتی شما پاسخی را برای یک کلاینت ارسال می کنید، اگر مشتری نمی خواهد بخواند، آن را مسدود می کنید؟

ام‌اس: - نه، ما مسدود نمی کنیم. اولا، ما همه اینها را پشت nginx داریم، یعنی هیچ مشکلی با کلاینت های کند وجود ندارد. دوم اینکه کلاینت یک کانال با بافر دارد - در واقع ما می توانیم تا صد آپدیت را در آنجا قرار دهیم ... اگر نتوانیم برای کانال بنویسیم، آن را حذف می کند. اگر دیدیم که کانال مسدود شده است، به سادگی کانال را می بندیم، و تمام - کلاینت در صورت بروز مشکل دوباره وصل می شود. بنابراین، در اصل، هیچ مسدودی در اینجا وجود ندارد.

که در: - آیا نمی توان بلافاصله یک رکورد به Listen/Notify ارسال کرد و نه یک جدول شناسه؟

ام‌اس: – Listen/Notify دارای محدودیت 8 هزار بایتی در پیش بارگذاری ارسالی است. در اصل، اگر با حجم کمی از داده ها سروکار داشته باشیم، امکان ارسال وجود دارد، اما به نظر من این روش [روشی که ما انجام می دهیم] به سادگی قابل اعتمادتر است. محدودیت ها در خود Postgres هستند.

که در: - آیا مشتریان در مورد مسابقاتی که به آنها علاقه ای ندارند به روز رسانی دریافت می کنند؟

ام‌اس: - در کل بله. به عنوان یک قاعده، 2-3 مسابقه به طور موازی در جریان است، و حتی پس از آن بسیار نادر است. اگر مشتری چیزی را تماشا می کند، معمولاً در حال تماشای مسابقه ای است که در حال انجام است. سپس، کلاینت یک پایگاه داده محلی دارد که تمام این به روز رسانی ها در آن جمع می شود، و حتی بدون اتصال به اینترنت، مشتری می تواند تمام موارد قبلی را که برای آنها به روز رسانی دارد، مشاهده کند. اساسا، ما پایگاه داده خود را در سرور با پایگاه داده محلی مشتری همگام می کنیم تا او بتواند به صورت آفلاین کار کند.

که در: - چرا ORM خودتان را ساختید؟

الکسی (یکی از توسعه دهندگان Look+): - در آن زمان (یک سال پیش بود) تعداد ORM های کمتری نسبت به الان وجود داشت که تعداد آنها بسیار زیاد است. چیز مورد علاقه من در مورد اکثر ORM های موجود این است که اکثر آنها بر روی رابط های خالی اجرا می شوند. یعنی متدهای موجود در این ORM ها آماده پذیرش هر چیزی هستند: یک ساختار، یک نشانگر ساختار، یک عدد، چیزی کاملاً نامربوط...

ORM ما ساختارهایی را بر اساس مدل داده تولید می کند. خودم. و بنابراین همه روشها بتنی هستند، از انعکاس استفاده نمی کنند و ... سازه ها را می پذیرند و انتظار دارند از آن سازه هایی که می آیند استفاده کنند.

که در: - چند نفر شرکت کردند؟

ام‌اس: – در مرحله اولیه دو نفر شرکت کردند. از جایی در ژوئن شروع کردیم و در مرداد ماه قسمت اصلی (نسخه اول) آماده شد. در سپتامبر منتشر شد.

که در: - در جایی که SSE را توصیف می کنید، از مهلت زمانی استفاده نمی کنید. چرا اینطور است؟

ام‌اس: - صادقانه بگویم، SSE هنوز یک پروتکل html5 است: استاندارد SSE برای برقراری ارتباط با مرورگرها طراحی شده است، تا آنجا که من می دانم. دارای ویژگی‌های اضافی است تا مرورگرها بتوانند مجدداً متصل شوند (و غیره)، اما ما به آن‌ها نیاز نداریم، زیرا مشتریانی داشتیم که می‌توانستند هر منطقی را برای اتصال و دریافت اطلاعات پیاده‌سازی کنند. ما SSE را تولید نکردیم، بلکه چیزی شبیه به SSE ساختیم. این خود پروتکل نیست.
نیازی نبود. تا آنجا که من متوجه شدم، کلاینت‌ها مکانیسم اتصال را تقریباً از ابتدا پیاده‌سازی کردند. آنها واقعاً اهمیتی نمی دادند.

که در: - از چه ابزارهای کمکی اضافی استفاده کردید؟

ام‌اس: - ما به طور فعال از govat و golint برای یکپارچه سازی سبک و همچنین gofmt استفاده کردیم. هیچ چیز دیگری استفاده نشد.

که در: - برای رفع اشکال از چه چیزی استفاده کردید؟

ام‌اس: - اشکال زدایی تا حد زیادی با استفاده از تست ها انجام شد. ما از هیچ دیباگر یا GOP استفاده نکردیم.

که در: – آیا می توانید اسلایدی را که در آن تابع Publish پیاده سازی شده است، برگردانید؟ آیا نام متغیرهای تک حرفی شما را گیج می کند؟

ام‌اس: - نه آنها دامنه دید نسبتاً "باریکی" دارند. آنها در هیچ جای دیگری به جز اینجا استفاده نمی شوند (به جز داخلی های این کلاس)، و بسیار فشرده است - فقط 7 خط طول می کشد.

که در: - به نوعی هنوز شهودی نیست ...

ام‌اس: - نه، نه، این یک رمز واقعی است! این در مورد سبک نیست. این فقط یک کلاس مفید و بسیار کوچک است - فقط 3 فیلد در داخل کلاس ...

میخائیل سالوسین. گردهمایی گلانگ. استفاده از Go در قسمت پشتی برنامه Look+

ام‌اس: - به طور کلی، تمام داده هایی که با مشتریان (مسابقات فصل، بازیکنان) هماهنگ شده اند تغییر نمی کنند. به طور کلی، اگر ورزش دیگری بسازیم که در آن باید مسابقه را تغییر دهیم، به سادگی همه چیز را در نسخه جدید مشتری در نظر می گیریم و نسخه های قدیمی مشتری ممنوع می شوند.

که در: - آیا بسته های مدیریت وابستگی شخص ثالث وجود دارد؟

ام‌اس: - ما از go dep استفاده کردیم.

که در: - در موضوع گزارش چیزی در مورد ویدیو وجود داشت، اما در مورد ویدیو چیزی در گزارش وجود نداشت.

ام‌اس: - نه، من چیزی در مورد ویدیو ندارم. نام آن "Look+" است - این نام برنامه است.

که در: - گفتید برای مشتریان پخش می شود؟

ام‌اس: - ما در جریان پخش ویدیو دخالتی نداشتیم. این به طور کامل توسط مگافون انجام شد. بله، من نگفتم که برنامه مگافون است.

ام‌اس: – برو – برای ارسال تمام داده‌ها – در مورد امتیاز، رویدادهای مسابقه، آمار... Go کل برنامه کاربردی است. مشتری باید از جایی بداند که از کدام لینک برای بازیکن استفاده کند تا کاربر بتواند مسابقه را تماشا کند. ما پیوندهایی به ویدیوها و استریم هایی داریم که آماده شده اند.

چند تبلیغ 🙂

از اینکه با ما ماندید متشکرم آیا مقالات ما را دوست دارید؟ آیا می خواهید مطالب جالب تری ببینید؟ با ثبت سفارش یا معرفی به دوستان از ما حمایت کنید ابر VPS برای توسعه دهندگان از 4.99 دلار, یک آنالوگ منحصر به فرد از سرورهای سطح ورودی که توسط ما برای شما اختراع شده است: تمام حقیقت در مورد VPS (KVM) E5-2697 v3 (6 Cores) 10GB DDR4 480GB SSD 1Gbps از 19 دلار یا چگونه سرور را به اشتراک بگذاریم؟ (در دسترس با RAID1 و RAID10، حداکثر 24 هسته و حداکثر 40 گیگابایت DDR4).

Dell R730xd 2 برابر ارزان تر در مرکز داده 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.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - از 99 دلار! در مورد بخوانید نحوه ساخت شرکت زیرساخت کلاس با استفاده از سرورهای Dell R730xd E5-2650 v4 به ارزش 9000 یورو برای یک پنی؟

منبع: www.habr.com

اضافه کردن نظر