ایمان مدائنی
ایمان مدائنی

برنامه نویس ، مشاور ، مدرس

مدرس رسمی و مورد تایید مایکروسافت در ایران .

  • تاریخ عضویت: 1396/07/20
  • آخرین زمان حضور : ‫۱ ماه قبل، پنج شنبه ۱۳ اردیبهشت ۱۳۹۷، ساعت ۰۸:۲۸
  • بازدید از پروفایل : 97

گزارش خطا

علت گزارش برای را بنویسید


Microsoft® Certified Trainer

گزارش

 

مدرس رسمی و مورد تایید مایکروسافت .

 

ایمان مدائنی

پسندیده شده توسط: شیوا محمدی , شهرام برزنی , سهیل علیزاده , خوشدل , صالح نادی , سید محمد صفوی , آرش

Microsoft® Certified Professional

گزارش

MCP
 Microsoft® Certified Professional

ایمان مدائنی

پسندیده شده توسط: شیوا محمدی , علینا اکبری , شهرام برزنی , سهیل علیزاده , محمد لطفی , محمد نادری , الناز فرهمند , عباس حسین زاد , خوشدل , صالح نادی , سید محمد صفوی , مرتضی

الگوریتم چیست ؟

گزارش

 

الگوریتم چیست ؟
کلمه ای است که یک برنامه نویس وقتی نمیخواد توضیح بده چیکار کرده به کار میبره . 😂😂

 

ایمان مدائنی

پسندیده شده توسط: شهرام برزنی , سهیل علیزاده , علی بهمن , وحیدشارعی , شیوا محمدی , فاطمه صفری , محمد لطفی , صالح نادی , سید محمد صفوی

| اشتراک گذاشته شده توسط ایمان مدائنی
نکاتی در مورد بهبود عملکرد وب سایت

گزارش

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

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

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

درخواست ها (requests)

ابتدا از درخواست ها شروع میکنیم ابتدا میخواهیم تصویری وحشتناک به شما نشان بدهم:

تصویر که مشاهده می کنید حاصل یک بار بارگذاری (load) صفحه سایت های فروشگاهی می باشد.

به تعداد درخواست های که  که زیر آن ها با خط قرمز مشخص شده دقت کنید. حدود 300 درخواست تنها برای یک بار بارگذاری صفحه این یک فاجعه است. لازم نیست یک هکر به سایت ما حمله Dos انجام بدهد ما خودمان این کار را میکنیم. فرض کنید 50,000 کاربر تنها یک بار صفحه را بارگذاری کنند نتیجه آن چه می شود؟ خب می رویم سراغ ریاضی 50,000 * 300 = 15,000,000

 

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

Pipline یک درخواست در برنامه های ASP.NET MVC به صورت زیر می باشد:

یک درخواست تا زمانی که به ما پاسخ دهد پروسه طولانی را طی خواهد کرد و باید از چندین لایه عبور کند تا ما نتیجه آن را دریافت کنیم. که این لایه شامل HttpHandler ، HttpModule  ، Filter ها ، Controller ، Action و ... می باشد. حال به این نتیجه رسیدیم که تعداد درخواست ها برای بازدهی بیشتر وب سایت مهم است و باید برروی تعداد آنها مدیریت داشته باشیم. خب برایمان سوال پیش می آید که چگونه تعداد درخواست ها و زمان پاسخ دهی آن ها را کاهش دهیم؟

درخواست های ارسالی به سرور شامل عکس ها ، فایل های استاتیک (javascript , css )، فونت ها و یک صفحه HTML می باشد.

زمانی که فایل های استاتیک خود را bundle نکنیم برای بارگذاری هر فایل یه درخواست به سرور ارسال می شود.این مسئله از طریق   inspect مروگر و مراجعه به تب Network می توانید بررسی کنید.

