Heroku Worker dyno 上进程之间的 TCP Socket 通信

发布于 2025-01-06 10:31:36 字数 1083 浏览 1 评论 0原文

我想知道如何在 Heroku Worker dyno 上的进程之间进行通信。

我们希望 Resque 工作线程读取队列并将数据发送到在同一测功机上运行的另一个进程。 “其他进程”是一个现成的软件,通常使用 TCP 套接字(端口 xyz)来侦听命令。它被设置为在 Resque 工作程序启动之前作为后台进程运行。

然而,当我们尝试在本地连接到该 TCP 套接字时,却无处可去。

我们用于设置队列的 Rake 任务执行以下操作:

task "resque:setup" do
  # First launch our listener process in the background
  `./some_process_that_listens_on_port_12345 &`

  # Now get our queue worker ready, set up Redis backing store
  port = 12345
  ENV['QUEUE'] = '*'  
  ENV['PORT'] = port.to_s
  Resque.redis = ENV['REDISTOGO_URL']

  # Start working from the queue
  WorkerClass.enqueue
end

这很有效 - 我们的侦听器进程运行,并且 Resque 尝试处理排队的任务。但是,Resque 作业会失败,因为它们无法连接到 localhost:12345(具体来说,Errno::ECONNREFUSED)。

Heroku 可能会阻止同一 dyno 上的 TCP 套接字通信。有办法解决这个问题吗?

我试图将“代码”从这种情况中取出,然后在命令行上执行(在服务器进程声称它已正确绑定到12345之后):

nc localhost 12345 -w 1 </dev/null

但这也无法连接。

我们目前正在研究更改客户端/服务器代码以在双方使用 UNIXSocket 而不是 TCPSocket,但由于它是现成的软件,我们'如果可能的话,我们宁愿避免我们自己的分叉。

I'd like to know how to communicate between processes on a Heroku worker dyno.

We want a Resque worker to read off a queue and send the data to another process running on the same dyno. The "other process" is an off-the-shelf piece of software that usually uses TCP sockets (port xyz) to listen for commands. It is set up to run as a background process before the Resque worker starts.

However, when we try to connect locally to that TCP socket, we get nowhere.

Our Rake task for setting up the queue does this:

task "resque:setup" do
  # First launch our listener process in the background
  `./some_process_that_listens_on_port_12345 &`

  # Now get our queue worker ready, set up Redis backing store
  port = 12345
  ENV['QUEUE'] = '*'  
  ENV['PORT'] = port.to_s
  Resque.redis = ENV['REDISTOGO_URL']

  # Start working from the queue
  WorkerClass.enqueue
end

And that works -- our listener process runs, and Resque tries to process queued tasks. However, the Resque jobs fail because they can't connect to localhost:12345 (specifically, Errno::ECONNREFUSED).

Possibly, Heroku is blocking TCP socket communication on the same dyno. Is there a way around this?

I tried to take the "code" out of the situation and just executed on the command line (after the server process claims that it is properly bound to 12345):

nc localhost 12345 -w 1 </dev/null

But this does not connect either.

We are currently investigating changing the client/server code to use UNIXSocket on both sides as opposed to TCPSocket, but as it's an off-the-shelf piece of software, we'd rather avoid our own fork if possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

老子叫无熙 2025-01-13 10:31:36

使用消息队列 Heroku 插件...,

例如 IronMQ 作为示例

Use message queue Heroku add-ons ...,

like IronMQ for exsample

油饼 2025-01-13 10:31:36

阅读你的问题,你已经回答了你自己的问题,你无法连接到 localhost 12345。

这种设置进程的方式是一种奇怪的方式,因为你在一个 Heroku dyno 中运行两个进程,这消除了 Heroku 的很多好处,即独立进程扩展隔离干净的依赖声明和隔离

我强烈建议将其作为两个单独的进程运行,通过第三方支持服务进行交互。

Reading your question, you've answered your own question, you cannot connect to localhost 12345.

This way of setting up your processes is a strange one as your running two processes within one Heroku dyno which removes a lot of the benefits of Heroku, i.e independant process scaling, isolation and clean depenedency declaration and isolation.

I would strongly recommend running this as two seperate processes that interact via a third party backing service.

情徒 2025-01-13 10:31:36

我认为,Heroku 只允许您在每个 dyno 的给定端口 ($PORT) 中监听。

我在这里看到两个解决方案:

  • 使用 Redis 作为通信中间件,因此工作人员将再次在 Redis 上写入,侦听器进程将查询 Redis 是否有新作业,而不是在端口中侦听。

  • 获取另一个heroku dyno(或更好,一个完全不同的应用程序)并启动监听进程(在$PORT上)并与两个应用程序进行通信

Heroku only lets you listen in a given port ($PORT) per dyno, I think.

I see two solutions here:

  • Use Redis as a communication middleware, so the worker would write on Redis again and the listener process, instead of listening in a port would be querying redis for new jobs.

  • Get another heroku dyno (or better, a complete different application) and launch there the listening process (on $PORT) and communicate both applications

深海夜未眠 2025-01-13 10:31:36

@makdad,“第 3 方软件”是用 Ruby 编写的吗?如果是这样,我会使用一个猴子补丁来运行它,该补丁会伪造 TCPSocket 或它用来访问 TCP 套接字的任何类。将猴子补丁放在自己的文件中,运行第 3 方软件的 Ruby 进程需要该文件。猴子补丁甚至可以直接从队列中读取数据,并使 TCPSocket 表现得就像已收到该数据一样。

是的,这不是很优雅,而且我确信可能有更好的方法来做到这一点,但是当你试图完成一项工作时(而不是花几天时间做研究),有时你只需要硬着头皮做一些丑陋但有效的东西。无论您选择什么解决方案,请务必为以后参与该项目的人员记录下来。

@makdad, is the "3rd party software" written in Ruby? If so, I would run it with a monkey patch which fakes out TCPSocket or whatever class it is using to access the TCP socket. Put the monkey patch in a file of its own, which will only be required by the Ruby process which is running the 3rd party software. The monkey patch could even read data directly from the queue, and make TCPSocket behave as if that data had been received.

Yes, it's not very elegant, and I'm sure there may be a better way to do it, but when are you trying to get a job done (not spend days doing research), sometimes you just have to bite the bullet and do something which is ugly, but works. Whatever solution you choose, make sure to document it for those who work on the project later.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文