برای پیاده سازی ارتباطات ریل تایم در وب اپلیکیشن های مدرن، متداول ترین گزینه ها وب سوکت و سرویس Socket.io هستند. در این نوشته تفاوت های این ۲ مورد رو بررسی میکنیم.
هنگام ساخت یک برنامه ریل تایم ، لحظه ای وجود داره که باید انتخاب کنید که چگونه تبادل داده ها در زمان واقعی بین کلاینت و سرور را پیاده سازی کنید. وب سوکت و Socket.io احتمالاً دو مورد از محبوب ترین راه حل ها برای پیاده سازی ارتباطات ریل تایم در وب مدرن هستند. اما کدام یک را انتخاب کنیم؟ تفاوت این دو فناوری چیست؟ با هم بررسی میکنیم.
هنگام صحبت در مورد وب سوکت ، ما به یک پروتکل ارتباطی وب اشاره می کنیم که یک کانال ارتباطی دو طرفه را از طریق یک اتصال TCP فراهم می کند. به عبارت دیگر ، امکان تعامل بین سرویس گیرنده (کلاینت) و سرور را با حداقل هزینه و بار ممکن میسازد و به ما امکان می دهد برنامه هایی بسازیم که از مزایای ارتباطات لحظه ای استفاده می کنند.
توسعه دادن یک اپلیکیشن برای چت را در نظر بگیرید: باید در اسرع وقت داده ها را دریافت و ارسال کنید، پس انجام این کار با وب سوکت سناریوی مناسب است! می توانید یک اتصال TCP را باز کرده و داده ها را به اشتراک بگذارید و اتصال را تا زمانی که به آن نیاز دارید باز بگذارید.
وب سوکت اولین بار در سال ۲۰۱۰ در گوگل کروم ۴ ظاهر شد و اولین RFC مربوط (RFC ۶۴۵۵) یک سال بعد ، در سال ۲۰۱۱ منتشر شد. غیر از مثال بالا گزینه های زیر هم موارد خوبی برای استفاده از وب سوکت هستند:
کتابخانه Socket.io یک کتابخانه جاوا اسکریپتی است که بر مبنای وب سوکت و چند تکنولوژی دیگر توسعه داده شده است. Socket.io در مواقعی که وب سوکت مهیا باشد از آن استفاده میکند، و در غیر این صورت از تکنولوژی هایی مثل Flash Socket, AJAX Long Polling, AJAX Multipart Stream بهره میبرد.
مزایای اصلی Socket.io نسبت به وب سوکت عبارتند از:
میبینید که به نظر میرسه Socket.io بهترین گزینه برای ارتباطات ریل تایم باشه... اما برخی مواقع دلایل خوبی هم وجود دارند که استفاده از وب سوکت ساده رو توجیح میکنند..
اول از همه ، هر مرورگر مدرن این روزها از وب سوکت پشتیبانی می کند. Socket.io برای فالبک به تکنولوژی های دیگه از منابع بیشتری استفاده میکند. که بیشتر اوقات هم، به این سطح از پشتیبانی نیازی نداریم; همچنین Socket.io منابع بیشتری از ترافیک شبکه را هم استفاده میکند. در حالی که با وب سوکت ساده، مرورگر احتمالا ۲ درخواست ساده را اجرا میکند:
و به همین سادگی شما آماده شروع ارتباط ریل تایم با سرور خود هستید! اما با Socket.io چطور؟
یک پکیج هم در npm به نام websocket-vs-socket.io وجود دارد که برای مقایسه ترافیک شبکه این دو فناوری ساخته شده است. البته در یک مرورگر هم میتونید تفاوت زیاد در منابع شبکه رو بررسی کنید.
ترافیک شبکه وب سوکت:
ترافیک شبکه Socket.io:
مقایسه ای که تا اینجا انجام دادیم، در واقع مقایسه ای روی کاغذ بوده. اما این تکنولوژی ها در حین نوشتن برنامه های ریل تایم چه تفاوتی ایجاد میکنند؟
با استفاده از وب سوکت ساده ، در برنامه Node.js ای زیر، یک وب سوکت سرور روی پورت ۳۰۰۰ ایجاد میکنیم.. هر بار که کلاینتی متصل شود، ما یک شناسه منحصر به فرد برای Session آن کلاینت در نظر میگیریم. و زمانی که کلاینت پیامی ارسال میکند، با چنین فرمتی ( [<client-id>]: <message> ) پاسخ میدهیم. پس کلاینت میداند که پیام با موفقیت ارسال شده است.
بسیار خب. اما اگر بخواهیم این پیام را برای تمام کلاینت های متصل ارسال کنیم، چی؟ وب سوکت به طور پیش فرض چنین ویژگی رو پشتیبانی نمیکنه اما پیاده سازی اش کار پیچیده ای هم نیست:
همان طور که مشاهده می کنید ، سرور وب سوکت هر کلاینت متصل را ردیابی می کند ، بنابراین می توانیم روی آنها حلقه بزنیم و پیام مورد نظر را برای همه ارسال کنیم. به این ترتیب ما ساده ترین سرور چت ممکن را پیاده سازی کردیم. می توانید کد بالا را با یک کلاینت وب سوکتی در دسکتاپ و یا از طریق یک اکستنشن کروم تست کنید.
بسیار خوب. حالا قصد داریم کد بالا رو با کتابخانه Socket.io پیاده سازی کنیم.
با استفاده از متد broadcast
که به شکل نیتیو پیاده سازی شده، میبینید که کد ها تقریبا نصف وب سوکت ساده هستند و می تونیم پیام ها رو برای تمام کاربران متصل ارسال کنیم.
فقط یک مشکل داریم.. تست کردن این کد روی یک وب سوکت کلاینت معمولی ، امکان پذیر نیست. به این دلیل که (همانطور که قبلاً گفته شد) ، Socket.io از وب سوکت ساده استفاده نمیکند ، در عوض چندین فناوری را برای پشتیبانی از بیشترین تعداد کلاینت ها ترکیب می کند. برای تست این اپلیکیشن به کتابخانه کلاینت Socket.io نیاز داریم; که در مثال زیر از طریق CDN آن را فراهم کرده ایم.
همانطور که مشاهده میکنید ، ممکنه این دو مثال چندان متفاوت به نظر نرسند ... اما Socket.io همواره به کتابخانه کلاینت خود نیاز دارد ، بنابراین نمی توانید از آن برای مقاصدی غیر از توسعه وب استفاده کنید. این در حالی است که وب سوکت ممکن است برای حل مجموعه بزرگی از مشکلات مانند ارتباطات P2P ، انتقال داده سرور به سرور و غیره به صورت بلا درنگ استفاده شود.
همان طور که با هم بررسی کردیم ، مشکلاتی وجود داره که Socket.io سعی در حل آنها دارد.
مقیاس پذیری
فرض کنید که برنامه چت شما موفقیت زیادی کسب کرده است و شما برای هندل کردن همه درخواست ها باید یک سرور دیگر و یک لود بالانسر (Load Balancer) اضافه کنید. حال، اگر در حال اتصال به "سرور ۱" باشید، اما لود بالانسر شما را به "سرور ۲" سوئیچ کند، با خطای زیر مواجه خواهید شد:
Error during WebSocket handshake: Unexpected response code: 400
خوب Socket.io با استفاده از یک کوکی (یا مسیریابی اتصال بر اساس آدرس اصلی آنها) این مشکل را حل می کند ، اما وب سوکت مکانیزم جایگزینی را به شکل پیش فرض ارائه نمی دهد.
عملکرد (پرفرمنس)
همانطور که قبلاً گفتیم ، Socket.io چندین لایه انتزاع را بر روی لایه انتقال وب سوکت فراهم می کند. همچنین استفاده از JSON را برای ارسال داده های باینری از کلاینت به سرور (و بالعکس) اعمال می کند. پس اگر نیاز به پرفرمنس بالا داشته باشید باید کتابخانه را کاستومایز کنید تا از این رفتار خاص جلوگیری کنید; در صورتی که با وب سوکت چنین مشکلی نخواهید داشت.
انتخاب
میبینید که انتخاب بین این ۲ گزینه کمی مشکل است. خوب Socket.io مسلما کمی کار رو راحت تر میکنه، و لازم نیست نگران مواردی مثل لود بالانسینگ، قطع اتصال و برادکستینگ باشیم. سوالی که پیش میاد اینه که: آیا واقعا به تمام این فیچرها نیاز داریم؟ چون فقط کتابخانه کلاینت Socket.io به تنهایی سنگین تر از React, Redux و React-Redux است.
نکته دیگری که باید به خاطر داشته باشید این است که Socket.io سمت سرور پیاده سازی شده و یک کتابخانه سفارشی است که در بیشتر اوقات ، به دلیل انتزاعات اعمال شده توسط خود Socket.io ، از منطق وب سوکت ساده پیروی نمی کند. پس اگر قرار باشه میکرو سرویس های Node.js تون رو ریفکتور کنید و به سمت Java, Go و یا هر زبان دیگه مهاجرت کنید، باید بیشتر منطق Socket.io را بازنویسی کنید تا نتایج مشابهی را با وبسوکت ساده بدست آورید. برادکست کردن پیام ها رو به کلاینت های آنلاین در نظر بگیرید.. درسته که با Socket.io این کار به سادگی استفاده از یک متد هست (اما در وب سوکت ساده باید دستی پیاده سازی شود) .. اما در حین استفاده از وب سوکت ساده، ریفکتور، توسعه و پیاده سازی ویژگی های جدید به مراتب در پروژه های کاستومایز شده، ساده تر است.