Bundle  نشده:

    <script src="/Scripts/jquery-1.10.2.min.js"></script>
    <script src="/Scripts/toastr.js"></script>
    <script src="/Scripts/jquery.validate.min.js"></script>
    <script src="/Scripts/jquery.validate.unobtrusive.min.js"></script>
    <script src="/Scripts/humane.min.js"></script>

Bundle  شده:

<script src="/home/scripts?v=_4rktjCqAf-wFF6pwFoRsDrSEpsLv1nVd1mRd2s8vqs1"></script>

اگر دقت کنید تمامی فایل ها درون یک فایل قرار می گیرد و این یعنی کاهش درخواست ارسالی. یک نکته دیگر فایل bundle شده دارای یک پارامتر به نام v می باشد زمانی که فایل های خود را ویرایش کنید مقدار این پارمتر تغییر کرده و کش قبلی را پاک می کند و تغییرات جدید را اعمال می کند.

 

برخی از سایت های بزرگ تمامی فایل های استاتیک خود را درون یک سرور دیگر قرار می دهد و با این کار میزان فشار بروی سرور خود را کاهش پیدا می کند، به عنوان مثال سایت stackoverflow عکس های خود را دورن i.stack.imgur.com قرار می دهد و یا از cdn ها استفاده می کند.

فشرده سازی

با استفاده از bundle دیگر نیاز نیست که فایل های js  و css را فشرده کنیم bundle این کار را برای ما انجام می دهد تنها یک فایل برای فشرده سازی می ماند که آن HTML دریافت شده از سرور می باشد.

برای این کار فریم ورک WebMarkupMin را به شما پیشنهاد می دهم از طریق دستور زیر را آن را نصب کنید:

Install-Package WebMarkupMin.AspNet4.Mvc -Version 2.4.0

پس از این که بسته nuget را نصب کردید به کلاس FilterConfig  مراجعه می کنیم و دو فیلتر مربوط به این فریم ورک که وظیفه فشرده سازی صفحه HTML را دارند را اضافه میکنیم.

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new MinifyHtmlAttribute());
            filters.Add(new MinifyXmlAttribute());
        }
    }

پس از این که برنامه را اجرا کنید و با استفاده از View Sourse کد HTML را بررسی کنید  هیچ فشرده سازی صورت نگرفته است. این فشرده سازی زمانی اعمال خواهد شده که شما پروژه خود را publish کنید  و برروی سرور قرار بدهید.

حال قصد داریم لایه هایی که یک درخواست قرار است طی کند و به ما پاسخ دهد را کاهش دهیم.

یکی از این لایه ها HttpModule  هایی هستند که به صورت پیشفرض برروی ASP.NET  تعریف شده اند.

حال میخواهیم برای اساس نیاز خود HttpModule  هایی که میخواهیم را حذف کنیم. برای حذف یا اضافه کردن یک HttpModule  نیاز است به سراغ Web.Config برویم:

<system.webServer>
   <remove name="WindowsAuthentication" />
      <remove name="FormsAuthentication" />
      <remove name="PassportAuthentication" />
      <remove name="FileAuthorization" />
      <remove name="ErrorMail" />
      <remove name="DefaultAuthentication" />
</system.webServer>

برای مثال بنده از ASP.NET Identity برای سیستم احراز هویت استفاده می کنم و نیازی به ماژول WindowsAuthentication ندارم بنا براین آن را حذف می کنم.

 

ارتباط با بانک اطاعات

برای ارتباط با بانک های اطلاعاتی و انجام تراکنش های مختلف نیاز به یک ORM است. ORM های زیادی تحت .NET وجود دارد دارند که خواسته ما برآورده می کنند. Entity Frameowrk و Dapper دو ORM تحت .NET هستند که محبوبیت زیادی بین برنامه نویسان دارند و بیشتر در پروژه نرم افزاری استفاده می شود.

