当我通过 socket.io 操作会话时,如何避免 node.js 中的竞争条件?

2024-01-01

我在我的 socket.io 设置中使用这个授权函数:

io.set('authorization', function (data, accept) {
    if (!data.headers.cookie) {
        return accept('Session cookie required.', false);
    }
    data.cookie = require("cookie").parse(data.headers.cookie);
    data.cookie = require("connect").utils.parseSignedCookies(data.cookie,"yeah whatever");
    data.sessionID = data.cookie['connect.sid'];
    sessionStore.get(data.sessionID, function(err, session){
        if (err) {
            return accept('Error in session store.', false);
        } else if (!session) {
            return accept('Session not found.', false);
        }
        // success! we're authenticated with a known session.info.
        return accept(null, true);
    });
});

然后我像这样操作会话变量:

var addAchievementToUser = function(achievement, sessionID) {
    sessionStore.get(sessionID, function(err, session) {
            //stuff happens here such as
            session.info.username = "whatever";
            sessionStore.set(sessionID, session, function () {
            });
        }
    });
};

这工作正常并且可以满足我的要求,但有时它会产生一些邪恶的竞争条件。

那么,我该如何重写它,以便它不会产生竞争条件?我研究了连接中间件,看看是否可以仅操作单个键/值对而不是整个会话对象。但似乎这是不可能的,因为会话需要是一个字符串:

MemoryStore.prototype.set = function(sid, sess, fn){
    var self = this;
    process.nextTick(function(){
        self.sessions[sid] = JSON.stringify(sess);
        fn && fn();
  });
};

有任何想法吗?


好吧,所以我开始使用 redis 中间件,但这并没有真正帮助我解决问题。无论如何,我基本上只通过 socket.io 编辑会话(并且在客户端第一次连接时编辑一次),所以我认为创建一个包含所有活动会话的会话数组是“最好的”,如下所示:

io.set('authorization', function (data, accept) {
    if (!data.headers.cookie) {
        return accept('Session cookie required.', false);
    }
    data.cookie = require("cookie").parse(data.headers.cookie);
    data.cookie = require("connect").utils.parseSignedCookies(data.cookie, "rawr");
    data.sessionID = data.cookie['connect.sid'];
    sessionStore.get(data.sessionID, function(err, session){
        if (err) {
            return accept('Error in session store.', false);
        } else if (!session) {
            return accept('Session not found.', false);
        }
        // success! we're authenticated with a known session.info.
        if (!sessions[data.sessionID]) {
            sessions[data.sessionID] = session;
        }

        return accept(null, true);
    });
});

所以我永远不需要使用 get session 方法来编辑我的会话数据(仅需要 set 方法)。好处是,当同一个客户端连接多个套接字时,这种方式甚至可以工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当我通过 socket.io 操作会话时,如何避免 node.js 中的竞争条件? 的相关文章

