چگونه در node و nginx در حالت توزیع شده از socket-io استفاده کنیم

فرض میکنم که شما هم دارید از pm2 برای مدیریت پروسس های node اتون استفاده میکنیددر این صورت با یه همچین دستوری برنامه اتون رو روی یه سرور scale میکنیدpm2 start app.js -i 4 --name myappمشکلی که در این حالت برای استفاده از socket وجود داره اینه که ما الان 4 تا پروسس داریم که درخواست های ورودی رو پردازش میکنند. این پروسس ها کلا با هم متفاوت هستند و گویی انگار رو یک سرور جدا هستند. وقتی کلاینت یه درخواستی رو در یه کانال socket.io ارسال میکنه، ممکنه که درخواست به یکی از پروسس هایی که اصلا توش اون کانال وجود نداره ارسال بشه. پس باید یه جوری همیشه هر کلاینت رو به اون پروسسی وصل کنیم که توش اون socket ایجاد شده و اون کانال تو اون پروسس وجود داره.وقتی pm2 پروسس ها رو ایجاد میکنه نمیشه بینشون تمیز قایل شد؛ و مثلا یک درخواست رو به یک پروسس خاص وصل کرد. برای همین هر پروسس رو روی یه پورت bind میکنیم و اونوقت میتونیم از یه load balancer مثل nginx استفاده کنیم و اون رو طوری کانفیگ کنیم که هر کلاینت رو بر اساس ip اش همیشه به اون پروسسی وصل کنه که اولین بار به اون هدایت شده. یه خورده گیج کننده بود نه؟ بزارید با مثال جلو بریم.اول ببینیم چطور میشه چندتا پروسس رو روی پورت های مختلف بالا آورد؟ اونم با pm2. اونم به شکلی که همه پورت ها رو هارد کد نکنیم. وقتی از دستور scale در pm2 استفاده میکنیم، یه مقداری رو در env ست میکنه به نامNODE_APP_INSTANCEکه ایندکس اون پروسس هست. مثلا تو تکه کد اول که 4 تا پروسس داریم، تو اولین پروسس مقدار NODE_APP_INSTANCE صفره و آخری مقدارش 3 خواهد بود. پس میتونیم کد زیر رو داشته باشیمvar express = require('express'); var app = express(); var http = require('http').Server(app) const io = require('socket.io')(http) http.listen( 8000 + parseInt(process.env.NODE_APP_INSTANCE), // <-- specify port "0.0.0.0", function () { console.log('nodejs server started', server.address().port); } );اینجوری وقتی از دستور scale در pm2 استفاده میکنیم، هر پروسس روی یک پورت اجرا میشه. حالا وقت اونه که nginx رو کانفیگ کنیم. از اون جایی که چندتا پروسس داریم، باید از ویژگی load balancer در nginx استفاده کنیم. برای اینکار اول یه upstream در بخش http تعریف میکنیم#in http{} section upstream myapp { ip_hash; # enable sticky session server 127.0.0.1:8000; server 127.0.0.1:8001; }به اون ip_hash دقت کنید. این خط سیاست load balancer رو مشخص میکنه و نشون میده که هر درخواست براساس ip اش همیشه به یکی از پروسس ها route بشه. مقادیر دیگه ای هم میتونه داشته باشه مثل least_conn که ریکوئست جدید رو میفرسته اونجا که کانکشن کمتری بهش هست.در آخر باید یه reverse proxy برای Nginx کانفیگ کنیم که درخواست ها به سمت این پروسس ها بیان که اونم اینجوریه server { listen 80; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://nodes; # enable WebSockets proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } به اون سه خط آخر دقت کنید که خیلی مهمه. به خصوص آخریفقط کافیه که برنامه اتون رو اجرا کنید و nginx رو ریستارت کنید. حالا شما یه سیستم توزیع شده در سطح کورهای cpu دارید. بهتره که تعداد پروسس هایی که برای scale استفاده میکنید برابر با core های cpu اتون باشهوالسلاممنابعhttps://github.com/Unitech/PM2/issues/1510https://socket.io/docs/using-multiple-nodes/https://github.com/socketio/socket.io/tree/master/examples/cluster-nginx