اینم یه تجربه پراکنده دیگه!

همیش مشکلات و محدودیت‌ها آدم رو به خلاقیت وا میداره اما یه سری محدودیت‌ها هم که به دلیل کار نابلدی یا حماقت افراد شرایط عجیب غریب کاری درست میشه هم اعصاب خورد کنه!(یکی از همکاران بنده که خواننده این وبلاگ هم هست و از قضا قبلا کارهای مدیریتی در شرکت‌های دیگه انجام داده پیشنهاد دادن که الزاما تصمیمات بخاطر کارنابلدی و این چیزا نمیفته بلکه شرایط کاری انقدر عجیب غریبه که فعلا همینه که هست) القصه بگم که به علت نبود sysadmin در شرکت(بخش ما)، قرار شد که من به عنوان توسعه دهنده سرویس، یکی از سرویس‌ها رو deploy کنم. این تصمیم که این کار به یه برنامه نویسی سپرده بشه اشتباهه اما بالاخره شرایط اینجوریه! من بعد از لاگین کردن به سرور سعی کردم که در اولین قدم کل اون سرور رو بروزرسانی کنم اما از قضا دیدم که اینترنت نداره! در خواست دادم که دسترسی اینترنت ایجاد کنن اما اون هم به دلایل عجیب اتفاق نیافتاده. پس مجبور شدم که یه repository محلی از تمام پکیج‌ها درست کنم و اون رو به سرور منتقل کنم. مراح این کار از این قراره. سرور یه centos 6.0 هست

  1. نصب یه centos 6.0 به منظور ایجاد repository
  2. نصب نرم افزاری به نام yumdownloader که در بسته yum-utils قرار داره. این ابزار برای دانلود کردن پکیج‌ها به همراه وابستگی‌هاشون هست.
  3. دانلود کردن پکیج‌هایی که میخوایم به همراه وابستگی‌هاشون به کمک
    yumdownloader --resolve <package>
  4. نصب ابزار createrepo برای ساختن repository
  5. ساختن repository با دستور
    createrepo --database /mnt/local_repo
  6. انتقال این repository به سرور و انجام عملیات بروزرسانی یا نصب

همین!

منبع : این و این

اینم یه تجربه پراکنده دیگه!

خب اگه شما بخوای یه کد رو برای یه پلتفرم غیر x86 یا x86_64 که همون ۳۲ بیتی و ۶۴ بیتی خودمون هستند کامپایل کنید، نیاز دارید که مفهومی به نام ToolChain مخصوص به اون پلتفورم رو داشته باشید. مثلا اگه بخواید کدی قاعدتا به زبان C یا C++ بنویسید که رو raspberry pi کار کنه باید اون رو کامپایلر مخصوص اون پلتفروم کامپایل کنیم و با کتابخانه‌های مربوطه که باز هم با همون کامپایلر کامپایل شدن لینک و در نهایت اجرا کنیم. برای این کار شما نیاز به چند تا چیز دارید

  • کامپایلر
  • لینکر
  • کتابخانه استاندارد سی

حالا ابزارهایی بوجود اومده که به شما کمک میکنه که این ابزارها رو برای تقریبا هر پلتفرمی درست کنید. اسم اون ابزار crosstool-ng هست. من هم کمک دارم ازش استفاده میکنم که اس دی کی یک دستگاه embedded رو ببرم به لینوکس. اگه موفق شدم بیشتر در موردش براتون مینویسم

همین!

 

اینم یه تجربه پراکنده دیگه!

در ادامه سری «ویر کارایی» میخواستم یه پست کوتاه در مورد یه مساله بسیار مهم در حوزه کارایی بنویسم. مساله‌ای که معروف به C10K هست.