随机推荐

  • 将 GraphQL 数据拉入 gatsby-browser.js (或更好的解决方案,请)

    我正在尝试运行一个GraphQL里面查询replaceRouterComponent从内部gatsby browser js 盖茨比浏览器API https www gatsbyjs org docs browser apis 然而 我可以
  • 什么是特殊目的寄存器? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 什么是特殊用途寄存器 特殊用途寄存器的名称是什么 以及每个寄存器的一些描述 顾名思义 特殊用途寄存器是专为任务而设计的寄存器 例如 c
  • Dart 支持参数化单元测试吗?

    我想运行一个 Dart 测试 该测试使用一组输入和预期输出重复进行 类似于 JUnit 的情况 我编写了以下测试来实现类似的行为 但问题是 如果所有测试输出计算不正确 则测试只会失败一次 import package test test d
  • Flask 应用程序使用 opencv 运行速度非常慢

    我有一个烧瓶应用程序 它从相机读取帧并将其传输到网站 相机 py from threading import Thread from copy import deepcopy import queue import cv2 class Ca
  • 为什么我不能用 std::unordered_map 替换 std::map

    这个问题可能有点粗略 因为我家里没有可用的代码 但我知道这件事否则会困扰我整个周末 当我尝试将一些代码更新到 C 11 时 我开始替换一些代码std map with std unordered map 该代码仅使用std map find
  • CGRectContainsRect 不工作

    我用这个方法有问题 我有两个显然彼此包含的矩形 我什至手动绘制了它们的坐标以确保 当我使用 CGRectContainsRect 比较这两个矩形时 它返回 false 对于我的一生 我已经尝试了一切 搜索了网络 但我找不到这个问题的答案 有
  • 使用 jQuery 从 HTML 文本查询脚本元素

    我正在通过以下方式加载页面 ajax 并插入parts将结果放入页面的相应部分 ajax url whole page html success function data status xhr result xhr responseTex
  • Jenkins:将用户定义的变量传递给 Email-Ext 插件

    我使用 Email Ext 插件在声明性管道的构建后阶段的构建结束时发送结果电子邮件 在电子邮件正文中 我尝试插入一些环境变量和一些用户定义的环境变量 内置变量显示正常 但是我定义的任何用户定义变量在电子邮件正文中都是空的 或者在 Atta
  • Visual Studio 2017 中的 React 项目

    我想在 Visual Studio 2017 中与我的 NET 应用程序一起开发 React 应用程序 在同一解决方案中 我正在使用 TypeScript 所以我想要一个可以自定义构建的项目类型 我想对项目进行 webpack 等 所以标准
  • Swing 组件不显示泰文字符

    我有一个简单的摆动应用程序 当我将泰语文本设置为 JLabel 或其他组件时 它们显示像问号的字符而不是泰语文本 有什么办法可以在 Swing 应用程序中支持泰语吗 没有特殊的功能或配置要做 确保您的字体支持泰语字符 当我遇到同样的问题时
  • 如何在 BaseColumns 中使用 _COUNT

    我一直在读BaseColumns https developer android com reference android provider BaseColumns html https developer android com ref
  • 在辅助屏幕上显示 NSWindow

    我想显示一个NSWindow在辅助监视器上全屏显示情节提要中创建的 以下代码导致窗口显示在主屏幕 主屏幕上 Y 原点没问题 但 X 原点是 0 它应该是 1680 下面的代码在优胜美地之前有效 NSScreen screen NSScree
  • RxAndroid 3主线程

    我正在尝试在 Rx3 中找到 subscribeOn 的主线程 Single just getHeavyData subscribeOn Schedulers io observeOn AndroidSchedulers mainThrea
  • 使用网络服务发现在 Java 服务器和 Android 客户端之间进行通信

    我正在构建一个 Java 服务器应用程序 在 PC 上运行 它使用以下命令将自身注册到本地网络JmDNS http jmdns sourceforge net 以及一个 Android 客户端应用程序 该应用程序应该使用以下命令发现 jav
  • 如何使用任务有条件地异步运行代码

    我有一个负责检索资源的类 该类还缓存它们以便快速访问 该类公开了用于检索资源的异步方法 public Task GetResourceAsync string resourceName return Task Factory StartNe
  • 标头部分中的 ransack 搜索表单:未向 search_form_for 提供 Ransack::Search 对象

    首先 我是 RoR 新手 所以答案可能是显而易见的 在这种情况下我深表歉意 我环顾四周 没有发现任何有帮助的东西 我试图在我的应用程序的每个网页的标题上都有一个搜索表单 它将搜索我所有 存储桶 的名称 这是相关代码 在 app views
  • Rails 身份验证令牌和 Ajax

    好吧 根据我在其他网站和堆栈溢出上读到的内容 Rails 会抛出此身份验证令牌错误 因为我的表单未传递令牌 这是一项安全功能 这我明白了 但我确实没有表格 我这里有 ajax 我的 javascript 将 id ed 信息发布到处理函数中
  • 如何在 Diesel 中针对 Postgres 数据库执行带有子查询的删除?

    我在 Postgres 数据库中有以下架构 Table A ID Name Table B ID FOREIGN KEY A ID 我正在尝试在 Diesel 中编写以下查询 DELETE FROM B WHERE B ID in SELE
  • 如何使用 iBatis 将数组写入 Oracle 10g XE 数据库?

    我一直在寻找这个高低的答案 但找不到答案 基本上我有一个对象正在使用 iBatis 写入我的数据库 这适用于字符串 整数等基本类型 但我的对象的属性之一是其他对象的数组 我希望能够保留这一点 然后调用 selectById 语句并检索包括数
  • 当我通过 socket.io 操作会话时,如何避免 node.js 中的竞争条件?

    我在我的 socket io 设置中使用这个授权函数 io set authorization function data accept if data headers cookie return accept Session cookie