中间件中运行的线程正在使用父级实例变量的旧版本

2023-12-06

我用过Heroku 教程实现网络套接字。

它适用于 Thin,但不适用于 Unicorn 和 Puma。

此外还实现了回显消息,它响应客户端的消息。它在每个服务器上都能正常工作,因此 websockets 实现没有问题。

Redis设置也是正确的(它捕获所有消息,并执行里面的代码subscribe block).

现在如何运作:

在服务器启动时,一个空的@clients数组已初始化。然后启动新线程,该线程正在侦听 Redis,旨在从 @clients 数组将该消息发送给相应的用户。

页面加载时,会创建新的 websocket 连接,并将其存储在 @clients 数组中。

如果我们从浏览器收到消息,我们会将其发送回与同一用户连接的所有客户端(该部分在 Thin 和 Puma 上都能正常工作)。

如果我们收到来自 Redis 的消息,我们还会查找 @clients 数组中存储的所有用户连接。 这就是奇怪的事情发生的地方:

  • 如果使用 Thin 运行,它会在 @clients 数组中找到连接并向它们发送消息。

  • 如果使用 Puma/Unicorn 运行,@clients 数组始终为空,即使我们按该顺序尝试(无需重新加载页面或任何内容):

    1. 从浏览器发送消息 ->@clients.length为1,消息已送达
    2. 通过Redis发送消息->@clients.length为0,消息丢失
    3. 从浏览器发送消息 ->@clients.length仍为1,消息已送达

有人可以澄清一下我错过了什么吗?

Puma服务器相关配置:

workers 1
threads_count = 1
threads threads_count, threads_count

相关中间件代码:

require 'faye/websocket'

class NotificationsBackend

  def initialize(app)
    @app     = app
    @clients = []
    Thread.new do
      redis_sub = Redis.new
      redis_sub.subscribe(CHANNEL) do |on|
        on.message do |channel, msg|
          # logging @clients.length from here will always return 0
          # [..] retrieve user
          send_message(user.id, { message: "ECHO: #{event.data}"} )
        end
      end
    end
  end

  def call(env)
    if Faye::WebSocket.websocket?(env)
      ws = Faye::WebSocket.new(env, nil, {ping: KEEPALIVE_TIME })
      ws.on :open do |event|
        # [..] retrieve current user
        if user
          # add ws connection to @clients array
        else
          # close ws
        end
      end

      ws.on :message do |event|
        # [..] retrieve current user
        Redis.current.publish({user_id: user.id, { message: "ECHO: #{event.data}"}} )
      end

      ws.rack_response
    else
      @app.call(env)
    end
  end
  def send_message user_id, message
    # logging @clients.length here will always return correct result
    # cs = all connections which belong to that client
    cs.each { |c| c.send(message.to_json) }
  end
end

Unicorn(显然还有 puma)都启动一个主进程,然后分叉一个或多个工作进程。 fork 复制整个进程(或者至少呈现复制的错觉 - 实际的复制通常仅在写入页面时发生),但仅复制调用的线程fork存在于新进程中。

显然,您的应用程序在分叉之前已进行初始化 - 通常这样做是为了让工作人员可以快速启动并从写入时复制内存节省中受益。因此,您的 redis 检查线程仅在主进程中运行,而@clients正在子进程中被修改。

您可以通过推迟创建 Redis 线程或禁用应用程序预加载来解决此问题,但是您应该意识到,您的设置将阻止您扩展到单个工作进程(使用 puma 和像 jruby 这样的线程友好 JVM 会出现这种情况)减少限制)

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