اگه بخوام بصورت خیلی تو دل برو و خودمونی این مساله رو تعریف کنم باید بگم که: نوشتن برنامه‌هایی با قابلیت کار کردن با ۱۰ هزار کانکشن همزمان بصورت موازی هست. یعنی در آن واحد ما به ۱۰ هزار مشتری پاسخ بدیم. این مساله در اواخر ده ۱۹۹۰ توسط آقای کگل معرفی شده و ادعا شده که الان سخت‌افزارهای قوی برای ارائه سوریس وجود داره و گلوگاه معمولا بخش نرم‌افزار هست. برای این مساله راه‌حل‌های مختلفی پیشنهاد شده که میتونید پست اصلی آقای کگل رو بخونید. معمولا این راه حل‌ها ترکیبی از تنظیم سیستم عامل به علاوه بهبود نرم افزار هست.

هنوز روی این مساله کار میشه و از نقطه نظر‌های مختلف بررسی میشه. و حتی اخیرا حد ۱۰ هزار کاربر رو به ۱۰ میلیون کاربر همزمان افزایش دادن و مساله جدیدی برای بررسی ارائه کردن.

اما من هنوز در ایران هیچ راه حلی رو به چشم ندیدم که این تعداد کانکشن همزمان داشته باشه. من توی سیستم بانکی کار کردم و با سیستم‌های مخابراتی آشنا هستم. معمولا تعداد کاربران همزمان سیستم‌های بانکی زیر ۴۰۰ کاربر همزمان و سیستم مخابراتی اگه اشتباه نکنم زیر ۱۰۰۰ کاربر هست. یعنی هنوز راه زیادی تا مساله C10K داره. البته باید بگم که چون سیستم‌های مخابراتی و بانکی مبتنی بر تراکنش هست، معمولا پیچیده تر از یک وب سرور هست که بخواد ۱۰ هزار کلاینت همزمان داشته باشه. هنوز هم شخصا سعادت آشنایی با سایتی رو نداشتم که این مقدار بازدید کننده داشته باشه.

امیدوارم در آینده نزدیک یه بخورد نزدیک با این مساله داشته باشم. و این یعنی که سطح سرویس‌ها اینترنتی در کشور ما به شدت افزایش یافته.

همین!

اینم یه تجربه پراکنده دیگه!

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

اختراع مجدد چرخ

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

  • طراحی پروتکل: یعنی اینکه تعیین کنیم این سیستم جدید اولا چه پیغام‌هایی رو میفرسته(فرمت پیغام‌ها)
  • طراحی روند کار: اینکه وضعیت‌های کلاینت و سرور چیاست و مثلا رجیستر شدن کلاینت جدید، حذف شدنش، قطع شدنش و … چطور مشخص میشه.

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

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

در طراحی کلاینت هم چالش‌ها، مزایا و معایبی رو داریم

  • چالش‌ها
    • تامین ثبات و مقاومت نسبت به خطا
  • مزایا
    • همه چیز در کنترل ماست و ما از زیر رو بم سیستم آگاهی داریم
  • معایب
    • نیاز به زمان و انرژی زیاد

استفاده از xmpp

خب استفاده از این راهبرد یکی از کم ریسک‌ترین راه‌هاست چرا که همین الان گوگل و اپل از این سیستم استفاده میکنند. دوم اینکه نرم‌افزارهای آماده‌ای هم برای این کار وجود داره. کارهایی که بایستی در این حالت انجام بشه اینه:

  • آشنایی با پروتکل xmpp
  • آشنایی با سرور و کلاینت‌های موجود برای xmpp
  • ارزیابی لیست ویژگی‌هایی که ما داریم با قابلیت‌های این سیستم‌ها

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

  • چالش‌ها:
    • نیاز به آموزش زیاد
    • نیاز به دستکاری و تغییر کدهای نوشته شده توسط دیگران: خیلی از ما در خوندن و دستکاری کد دیگران با مشکلات عدیده‌ای مواجه هستیم که خب معمولا باعث میشه از این کار بترسیم.
  • مزایا:
    • وجود نرم‌افزارها متن باز
    • ریسک پایین کار
  • معایب:
    • پروتکل xmpp مبتنی بر xml هست که عملیات استخراج اطلاعات رو از نظر محاسباتی پر هزینه میکنه.
    • پروتکل‌ xmpp دارای extension های غیر استاندارد زیادی هست که همه سرورها و همه کلاینت‌ها از اون پشتیبانی نمی‌کنن.

