Get Mystery Box with random crypto!

نمایش تعداد کاربران آنلاین در AspNet Core برای محاسبه تعداد ک | DotNetZoom

نمایش تعداد کاربران آنلاین در AspNet Core

برای محاسبه تعداد کاربران آنلاین اساسا دو روش وجود داره

روش اول - با استفاده از Cookie

در ASP.NET قدیم داخل کلاس global.asax متد هایی وجود داشت به نام Session_Start و Session_End که به هنگام شروع و پایان "سشن" کاربری، فراخوانی میشدن (با شی Session اشتباه گرفته نشود)
رخداد Session_Start زمانی raise یا اجرا میشد که یک سشن جدید برای یک کاربر ساخته بشه
و رخداد Session_End نیز زمانی raise میشد که یک سشن expire (منقضی) بشه

مکانیزمی که سشن کاربری رو ایجاد ومنقضی میکرد، مراحلش به این صورت بود که:

اولین بار که شخصی سایت رو باز میکرد، خود ASP.NET یک کوکی به نام "ASP.NET_SessionD" با مقدار یک "کلید تصادفی" به همراه Response برای کاربر میفرستاد و اون در مرورگر کاربر ذخیره میشد و از اون طرف همین "کلید تصادفی" در حافظه مموری سرور (به کمک شی Session) به عنوان شناسه یک کاربر (که شاید هنوز نمیدونیم کیه ولی میدونیم یه کاربره) ذخیره میشد (تا اینجای کار یک سشن برای کاربر جدید ساخته شده، در نتیجه رخداد Session_Start فراخوانی میشد)

از درخواست های بعدی، این کوکی به همراه مقدارش (همون کلید تصادفی)، به Server ارسال میشد سپس ASP.NET این کلید رو میخوند و با مقادیر ذخیره شده در شی Session (در حافظه رم) مطابقت میداد و متوجه میشد که این همون کاربری هست که قبلا درخواست زده بود.
تایم منقضی شدن این سشن ها (session expire) به صورت پیشفرض 20 دقیقه بود و مادامی که درخواست یا بازدید از سمت همون کاربر میومد، این مدت زمان تمدید میشد.
در نتیجه مادامی که آخرین درخواست کاربر کمتر از 20 دقیقه قبل بود، سشن برقرار بود و زمانی که این مدت از 20 بیشتر میشد. اون سشن به صورت خودکار expire/منقضی میشد (در این مرحله رخداد Session_End فراخوانی میشد)

بنابراین مادامی که کاربر ما، فاصله بین هر درخواستش کمتر از 20 دقیقه بود، سشن اون کاربر برقرار بود و یک کاربر "آنلاین" به حساب میومد
و زمانی که از آخرین درخواست کاربر، بیش از 20 دقیقه میگذشت، سشن کاربر منقضی شده و یک کاربر "آفلاین" به حساب میومد
در این حالت با کمی کد نویسی میشد تعداد کاربران آنلاین رو محاسبه کرد، به این صورت که یک متغیر global برای تعداد کاربران آنلاین در نظر میگرفتیم و به هنگام Session_Start اون رو ++ (یکی اضافه) و به هنگام Session_End اون رو -- (یکی کم) میکردیم

نکته: این توضیحات حالت پیشفرض هست، در صورت تنظیم sessionState میتونه محل ذخیره سازی سشن و کوکی در سمت سرور و کلاینت متفاوت باشه (مثلا ذخیره شدن سشن ها درون یک دیتابیس SqlServer به جای Memory یا تنظیم شدن کلید تصادفی درون URL به جای کوکی) - توضیحات بیشتر

در ASP.NET Core اما این مکانیزم و این دو متد دیگه وجود نداره. پس مجبوریم مشابه همین مکانیزم رو خودمون کدنویسی و طراحی کنیم. کد نویسیش کار خاصی نداره، همین مراحل ساخت کوکی با یک "کلید تصادفی" (مثلا guid) و ذخیره اون علاوه بر Response، درون یک InMemory Cache داخل یک Middleware به سادگی انجام میشه

در این روش چون فاصله زمانی 20 دقیقه رو برای session expire هست در نتیجه همیشه ما یک تلورانس و اختلاف 20 دقیقه ای ممکنه داشته باشیم. اگر کاربر جاری همین الان مرورگرش رو میبنده یا برق میره چون session اش تا 20 دقیقه از آخرین بازدیدش معتبر هست، همچنان تا 20 دقیقه آینده "آنلاین" محسوب میشه

روش دوم - با استفاده از ارتباطات Realtime مانند SignalR

این روش خیلی مشابه روش قبل هست با این تفاوت که به محض برقرار شدن اتصال کاربر (رخداد OnConnectedAsync کلاس Hub) اون رو به عنوان کاربر آنلاین و به محض قطع شدن ارتباطش (رخداد OnDisconnectedAsync کلاس Hub) اون کاربر رو آفلاین در نظر میگیریم.
بقیه موارد ساخت کلید تصادفی و تنظیم کوکی جهت تشخیص کاربر از بقیه کاربر ها تقریبا مشابه قبل هست

مزیت این روش اینه که دیگه ما تلورانس و اختلاف 20 دقیقه رو نخواهیم داشت و به صورت آنی و در لحظه تعداد کاربران آنلاین بروزرسانی خواهد شد
معایبش هم اینه که به دلیل استفاده از ارتباطات realtime پردازش بیشتری نسبت به روش اول روی سرور میوفته و یا اینکه امکان استفاده از ارتباطات realtime در برنامه شما به هر دلیل از جمله زیرساخت network یا محدودیت های سرور و application شما وجود نداشته باشه

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

در اینجا یک پروژه نمونه آماده کردم که هر دو این روش ها رو پیاده سازی کرده و میتونین با بررسی سورس کدش بیشتر با نحوه عملکرد اون آشنا بشین
https://github.com/dotnetzoom/OnlineUsers-AspNetCore
_________
@DotNetZoom