Как мне убедиться в этом?идентификатор одинаков на сервере и клиенте после перезагрузки страницы?

#node.js #redis #socket.io

#node.js #редис #socket.io

Вопрос:

Я пишу Доказательство Концепции (уже не менее 2 месяцев), в которой используется кластер узлов (рабочие), Redis и socket.io.

Разъем.В данном случае io не используется для чата — только для обратной связи. Ajax-это не вариант.

Я использую pub/sub для redis, и эта часть работает (я думаю). По крайней мере, значения, возвращенные из pubClient.get («ключ»), верны.

Когда я делаю запрос с внешнего интерфейса и никак не перемещаюсь или не перезагружаю страницу, все работает идеально — я могу сделать 10 запросов и получить 10 ответов.

И наоборот, когда я перемещаюсь, то же самое неверно — и мне нужно предоставлять результаты независимо от того, сколько кто-то перемещается по интерфейсу.

Похоже, что после перезагрузки происходит отключение. Как в инструментах разработки консолей, так и в узле js идентификаторы сокетов одинаковы. Я действительно ломаю голову над этим вопросом!

Есть там какая-нибудь помощь?

Итак, для некоторых в основном сокет.код ввода-вывода:

клиент:

 socket = io('https://'   location.hostname   ':4444/', {  transports: ['websocket', 'polling'],  secure: true,  });   socket.on('download', function(data){// after reload, this never hits  console.log('DOWNLOAD '  data.download);  });   var pkgs = ['y14Vfk617n6j', 'My77gWYmBLxT', 'IYd6dL9UoXkx'];  if(pkgs.length gt; 0){  for(var i = 0; i lt; pkgs.length; i  ){  socket.emit('get-request', pkgs[i]);  }  }    

сервер:

 var cluster = require('cluster');  var express = require('express');  var numCPUs = require('os').cpus().length;  const { setupMaster, setupWorker } = require("@socket.io/sticky");  const { createAdapter, setupPrimary } = require("@socket.io/cluster-adapter");  var app = express();  const https = require('https');  const { Server } = require("socket.io");  const Redis = require("ioredis");  const sock_nodes = [  {port: 6379, host: '192.168.0.41'},  {port: 6380, host: '192.168.0.34'},  {port: 6381, host: '192.168.0.35'},  {port: 6379, host: '192.168.0.34'},  {port: 6380, host: '192.168.0.35'},  {port: 6381, host: '192.168.0.41'}  ];    const port = 4444;  const httpServer = https.createServer(options, app);  const io = new Server(httpServer, {maxHttpBufferSize: 10240000});   const pubClient = new Redis.Cluster(sock_nodes, {  redisOptions: {  password: 'my secret!'  }  });    const subClient = pubClient.duplicate(); // I am not actually using this - should I be?  if (cluster.isMaster) {  for (var i = 0; i lt; numCPUs; i  ) {  // Create a worker  cluster.fork();  }  cluster.on("exit", (worker) =gt; {  console.log(`Worker PID ${worker.process.pid} died`);  var w = cluster.fork();  console.log('WORKER %d died (%s). restarting...', worker.process.pid, worker.state);  w.on('message', function(msg){  console.log("Message Received : " , msg);  });  });    } else {   app.use((req, res, next) =gt; {  var reqip = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress;  //~ console.log(reqip, md5(reqip));   var sess = parseCookies(req, 'session_state');  if(!sess){  res.cookie('session_state', md5(reqip));  }  next();  });   app.get('/', (req, res) =gt; {  getSession(req, res, function(sess){  getPub('currSockets', sess, function(err, socket){  res.render("pages/shared/index", {'ns': sess, 'socket': socket});  });  });  });  });   app.get('/start', function(req, res){  getSession(req, res, function(sess){  getPub('currSockets', sess, function(err, socket){  res.render("pages/shared/start", {'ns': sess, 'socket': socket});  });  });   });   io.on('connection', function (socket) {  var currUser = parseCookies(socket.request, 'session_state');  socket.join(currUser);    getPub('currSockets', currUser, function(err, currSockets){  if (currSockets) {  currSockets = JSON.parse(currSockets);   if (currSockets[currUser]) {  if (currSockets[currUser].stream) {   currSockets[currUser].sock = socket.id;  setCurrSockets(currSockets, currUser, null, function(cSocks){    });  }  }  }  });    socket.on('get-request', function(data){ // can be one or many requests  // there is a similar, currently irrelevant, socket.on('new-request') that is left out here   if(data){  getPub('currSockets', currUser, function(err, currSockets){  currSockets = JSON.parse(currSockets);  if(currSockets){  if(currUser){  if(currSockets[currUser]){  if(currSockets[currUser].stream){  var str = Object.keys(currSockets[currUser].stream);  for(var i = 0; i lt; str.length; i  ){  if(str[i] !== 'sock'){  if(!currSockets[currUser].stream[str[i]]){  delete currSockets[currUser].stream[str[i]];  setCurrSockets(currSockets, currUser, null, function(cSocks){   checkCurrSockets(currUser, data, socket);   });  }  }  }  }  }  }  }  });  }  });  });   httpServer.listen(port, () =gt; {  logs(__line__, `Worker ${process.pid} listening on ${port}`);  }); }  function existsPub(key, cb){  return pubClient.exists(key, cb);  }   function setPub(key, val, cb){  if(val === JSON.stringify({})){  return pubClient.get(key, cb);  }  return pubClient.set(key, val, cb);  }   function getPub(key, currUser, cb){  existsPub(key, function(err, reply){  if(reply === 1){  return pubClient.get(key, cb);// always getting an old socket.id  }  });  }  // Here is the piece that doesn't work after reloading the page   function ioEmit (currSock, target, payload) {  io.to(currSock).emit(target, payload); // doesn't work after page reload  } // end piece where after reload does not work    getPub('currSockets', currUser, function(err, currSockets){  if( currSockets){  currSockets = JSON.parse(currSockets);  ioEmit(currUser, 'download', {'download': currSockets[currUser].stream[data]);  }  });   function parseCookies (req, name) {  var list = {}, rc;  rc amp;amp; rc.split(';').forEach(function( cookie ) {  var parts = cookie.split('=');  list[parts.shift().trim()] = decodeURI(parts.join('='));  });  return list[name];  }  function getSession(req, res, callback) {  var sess = false;  if(req.headers) {// handle req  var reqip = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress;  if(req.headers.cookie){  sess = req.headers.cookie.split('=')[1].split(';')[0];  } else {  res.cookie('session_state', md5(reqip));  }  return callback(sess);   } else if(req.request) {// handle socket  //~ console.log('req.request.headers.cookie', req.request.headers.cookie.split('=')[1]);  if(req.request.headers.cookie){  sess = req.request.headers.cookie.split('=')[1].split(';')[0];  //~ req.emit('join', sess);  //~ callback({[sess]: {'sock': req.id}});  callback(req.id);  }  } else {  return callback(null);  } }  function setCurrSockets(currSockets, currUser, data, cb){  if(Object.keys(currSockets[currUser].stream).length gt; 0){  if(data){  if(ready(currSockets, currUser, data)){  delete currSockets[currUser].stream[data];// it appears that setCurrSockets is getting called too soon  }  }  setPub('currSockets', JSON.stringify(currSockets), function(err){   });  if(typeof cb === 'function'){  setTimeout(() =gt; {  getPub('currSockets', currUser, function(err, cSocks){  cb(cSocks);// updated callback to return cSocks  }, 2000);  });  }  } else {  currSockets[currUser].stream = {};  setPub('currSockets', JSON.stringify(currSockets), function(err){  if(err){    } else {  if(typeof cb === 'function'){  cb(currSockets);// updated callback to return cSocks  }  }  });  } }  

Комментарии:

1. Ты не можешь. Когда будет загружена новая страница, клиент запросит НОВЫЙ сокет. подключение ввода — вывода и тому правильно будет присвоено новое socket.id . Если вы хотите отслеживать одного и того же клиента с одной страницы на другую, для этого вам следует использовать файл cookie или экспресс-сеанс, а затем вы можете присоединить новый socket.id к этому сеансу, когда клиент подключится на новой странице.

2. Спасибо. Я думал, что использую печенье? Похоже, я упустил какой-то необходимый код. Обновление сейчас — добавлена сессия getSession

3. @jfriend00 — добавил getSession в код выше — я опустил его по какой-то глупой причине!

4. Что это такое sess = req.headers.cookie.split('=')[1].split(';')[0]; ? Похоже, вы пытаетесь получить доступ к файлу cookie по позиции в разделенном массиве, даже не глядя на его имя. Это нехорошо. К вашему сведению, существует готовое промежуточное программное обеспечение для анализа файлов cookie, которое полностью протестировано для доступа к определенному файлу cookie без его самостоятельного анализа вручную.

5. ну, это POC, и я не знаю об этом промежуточном программном обеспечении, и есть только один файл cookie, но я ценю ваш вклад @jfriend00

Ответ №1:

понял это. Проблема была здесь:

 for(var i = 0; i lt; str.length; i  ){  if(str[i] !== 'sock'){    gt;gt;gt;gt; if(!currSockets[currUser].stream[str[i]]){ // never true  // delete currSockets[currUser].stream[str[i]];  setCurrSockets(currSockets, currUser, null, function(cSocks){     checkCurrSockets(currUser, data, socket);   });  }  }  }  

поэтому я прокомментировал цикл for и сохранил часть setCurrSockets, и это работает. Просто подумал, что я хотел бы поделиться, на случай, если кто-то еще попытается использовать redis, кластер узлов и сокет.ио вместе. Как сказал @jfreind00, вы должны использовать систему аутентификации со случайной строкой для хранения файлов cookie.

Комментарии:

1. Еще раз спасибо @jfriend00 — ваши комментарии привели меня к решению!