استفاده از IRC

خب ریسک این راهبرد یکم بیشتر از قبله، اما توسط ارتش آمریکا برای اطلاع رسانی در حین عملیات استفاده شده که نشون میده این ایده هم قابلیت اجرای عملیاتی داره. کارهایی که در اینجا هم باید انجام بشه شبیه xmpp هست:

 

  • آشنایی با پروتکل IRC که خیلی ساده و راحت هست
  • آشنایی با سرور و کلاینت‌های موجود برای IRC
  • ارزیابی لیست ویژگی‌هایی که ما داریم با قابلیت‌های این سیستم‌ها

بعد از انجام این بررسی‌ها باید برویم سراغ انتخاب سرور و کلاینت. چالش‌ها و مزایا و معایب این روش از این قراره:

  • چالش‌ها:
    • نیاز به دستکاری و تغییر کدهای نوشته شده توسط دیگران
  • مزایا:
    • نیاز به آموزش قابل قبول
    • وجود نرم‌افزارها متن باز
    • ریسک پایین کار
    • پروتکل IRC مبتنی بر متن بوده و بسیار ساده است.
  • معایب:
    • پروتکل IRC مبتنی بر متن بوده و به سختی یا با هزینه بیشتر میشه اطلاعات بایتنری رو از طریق اون انتقال داد.

 جمع بندی

اگه من بخوام جمع بندی کنم من حداکثر سعیم رو میکنم که سراغ «اختراع مجدد چرخ» نرم. جاهایی که با کمبود قدرت محاسباتی کلاینت مواجهم یا قرار نیست با این اطلاع رسانی آنی «شاخ غول» بشکنم، استفاده از IRC‌ به علت ساده تر بودنش قابل قبول تره اما اگه موقعیت عجیب غریب باشه احتمالا میرم سراغ xmpp.

امیدوارم این مطلب به دردتونه خورده باشه! همین!

اینم یه تجربه پراکنده دیگه!

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

خب اول از همه ویندوز، iOS و آندروید هر سه در سطح سیستم عامل این عملیات رو پشتیبانی میکنن. بدین صورت که اگه شما بخوای اطلاعاتی رو به موبایل push کنی بایستی تقریبا مراحل زیر رو طی کنی:

  1. نرم افزاری رو که میخوای براش اطلاعات بفرستی به فراهم کننده این سرویس معرفی کنی و ازش یه شبه اکانت بگیری
  2. توی نرم افزار موبایل کارها مرتبط با پیدا سازی این سرویس رو انجام بدی
  3. از سمت سرور به سرورهای فراهم کننده وصل بشی و بدونی چه کلاینت هایی داری و به اون کلاینت‌ها اطلاعات رو push کنی.

خب دونستن این اطلاعات خیلی به من برای رسیدن به هدفم کمک نمی‌کرد. پس رفتم سراغ یه جای دیگه. ما راه‌حل‌هایی داریم به اسم Backend as a Service که اونها اداعا میکنن که سرور push notification دارن. بعد از بررسی و خوندن مستندات و یکم دست و پنجه نرم کردن با این راه‌حل‌ها فهمیدم که کارکردن و سرو کله زدن سرورهای فراهم کننده خیلی راحت و تو دل برو نیست و برای پیاده سازی باید کلی نحوه ارسال این اطلاعات مدیریت بشه. سرور push notification توی این راه‌حل‌ها سعی میکردن این مدیریت رو انجام بدن. این اطلاعات هم خوب بود اما خیلی به درد نمی‌خورد.

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

خب همین سرنخ کافی بود تا من برم و بیشتر بررسی کنم ببینم تکنولوژی‌های چت چی هستن و چطور میشه ازشون استفاده کرد. پروتکل‌های متفاوتی رو توی اینجا پیدا کردم. اما اکثرا یا ویژگی‌هایی داشتن که من نمیخواستم( مثلا ارسال صدا، تصویر و …) یا اینکه خیلی معمول نبودن یا مقبولیت عام نداشتن. پس از بررسی اولیه به نظرم استفاده از یکی از این دوتا پروتکل میتونه برامون push notification به همراه داشته باشه

