Ruby派生的进程在父服务器端口上侦听



我正在fedora 32上运行一个puma服务器ruby应用程序。在我的服务器中,由于各种原因,我有一些调用会产生新的长时间运行的进程。我遇到了一个问题,我的派生进程正在运行,正在与我的服务器相同的端口上侦听。这导致在部署时重新启动服务器时出现问题,因为进程在所需端口上侦听,服务器无法启动。这怎么可能呢?根据我的理解,当我生成一个进程时,它应该具有与父进程完全不同的内存,并且不共享文件描述符。我的产卵命令只是

my_pid = Process.spawn(my_cmd, %i[out err] => log_file)

Ruby 2.7.0版

编辑:我在部署过程和最初的问题描述中忽略了这一点,服务器重启并不是一个新进程的实际拆除和重启,而是通过向puma服务器发送USR2信号(如这里所述(

一个快速的变通方法/解决方案是调用fork,关闭分叉进程中Puma的套接字,然后调用exec,这将替换正在运行的进程。。。但是,此解决方法仅限于Unix系统。在windows上,您可能可以使用更复杂的方法来实现类似的功能。

遗憾的是,我不知道如何关闭彪马的监听插座。也许这会有所帮助,但更有可能还有其他技巧。

我相信我已经找到了造成这种情况的原因。我使用的彪马重启过程似乎有问题。通过使用USR2信号重新启动服务器,它可以更改套接字打开fd上的标志。

[me@home puma_testing]$ cat /proc/511620/fdinfo/5
pos:    0
flags:  02000002
mnt_id: 10
[me@home puma_testing]$ kill -s USR2 511620
[me@home puma_testing]$ cat /proc/511620/fdinfo/5
pos:    0
flags:  02
mnt_id: 10

这是在fedora 32上使用一个非常简单的puma和sinatra设置进行测试的,如下所示:puma.rb

# frozen_string_literal: true
rackup File.join(File.dirname(File.realpath(__FILE__)), './server.ru')
# https://www.rubydoc.info/gems/puma/Puma/DSL#prune_bundler-instance_method
# This allows us to install new gems with just a phased-restart. Otherwise you
# need to take the master process down each time.
prune_bundler
port 11111
environment 'production'
pidfile File.join(File.dirname(File.realpath(__FILE__)), '../', 'server.pid')
tag 'test'

server.ru一样

require 'sinatra'
class App < Sinatra::Base
get "/" do
"Hello World!"
end
get "/spawn" do
spawn "sleep 500"
end
end
run App

使用打包程序bundle exec puma -C puma.rb运行。请注意,您可以使用/spawnget请求在重新启动之前和之后测试生成新进程,以查看它是否正在使用lsof -itcp:11111侦听套接字

最新更新