تمامی ORM ها .NET به صورت توکار از ADO.NET استفاده می کنند. حال میخوام به مقایسه ORM ها بپردازیم، استفاده مستقیم از ADO.NET سریع ترین روش است و عملکرد بالایی دارد ولی از امکاناتی که ORM ها برای شما فراهم می کنند برخوردار نخواهید بود. Dapper سریع تر از EF است ولی امکانات EF را دارا نمی باشد. در کل Dapper یک Micro-ORM حساب می آید نه یک ORM کامل.

این نکته را هم اضافه کنم که نسخه جدید Entity Framework Core که بر مبنای .NET Core می باشد پا به پای Dapper پیش می رود و این احتمال را می دهم که بتواند از Dapper پیشی بگیرد. این نسخه دو برابر سریع تر از نسخه قبلی خود یعنی EF 6.X می باشد.

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

ابتدا یک توصیه ای دارم، قبل از این که از یک فریم مانند EF استفاده کنید نحوه عملکرد و چرخه حیات را به صورت عمیق بررسی کنید.

 

ابتدا به سیستم کش EF می پردازیم:

Ef دارای یک کش سطح اول می باشد که موجودیت واکشی شده از بانک درون context قرار گرفته و زمانی که میخواهیم دوباره آن موجودیت را فراخوانی کنیم اگر در حافظه موجود بدون این که از بانک آن را واکشی کند موجودیت مورد نظر را دریافت کرده و در اختیار ما قرار می دهد. تنها زمانی این اتفاق صورت میگیرد که از چند متد خاص که با داده های local کار می کنند استفاده کنید این متد ها شامل دو متد Find() , Load() می باشند.

منظور از local چیست ؟

هر DbSet تعریف شده در DbContext دارای یک local می باشد و موجودیت های بارگذاری شده دورن آن قرار می گیرند :

            using (var context = new ApplicationDbContext())
            {
                var loadedRoles = context.Roles.Local; //لیستی از نقش هایی که قبلا بارگذاری شده اند
                var loadedRolesCount = context.Roles.Local.Count; // تعداد داده های بارگذاری شده

                foreach (var role in loadedRoles)
                {
                    Console.WriteLine($"Cached Role Count: {loadedRolesCount}");
                    Console.WriteLine(role.DisplayName);
                }
            }

نحوه واکشی موجودیت ها بارگذاری شده:

اگر تنها میخواهید یک موجودیت را با استفاده از کلید اصلی واکشی کنید از متد Find استفاده کنید:

var role = context.Roles.Find(1)

در غیر این صورت میتوانید از متد load استفاده کنید:

context.Roles.Where(x => x.DisplayName.Contains("Admin")).Load();
var role = context.Roles.Local.Single(x => x.DisplayName == "Admin");

متد load از نوع void می باشد و تنها داده را درون local قرار می دهد.  بنابراین برای واکشی موجودیت باید از local استفاده کنیم.

این نکته را هم اضافه کنم که زمانی که DbContext شما dispose  شود موجودیت های بارگذاری شده در local حذف خواهند شد.

 

جلوگیری از ردیابی تغییرات هنگام واکشی داده های نمایشی

Ef به صورت خودکار موجودیت های تغییر داده شده را تشخیص می دهد و برروی آنها یک برچسب میچسباند تا وضعیت آنها مشخص شود (Added,Deleted,Modified, Detached, Unchanged).

حال زمانی که میخواهیم تنها یک لیست را از بانک اطلاعاتی دریافت کرده و تنها آن را نمایش دهیم لازم نیست، Ef خود را به زحمت بیندازد و سیستم Change Tracking خود را استفاده کند، برای رفع این مسئله تیم Ef متدی را برای ما فراهم کرده است که این متد AsNoTracking می باشد نحوه استفاده به شکل زیر می باشد:

              var displayRoles = context.Roles.AsNoTracking().ToList();

Profile کردن کوئری های ارسالی به بانک