فعلا همین!

پ.ن. این پست یه قسمت دیگه هم خواهد داشت که از منظر پیاده‌سازی به این موضوع نگاه میکنه.

 

 

اینم یه تجربه پراکنده دیگه!

یه مدته که اینجا حرف برنامه نویسی زده نشده و میترسم «عنودان بد گهر» فکر کنن که من برنامه نویسی رو فراموش کردم. پس این دفعه سعی میکنم یه موضوع عمیق که به کارایی سرور سوکت مربوط میشه رو بنویسم.

توی یکی از پروژه‌هایی که من انجام میدادم مهمترین نیازمندی این بود که با کارایی بالا از سوکت UDP اطلاعات رو دریافت و پردازش کنم. کل پردازش یه سری عملیات به نسبت ساده ریاضی بود و کل ماجرا توی کارایی اون سوکت UDP خلاصه میشد. خب اولین راهی که پیش من بود این بود که اولا تحقیق و دوما آزمایش کنم. توی تحقیقاتم با توجه به مطلبی که توی این کتاب در مورد Nginx خونده بودم و نتیجه جستجو‌هام به این نتیجه رسیدم که بایستی بصورت Async سوکت‌ها رو مدیریت کنم. توی تحقیقاتم با توجه به معلوم نبودم پلتفرم توسعه با استفاده از Node.JS و C# نمونه‌هایی پیاده کردم و تست کردم و الحق که به نتایج قابل قبولی تو مایه‌های ۱۰۰۰ یا ۱۰۰۰۰ پکت در ثانیه رسیدم. توی C و C++ راه حل‌های متفاوتی برای این کار ارائه شده بود که بهترینش به نظرم کاری بود که توی boost::asio انجام شده بود که کلا روند async رو برای سوکت‌ها فایلها و تایمرها پیاده‌سازی کرده بود. نتیجه استفاده از این کتابخانه بسیار خوب بود و تا الان فراتر از حد نیاز کارایی رو فراهم کرده. کد هم به شدت ساده است. کل سرور در حد ۲۰ خط پیاده‌سازی شده.

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

  • kqueue: مکانیزمی هست که توی خانواده BSD فراهم شده
  • epoll: مکانیزمی هست که توی کرنل لینوکس فراهم شده
  • event port: در سولاریس مورد استفاده قرار گرفته
  • Overlapped I/O: به پیاده سازی اختصاصی این ماجرا در ویندوز گفته میشه.
  • Input/Output Completion Port: روندی است که ویندوز و سولاریس اون رو پیاده‌سازی کردن.

البته باید بگم که برخی از این مکانیزم‌ها به سیستم عامل‌های دیگه هم پورت شدن و توی اونها هم قابل دسترسی هستند.

خب اگه ما بخوایم کدی بنویسیم که از یکی از این مکانیزم‌ها به درستی استفاده کنه و قابل پورت به سیستم عامل‌های دیگه باشه میرسیم به همون boos::asio که دقیقا همین کار رو کرده وسیستم عامل‌های مختلف رو هم پیشتیبانی میکنه. پیاده‌سازی این مکانیزم‌ها معمولا یه سختی هم داره و اون اینه که شما بایستی با system call های کرنل اون سیستم عامل آشنایی خوبی داشته باشی که در اکثر برنامه‌نویسا نیست که این باعث سخت شدن نگهداری کد میشه.

در مجموع استفاده کردن این کتابخانه‌ها که هم بخوبی تست شدن، هم ثبات کافی دارن باعث سادگی کار کاهش زمان مورد نیاز برای توسعه میشه. اما یادتون باشه که این سادگی هزینه داره و اگه یه روزی برسه این برنامه جواب کارتون رو نده شما باید آستیناتون رو بالا بزنید و کد رو یه شخم حسابی بزنید!

همین!