中间件中运行的线程正在使用父级实例变量的旧版本 的相关文章

  • 多线程难题[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Rails button_to 失败,路径不存在,路径已存在

    编写我的第一个非常简单的 Rails 应用程序 一个简单的管理应用程序 用于跟踪我们一个部门的工作 为人员生成的索引页面上有一个 link to 用于添加新人员 我尝试将其更改为 button to 但它失败了 说路径 people new
  • 如何获取当前正在执行的 NSOperation?

    有没有相当于 NSOperationQueue currentQueue or NSThread currentThread for NSOperation 我有一个相当复杂的域模型 其中繁重的处理发生在调用堆栈的深处 为了及时取消操作 我
  • OpenSSL::SSL::SSLError:SSL_connect 返回=1 errno=0 状态=错误:证书验证失败(无法获取本地颁发者证书)

    有大量关于此的帖子 我看过很多 零个修复似乎有效 main gt PayPal SDK Subscriptions Plan all Request post https api sandbox paypal com v1 oauth2 t
  • Java:多线程和UDP套接字编程

    我是 Java 多线程和套接字编程的新手 我想知道实现 2 个线程的最佳方法是什么 一个用于接收套接字 一个用于发送套接字 如果我想做的事情听起来很荒谬 请告诉我为什么 该代码很大程度上受到 Sun 在线教程的启发 我想使用多播套接字 以便
  • 如何在我的装置中加载 HABTM 与外键关系?

    我有以下两个模型 学校和用户 以及它们之间的 HABTM 关系 并带有连接表 在这个连接表中 引用User表的外键没有被调用user id but student id class School lt ActiveRecord Base h
  • ManualResetEvent WaitOne 未解锁

    我对我正在使用的 ManualResetEvent 有点困惑 它似乎没有解锁 有谁知道为什么会出现这种情况 我得到的场景就是这样的 真实的情况相当复杂 我还没有成功地隔离出一段可以合理发布来重现问题的代码 EDIT我更新了下面的代码示例 这
  • Java 从多次调用中收集 CompletableFuture 的结果

    我必须运行多个外部调用操作 然后以列表的形式获取结果 我决定使用CompletableFutureapi 我准备的代码相当恶心 这个例子 public class Main public static void main String ar
  • 正在更改的线程参数

    当启动多个线程时 id我正在解析的参数有时是错误的 这是我的启动 for int i 0 i lt threadCount i Thread thread new Thread gt WorkerThread i thread Start
  • 高CPU,可能是由于上下文切换?

    我们的一台服务器的应用程序的 CPU 负载非常高 我们查看了各种统计数据 但在寻找问题根源时遇到了问题 当前的理论之一是涉及的线程太多 我们应该尝试减少并发执行线程的数量 只有一个主线程池 有 3000 个线程 以及一个与之一起工作的 Wo
  • FloatToStr / DateToStr 的线程安全性

    我刚刚在文档中发现FloatToStr and DateToStr它们的单参数重载不是线程安全的 原因是它们访问存储在全局变量中的本地化信息 我的问题是 如果我不在运行时更改格式设置 这有任何实际意义吗 据我了解 只要每个人都只读取格式设置
  • 具有 has_many 和 has_one 多态关联的工厂女孩

    我目前正在开发一个项目 我想使用 Factory Girl 创建测试 但我无法使其与多态 has many 关联一起工作 我已经尝试了其他文章中提到的许多不同的可能性 但它仍然不起作用 我的模型看起来像这样 class Restaurant
  • Rails 3.1 和 Coffeescript 出现“找不到变量”错误

    我的应用程序中有引用我的 application js 文件的视图 该文件包含我在整个应用程序中使用的函数 在使用了 3 1 的边缘版本后 我刚刚安装了 Rails 3 1 候选版本 在安装 RC 之前 我没有遇到任何问题 但现在我收到此错
  • VB6 的线程模型是什么?

    我正在将一个古老的 VB6 程序移植到 C Net 我不太了解VB6 我问这个是为了更好地理解它 旧的VB6程序有一个程序执行的主过程 但是它also有许多用于套接字事件或计时器事件的事件处理程序 以及这些经常操纵的共享资源 例如 公共全局
  • 在多线程程序中调用fftw

    我想在线程中使用 fftw3 但代码粘贴在http codepad org lIjdGF5z http codepad org lIjdGF5z导致 双重释放或损坏 错误 如何在线程中正确调用 fftw3 例程 谢谢 您可以通过命令 g t
  • 使用 ExitThread 关闭线程 - C

    我有一个简单的程序 它创建一个线程 循环二十次 然后调用关闭自身并执行必要的清理 当我调试程序时 它到达 ExitThread 方法并暂停 忽略 printf 我已经在它之后设置了向我发出关闭信号的信号 这是正常现象还是我忘记做某事 我是使
  • rails-created_at 当用户订购时,是否应该向表中添加索引?

    您好 我有一张模特照片 default scope order gt photos created at DESC photos version DESC 鉴于我按 CREATED AT 和版本进行排序 我应该在 CREATED AT 上有
  • 如何在完成另一个线程后运行一个线程

    我想运行两个线程r1 and r2 首先启动r1并完成后r1 start r2 仅在完成后r1 这怎么能做到呢 两个线程 一个接着一个 我的答案here https stackoverflow com questions 4592716 m
  • 过度提交 RailsS​​chemaUpToDate 在 --run 时通过,但在提交时失败

    我遇到了一个奇怪的问题overcommit and Rails 5 0 2应用程序与ruby 2 4 0 overcommit run Running pre commit hooks Check if database schema is
  • HEROKU - 无法运行 git push heroku master [重复]

    这个问题在这里已经有答案了 我运行命令 heroku create stack cedar git push heroku master 但它给了我一个错误 gt Counting objects 144 done Delta compre

随机推荐

  • 在忽略字段的列表中查找重复项

    我有一个List的人员 我想找到重复的条目 考虑除id 所以使用equals 方法 因此List contains 因为他们采取id考虑在内 public class Person private String firstname last
  • Wix Burn:如何阻止 Bootstrapper 自行安装

    我相信这个问题可能已经在我之前被问过 但不知何故 我没有找到合适的答案 我可能必须编写自己的托管引导程序 但到目前为止 在我得到的示例中 引导程序也会自行安装并出现在 添加 删除 程序中 而不是我的产品中 问题 我们可以让引导程序只安装我们
  • 插入后,用两列主键更新时间戳触发器

    我有一个简单的详细信息表 如下所示 listid custid status last changed 主键由两者组成listid and custid 现在我正在尝试设置一个触发器来设置last changed每次发生插入或更新时 将列更
  • 如何从 SharedPreferences 中删除某些包含字符串的键?

    我的 Android 共享首选项是 核心价值 jhon usa xxx彼得 英国 luis mex xxxangel 意大利 弗兰 杜邦 xxx查尔斯 比利时 更多带有 xxxname 的行 如何删除键中包含 或开头 以 xxx 的键 值
  • Three.js 正确混合 css3d 和 webgl

    我正在尝试组合 webgl 和 css3d 场景 以便两个场景中的对象正确地混合在一起 我遵循所描述的模式here 并通过修改 Three js 示例 css3d sandbox html 创建了一个简单的示例 在我的版本中 我向 webG
  • 无法访问保存在 Xamarin.iOS 钥匙串值中

    在我的应用程序中 我有两种方法可以帮助我保存和从钥匙串中获取值 public static void StoreKeysInKeychain string key string value DeleteKeyFromKeychain key
  • 覆盖 Maven 插件参数 [重复]

    这个问题在这里已经有答案了 我有一个 Maven 插件 它在 POM 文件中配置为
  • html 链接不起作用(使用基本 href)

    你好 我正在使用这个标签 与此标签相关联 a href main page mainpage html br b main b a 并在浏览器中获取 http awebsite ca main page mainpage html C2 9
  • Eclipse Kepler RCP 主工具栏操作

    Google is我最好的朋友 但我得到的信息太分散而且很不清楚 没有简明的教程来描述我的需求 我想向我的 RCP 应用程序的主工具栏添加操作 但我需要彻底解释执行此操作的每种方法 但由于这是 StackOverflow 我会立即写下这些问
  • Xcode 中的归档项目错误地创建了多应用程序包

    在 Xcode 中归档我的项目是创建一个多应用程序捆绑包 而不是捆绑我的主要发布目标 这正是我想要的 具体来说 当我在 Organizer 中验证我的存档时 它会向我显示以下消息 项目名称 不包含单捆绑应用程序或包含多个产品 请选择另一个存
  • 获取 javascript 'Sys' 是未定义的错误

    在开发机器上 我的网站运行良好 但我收到了 javascript 系统 未定义托管服务器上出现错误 并且我的 AJAX 无法正常工作 我已经制作了一个示例页面和脚本管理器 请查看 http nexapps com default2 aspx
  • 如何访问 Ajax 调用中的变量集

    我正在尝试在通过 Ajax 调用一些 PHP 代码的函数中设置一个变量 可以说 问题在于该变量无法从函数外部访问 var startPageSelected function getSavedStartPage post webroot h
  • onCreate() 在 Activity 停止(但未销毁)时调用。仅在安装后

    我正在开发一个针对 Api 19 的应用程序 这基本上是一个处理草图 我面临的问题是 我的应用程序在安装后第一次运行时 它运行良好 直到用户将其发送到后台 然后 如果他们再次单击应用程序图标 则会调用 onCreate 但 Activity
  • 具有模板化类成员函数的多线程

    因此 我对 STL 提供的 C 11 并发编程功能相当陌生 我正在使用以下代码 include
  • Python networkx 使用draw_networkx_nodes()时改变节点的颜色

    目标是获得类似于 为了定义我使用的图表 import matplotlib pyplot as plt import networkx as nx graph 1 2 3 4 2 5 11 12 13 14 15 3 6 7 66 77 5
  • 如何使用 jQuery 让元素滚动到视图中?

    我有一个 HTML 文档 其中包含网格格式的图像 使用 ul li li ul
  • Swift 4:解析 JSON 时保持相同的顺序

    我需要在应用程序中显示地址列表 同时保持与响应 JSON 相同的顺序 它看起来像这样 addresses e5fdb5ba 7afb 11e8 bead 43321d1a8905 contact Name1 zipCode 06100 14
  • “违反主键约束”SQL 错误

    这似乎是一个很常见的问题 但是 到目前为止我所尝试的一切都没有解决方案 我正在为我的 PK 使用 ID 字段 并且自动增量已打开 这种情况发生在数据已与当前数据合并的 DEV 环境中 任何帮助将不胜感激 我正在使用 SQL Server 我
  • 在不知道最后页码的情况下跨多页进行网页抓取

    运行我的网站代码来抓取分布在多个页面上的不同教程的标题 我发现它工作完美 我尝试编写一些代码 不依赖于 url 的最后页码 而是依赖于状态代码 直到它显示 http status200 我在下面粘贴的代码在这种情况下运行得很好 然而 当我尝
  • 中间件中运行的线程正在使用父级实例变量的旧版本

    我用过Heroku 教程实现网络套接字 它适用于 Thin 但不适用于 Unicorn 和 Puma 此外还实现了回显消息 它响应客户端的消息 它在每个服务器上都能正常工作 因此 websockets 实现没有问题 Redis设置也是正确的