همه ما کد هایی نوشته ایم که کار می کنند و با یک بار بارگذاری صفحه اطاعات را از بانک اطلاعاتی واکشی کرده و به ما نمایش می دهد. حال یه سوال از شما دارم آیا کوئری های SQL که توسط Ef  ارسال شده به بانک را مشاهده کرده اید ؟

تجربه : چند وقت پیش در یک پروژه لازم بود 8 جدول (به همراه join های تو در تو) در را یک صفحه بارگذاری کنم. هنگام بارگذاری صفحه این کوئری حدود 20 ثانیه طول کشید، برای بررسی این مشکل ابتدا نرم افزار Entity Framework Profiler  را نصب کردم و با استفاده از آن کوئری تولید شده مشاهده کردم، نتیجه باورنکردنی بود  1619 خط کوئری برای این کار ایجاد شده بود و فشار زیادی به سرورم وارد می کرد سریع این مشکل رو رفع کردم.

نرم افزار EF Profiler تمامی کوئری هایی که توسط وب سایت شما به بانک ارسال می شود را profile کرده  و اگر کوئری ارسال شده غیر استاندارد باشد به شما اطلاع رسانی می کند.

 

استفاده از Asynchronous

حتما این جمله را شنیده اید که می گویند : "استفاده از متد های Async با افزایش سرعت و بهبود عملکرد می شود" این جمله کاملا اشتباه است، استفاده از متد های Async صرفا برای مدیرت منابع می باشد و کاهش فشار برروی سرور و پردازش بیشتر درخواست ها است زیرا پردازش درخواست ها به صورت synchronous محدود می باشد و باعث می شود CPU فشار زیادی متحمل شود. این عمل زمانی به شما کمک می کند که با تعداد درخواست های زیاد رو به رو شوید.

معرفی: برای این که از صحیح بودن کد async خود اطمینان حاصل کنید افزونه AsyncFixer را برروی Visual studio  خود نصب کنید.

توصیه

آخرین تاریخ بروز رسانی ASP.NET MVC  در 2/9/2015 می باشد این نشان دهنده آن است که مایکروسافت قصد توسعه و ارئه آپدیتی برای این فریم ورک ندارد را پس بنابراین خود را برای محاجرت به ASP.NET Core آماده کنید. چرا که ASP.NET Core دارای امکانات و بهبود هایی در سیستم خود می باشد که میتوان وب سایت ما در حجم درخواست های زیاد پایدار نگه دارد. ASP.NET Core دارای یک وب سرور قدرتمند به نام Kestrel می باشد که این وب سرور، 1,188,521 درخواست بر ثانیه را میتواند پشتیبانی کند درحالی که IIS به تنهایی 57,792  درخواست را پشتیبانی می کند.

نتیجه گیری

راه های زیادی برای بهبود عملکرد وجود دارد که ما تنها جزئی از آن را بررسی کردیم و هر مبحث نیاز به یک مقاله جداگانی می باشد. استفاده از ابزار هایی که میزان Performance برنامه ما را اندازه گیری می کند میتوانند برای پیدا کردن مسائلی که باعث کاهش Performance می شود بسیار مفید باشد.

سهیل علیزاده

پسندیده شده توسط: شیوا محمدی , سهیل علیزاده , علی بهمن , شهرام برزنی , ایمان مدائنی , علینا اکبری , مهران قارزی , صالح نادی , سجاد وهمی , سید محمد صفوی , مجید مرادی , محمد

| اشتراک گذاشته شده توسط ایمان مدائنی
تازه های ReSharper Ultimate 2017.1 پشتیبانی از C# 7.0

گزارش

نمایش فایل تصویری

تازه های ReSharper Ultimate 2017.1 پشتیبانی از C# 7.0

فرهمند آریاشکوه

پسندیده شده توسط: شیوا محمدی , ایمان مدائنی , فرهمند آریاشکوه , سهیل علیزاده , سعیدعلیزاده , مهران قارزی , امیر رادمان نژاد , شهرام برزنی , حمیددواچی , سید محمد صفوی
ثبت نام ورود