Meteor.setTimeout 和 Meteor.methods 之间的并发

2024-05-18

在我的 Meteor 应用程序中实现回合制多人游戏服务器,客户端通过发布/订阅接收游戏状态,并且可以调用 Meteor 方法sendTurn将回合数据发送到服务器(他们无法直接更新游戏状态集合)。

var endRound = function(gameRound) {
    // check if gameRound has already ended / 
    // if round results have already been determined
    //     --> yes: 
                  do nothing
    //     --> no:
    //            determine round results
    //            update collection
    //            create next gameRound
};

Meteor.methods({
    sendTurn: function(turnParams) {
        // find gameRound data 
        // validate turnParams against gameRound
        // store turn (update "gameRound" collection object) 
        // have all clients sent in turns for this round?
        //      yes --> call "endRound"
        //      no  --> wait for other clients to send turns
    }
});

为了实现时间限制,我想等待一定的时间段(让客户有时间打电话sendTurn),然后确定回合结果 - 但前提是回合结果尚未确定sendTurn.

我应该如何在服务器上实现这个时间限制?

我天真的实现方法是调用Meteor.setTimeout(endRound, <roundTimeLimit>).

问题:

  • 那么并发呢?我假设我应该同步更新集合(没有回调)sendTurn and endRound(?),但这足以消除竞争条件吗? (阅读已接受答案的第四条评论这个问题 https://stackoverflow.com/questions/18007014/meteor-could-a-race-condition-happen-with-meteor-collections-on-server-side关于同步数据库操作也会产生,我对此表示怀疑)

  • 在这方面,“根据请求”在流星文档 http://docs.meteor.com/#/full/structuringyourapp在我的上下文中(函数endRound由客户端方法调用和/或在服务器中调用setTimeout)?

    在 Meteor 中,您的服务器代码在每个请求的单个线程中运行,而不是以 Node 典型的异步回调风格运行。

  • 在多服务器/集群环境中,(如何)这将工作?


很好的问题,而且它比看起来更棘手。首先,我想指出,我已经在以下存储库中实现了针对这个确切问题的解决方案:

https://github.com/ldworkin/meteor-prisoners-dilemma https://github.com/ldworkin/meteor-prisoners-dilemma https://github.com/HarvardEconCS/turkserver-meteor https://github.com/HarvardEconCS/turkserver-meteor

总结一下,问题基本上有以下几个特点:

  • 每个客户端在每一轮中发送一些操作(您将其称为sendTurn)
  • 当所有客户端都发送了他们的操作后,运行endRound
  • 每轮都有一个计时器,如果到期,则自动运行endRound anyway
  • endRound无论客户端做什么,每轮都必须执行一次

现在,考虑我们必须处理的 Meteor 的属性:

  • 每个客户端一次只能有一个连接到服务器的未完成的方法(除非this.unblock()在方法内部调用)。以下方法等待第一个方法。
  • 服务器上的所有超时和数据库操作都可以让步给其他纤程

这意味着每当方法调用经历屈服操作时,Node 或数据库中的值都可能发生变化。这可能会导致以下潜在的竞争条件(这些只是我已修复的条件,但可能还有其他条件):

  • 例如,在 2 人游戏中,两个客户端调用sendTurn完全在同一时间。两者都调用屈服操作来存储转弯数据。两种方法都会检查是否有 2 个玩家轮流发送,找到肯定的结果,然后endRound运行两次。
  • 一名玩家打电话sendTurn就在回合结束时。在这种情况下,endRound被超时和玩家的方法调用,导致再次运行两次。
  • 对上述问题的错误修复可能会导致饥饿endRound永远不会被叫到。

您可以通过多种方式解决此问题,可以在 Node 中同步,也可以在数据库中同步。

  • 由于一次只有一个 Fiber 实际上可以更改 Node 中的值,因此如果您不调用屈服操作,则可以保证避免可能的竞争条件。因此,您可以将回合状态等内容缓存在内存中,而不是数据库中。然而,这要求缓存正确完成并且不会延续到集群环境。
  • 移动endRound方法调用本身之外的代码,使用其他东西来触发它。这是我采取的方法,确保只有计时器或最终玩家触发回合结束,而不是两者都触发(请参阅here https://github.com/ldworkin/meteor-prisoners-dilemma/blob/master/server/server.js#L121对于使用的实现observeChanges).
  • 在集群环境中,您必须仅使用数据库进行同步,可能需要使用条件更新操作和原子运算符。像下面这样:

    var currentVal;
    
    while(true) {
      currentVal = Foo.findOne(id).val; // yields
    
      if( Foo.update({_id: id, val: currentVal}, {$inc: {val: 1}}) > 0 ) {
        // Operation went as expected
        // (your code here, e.g. endRound)
        break;
      }
      else {
        // Race condition detected, try again
      }
    } 
    

上述方法比较原始,在高负载下可能会导致数据库性能不佳;它也不处理计时器,但我相信通过一些思考,您可以弄清楚如何扩展它以更好地工作。

您可能还想看这个定时器代码 https://github.com/HarvardEconCS/turkserver-meteor/blob/master/lib/timers_server.js一些其他的想法。一旦我有时间,我将把它扩展到你所描述的完整设置。

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

Meteor.setTimeout 和 Meteor.methods 之间的并发 的相关文章

  • 如何在nodejs中使用crypto.randomBytes使用async/await?

    const crypto require crypto async function getKey byteSize let key await crypto randomBytes byteSize return key async fu
  • SQLite同时读写

    我读过很多主题 但无法找到问题的答案 是否可以同时读写 我有后台线程更新一些数据 UI 需要存储在数据库中的一小部分数据 所以在UI线程中执行SELECT操作 但当更新正在进行时它会阻塞 结果 UI 冻结了几秒钟 有人在写入时成功从数据库读
  • 在c99中使用__thread

    我想使用 thread 存储类定义一些特定于线程的变量 但三个问题让我犹豫不决 它真的是c99的标准吗 或者更重要的是 编译器支持有多好 变量会在每个线程中初始化吗 非多线程程序是否将它们视为普通的旧全局变量 回答您的具体问题 不 它不是
  • NodeJS 无法加载 css 文件

    所以我正在尝试制作一个 NodeJS 服务器 并且我尝试保留尽可能少的附加组件 但是 我遇到了一个问题 我似乎无法加载任何内容CSS我调用的文件HTML文件 该调用似乎确实由服务器处理 但它不会显示在浏览器中 My 网络服务器 js fil
  • 未处理的拒绝:发送后无法设置标头

    我正在 Dialogflow 中创建一个聊天机器人 当我尝试将数据添加到数据库时 它抛出了 未处理的拒绝 错误 这是我的index js文件 use strict const functions require firebase funct
  • 为什么 Mongohint 可以使查询运行速度提高 10 倍?

    如果我使用explain 从shell运行mongo查询 获取所使用的索引的名称 然后再次运行相同的查询 但使用hint 指定要使用的相同索引 解释计划中的 millis 字段是显着下降 例如 没有提供任何提示 gt gt db event
  • 返回旧的(m,文件名);错误 [ERR_REQUIRE_ESM]:ES 模块的 require()

    我正在尝试与 unsplash api 进行集成 但我得到了 当我尝试通过 ts node 运行脚本时 如下所示 ts node unsplash ts 有错误 C Users USER AppData Roaming npm node m
  • Node.js 请求随机开始挂起,直到服务器重新启动后才会清除

    我在我们的网络应用程序上遇到了一个非常奇怪且看似随机的问题 我似乎无法成功调试 它可以正常运行 10 分钟到 6 小时 然后突然无法向服务器发出或从服务器发出远程请求 它们只是挂起 这包括常规的 http 和 Web 套接字请求 奇怪的是
  • M:N线程模型真的利用了CPU核心吗?

    有几种线程模型可用于在应用程序中调度线程 1 1 内核级线程 用户创建的每个线程都映射到内核中的调度线程 N 1 用户级线程 用户在单个应用程序中创建的所有线程实际上都映射到单个调度的内核线程 M N 混合螺纹 用户在应用程序中创建的 M
  • Scala 中用于阻止调用的 Future

    The Akka文档说 you may be tempted to just wrap the blocking call inside a Future and work with that instead but this strate
  • Node.js - 异步 JSON 查询

    如果这是一个愚蠢的问题 我深表歉意 但我对 Javascript 很陌生 而 Node js 确实让我很头疼 因为它是异步的 我的目标是从 API 查询 JSON 对象并能够使用它 我试图寻找关于我应该做什么的问题和答案 但它们对我来说都没
  • Schedulers.io() 不返回主线程

    我正在使用 RxParse 来解析查询的异步负载 但是当我使用 subscribeOn Schedulers io 订阅我的可观察值时 我的 onCompleted 方法永远不会在主线程上调用 相反 我的 onCompleted 方法是在工
  • Node.js es6 使用index.js 导出/导入

    我有以下文件夹结构 src index js lib test js dist examples example js src lib test js export default class Test src index js impor
  • Node.js 进行 rsa 加密的正确方法?

    我正在尝试创建一个 WS 来发出肥皂请求 在消息正文中有一个包含加密文本的字段 我有公钥来加密文本 但我获得的唯一结果是文本无法识别 我使用节点的加密模块来发出请求 并且文本已加密 但我不知道为什么没有正确加密 PS我用 openssl p
  • 类验证器 (Node.js) 在自定义验证中获取另一个属性值

    目前 我有一个非常简单的类验证器文件 其中包含 Nest js 中的 ValidationPipe 如下所示 import IsDateString IsEmail IsOptional IsString Length Max from c
  • Sequelize 4.3.2 n:m(多对多)关联:未处理的拒绝 SequelizeEagerLoadingError

    我有 3 个模型 用户 项目 UserProject module exports function sequelize DataTypes var User sequelize define User title DataTypes ST
  • 无法在 AWS Lambda 自定义授权方中验证 Twilio 请求

    我使用 NodeJS 构建了一个自定义授权者 lambda 函数 并将其配置为授权 AWS 中的另一个 lambda 函数 这个其他函数是从 HTTP 端点触发的 并且具有我在 Twilio Messaging Service 中配置为 w
  • 在 AWS Lambda 中共享代码

    在 AWS Lambda 函数之间共享代码的首选方式是什么 我有这样的结构 functions a 节点模块 index js 包 json b 节点模块 index js 包 json c 节点模块 index js 包 json 这让每
  • MongoDB Java 驱动程序:MongoCore 驱动程序与 MongoDB 驱动程序与 MongoDB 异步驱动程序

    MongoDB Java 驱动程序有三种不同的驱动程序选项 核心驱动 MongoDB 驱动程序 MongoDB 异步驱动程序 The 驱动程序描述页面 https docs mongodb org ecosystem drivers jav
  • 对于单主机 Node.js 生产应用程序来说,什么是好的会话存储? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话

随机推荐

  • 为不同的字体系列指定不同的字体大小

    有没有办法为不同的字体系列指定不同的字体大小 我想要使 用的字体 出于产品品牌目的 是一种有点罕见的字体 FlashDLig 并非所有 PC 和浏览器都支持 我的一台带有 IE 9 的 Windows 7 PC 不显示它 现在 对于我使用
  • Java:java.util.ConcurrentModificationException

    我正在制作 2D 目前正在研究用子弹射击 子弹是一个单独的类 所有项目符号都存储在称为项目符号的数组列表中 当它超出屏幕一侧 Exception in thread main java util ConcurrentModification
  • Python 2:SMTPServerDisconnected:连接意外关闭

    我在用 Python 发送电子邮件时遇到一个小问题 me my email address you recipient s email address me email protected cdn cgi l email protectio
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 使用连接池后如何处理过多的并发连接?

    Scenario 假设您有一个拥有大量流量的网站或应用程序 即使使用数据库连接池 性能也会受到真正的打击 站点 应用程序甚至可能崩溃 因为并发连接太多 Question 人们有什么选择来处理这个问题 我的想法 我在想有这个问题的人可以创建多
  • Python beautifulsoup 仅限 1 级文本

    我看过其他 beautifulsoup 得到相同级别类型的问题 看来我的有点不同 这是网站 我正试图拿到右边那张桌子 请注意表的第一行如何展开为该数据的详细细分 我不想要那个数据 我只想要最顶层的数据 您还可以看到其他行也可以展开 但在本例
  • 为什么 Delphi 中的 ADO Next 记录处理速度变慢?

    我有一个多年前开发的 Delphi 4 程序 它使用Opus 直接访问 http sourceforge net projects directaccess 按顺序搜索 Microsoft Access 数据库并检索所需的记录 Delphi
  • 屏幕开/关检测

    在这里 我试图确定屏幕是否打开 但按下电源锁定 解锁按钮时它似乎不起作用 应用程序运行没有错误 但 if else 中的代码似乎没有效果 Edited现在代码可以工作了 谢谢Olgun 但媒体播放器播放不会停止 并且每次在屏幕上 离屏时都会
  • 在 UIImage 顶部绘制透明圆圈 - iPhone SDK

    我在尝试找出如何在 UIImageView 中的 UIImage 顶部绘制透明圆圈时遇到了很多麻烦 谷歌给了我线索 但我仍然找不到有效的例子 有没有人知道的例子可以证明这一点 最简单的方法就是创建一个半透明的方形 UIView 然后将其图层
  • 如果没有 /// 标签,TypeScript 的“将 JavaScript 输出合并到文件中”选项无法推断出正确的脚本顺序

    我正在开发一个使用 将 JavaScript 输出合并到文件中 选项的 TypeScript 解决方案 我经常引用另一个文件中定义的项目 例如 In MyBaseClass ts export class MyBaseClass In My
  • 从Python中的字典列表中查找特定值

    我的字典列表中有以下数据 data I versicolor 0 Sepal Length 7 9 I setosa 0 I virginica 1 I versicolor 0 I setosa 1 I virginica 0 Sepal
  • 使用 JQuery 禁用和启用所有超链接

    我有以下禁用所有超链接的内容 但在事件发生后我想再次启用它们 我该如何执行此操作 a click function return false 我认为这不仅仅是将其设置为 true 那么简单 谢谢大家 不要以这种方式绑定 点击 处理程序 而是
  • Python,将函数的输出重定向到文件中

    我正在尝试将函数的输出存储到Python中的文件中 我想做的是这样的 def test print This is a Test file open Log a file write test file close 但是当我这样做时 我收到
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • 如何在列表框项目之间画一条线

    我希望能够用水平线分隔列表框中的每个项目 这只是我用于绘制项目的一些代码 private void symptomsList DrawItem object sender System Windows Forms DrawItemEvent
  • 在现有 iOS 应用程序中集成 React-native(0.40.0) 后找不到 Yoga/Yoga.h 头文件

    在我的 Swift iOS 应用程序中集成 React Native 后 我无法构建 yoga Yoga h file cannot be found 我已经浏览了文档 查看了react native github页面 检查了类似问题的SO
  • C++ 子字符串返回错误结果

    我有这个字符串 std string date 20121020 我正在做 std cout lt lt Date lt lt date lt lt n std cout lt lt Year lt lt date substr 0 4 l
  • SDK >=26 仍需要 mipmap/ic_launcher.png?

    在 Android 中 有两种指定启动器图标 可以说是应用程序图标 的方法 老 方式 在 mipmap 文件夹中指定不同的 png 文件 通常命名为 ic launcher png 但可以通过以下方式设置名称android icon mip
  • Meteor.setTimeout 和 Meteor.methods 之间的并发

    在我的 Meteor 应用程序中实现回合制多人游戏服务器 客户端通过发布 订阅接收游戏状态 并且可以调用 Meteor 方法sendTurn将回合数据发送到服务器 他们无法直接更新游戏状态集合 var endRound function g