本地启动不同端口Puma实例时遭遇Address already in use错误求助
问题:启动两个Hanami Puma实例时端口9293地址占用报错
我在开发机上启动两个基于Hanami的Puma服务实例(一个API、一个Web应用),API服务能正常启动,但Web应用启动失败,报错:Address already in use - bind(2) for "127.0.0.1" port 9293。
API应用启动日志
jignesh@jignesh-Latitude-7290:~/hanami_projects/my_api_app$ bundle exec hanami server --port=2400 13:59:36 - INFO - Using Guardfile at /......./my_api_app/Guardfile. 13:59:36 - INFO - Puma starting on port 2400 in development environment. 13:59:36 - INFO - Guard is now watching at '/......./my_api_app' [15170] Puma starting in cluster mode... [15170] * Puma version: 6.2.1 (ruby 3.1.2-p20) ("Speaking of Now") [15170] * Min threads: 5 [15170] * Max threads: 5 [15170] * Environment: development [15170] * Master PID: 15170 [15170] * Workers: 2 [15170] * Restarts: (✔) hot (✖) phased [15170] * Preloading application [15170] * Listening on http://0.0.0.0:2400 [15170] Use Ctrl-C to stop [15170] * Starting control server on http://127.0.0.1:9293 [15170] * Starting control server on http://[::1]:9293 [15170] - Worker 0 (PID: 15177) booted in 0.0s, phase: 0 [15170] - Worker 1 (PID: 15179) booted in 0.0s, phase: 0 [15170] ! Terminating timed out worker (worker failed to check in within 60 seconds): 15177 [15170] - Worker 0 (PID: 25100) booted in 0.0s, phase: 0
Web应用启动日志
jignesh@jignesh-Latitude-7290:~/hanami_projects/my_web_app$ bundle exec hanami server 15:32:31 - INFO - Using Guardfile at /......./my_web_app/Guardfile. 15:32:32 - INFO - Puma starting on port 2300 in development environment. 15:32:32 - INFO - Guard is now watching at '/......./my_web_app' [25763] Puma starting in cluster mode... [25763] * Puma version: 6.2.2 (ruby 3.1.2-p20) ("Speaking of Now") [25763] * Min threads: 5 [25763] * Max threads: 5 [25763] * Environment: development [25763] * Master PID: 25763 [25763] * Workers: 2 [25763] * Restarts: (✔) hot (✖) phased [25763] * Preloading application [25763] * Listening on http://127.0.0.1:2300 [25763] Use Ctrl-C to stop /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `initialize': Address already in use - bind(2) for "127.0.0.1" port 9293 (Errno::EADDRINUSE) from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `new' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:335:in `add_tcp_listener' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:329:in `block in add_tcp_listener' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:328:in `each' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:328:in `add_tcp_listener' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:164:in `block in parse' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:147:in `each' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/binder.rb:147:in `parse' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/runner.rb:78:in `start_control' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/cluster.rb:410:in `run' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/launcher.rb:194:in `run' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/lib/puma/cli.rb:75:in `run' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/gems/puma-6.2.2/bin/puma:10:in `<top (required)>' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/puma:25:in `load' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/puma:25:in `<main>' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/ruby_executable_hooks:22:in `eval' from /home/jignesh/.rvm/gems/ruby-3.1.2@my_web_app/bin/ruby_executable_hooks:22:in `<main>'
通用Puma配置文件(两个应用相同)
# frozen_string_literal: true max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5) min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count } threads min_threads_count, max_threads_count port ENV.fetch("HANAMI_PORT", 2300) environment ENV.fetch("HANAMI_ENV", "development") workers ENV.fetch("HANAMI_WEB_CONCURRENCY", 2) on_worker_boot do Hanami.shutdown end preload_app!
已尝试的无效操作
修改Web应用的my_web_app/config/puma.rb,将port配置替换为bind:
#port ENV.fetch("HANAMI_PORT", 2300) bind "tcp://127.0.0.1:2300"
/etc/hosts内容
127.0.0.1 localhost 127.0.1.1 jignesh-Latitude-7290 127.0.0.1 api.some_api.local # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
解决方案
问题出在Puma的控制服务器端口上,不是应用服务端口。从API日志能看到,Puma集群模式下会默认启动控制服务器监听127.0.0.1:9293,两个实例都用这个默认端口就会冲突。
解决方法是给每个应用指定不同的控制服务器端口,有两种方式:
方式1:修改Puma配置文件
在Web应用的config/puma.rb中添加control_url和control_auth_token配置,指定专属端口:
# frozen_string_literal: true max_threads_count = ENV.fetch("HANAMI_MAX_THREADS", 5) min_threads_count = ENV.fetch("HANAMI_MIN_THREADS") { max_threads_count } threads min_threads_count, max_threads_count port ENV.fetch("HANAMI_PORT", 2300) environment ENV.fetch("HANAMI_ENV", "development") workers ENV.fetch("HANAMI_WEB_CONCURRENCY", 2) # 添加控制服务器配置,指定不同端口 control_url "tcp://127.0.0.1:9294" control_auth_token "your_unique_token_here" # 可选,但建议添加,避免未授权访问 on_worker_boot do Hanami.shutdown end preload_app!
API应用也可以修改控制端口,或者保持默认9293,只要两个端口不重复即可。
方式2:启动时通过命令行参数指定
启动Web应用时,加上--control-url参数:
bundle exec hanami server --control-url tcp://127.0.0.1:9294
验证方法
启动Web应用后,检查端口占用情况:
lsof -i :9294
如果能看到Puma进程监听该端口,说明配置生效。
内容的提问来源于stack exchange,提问作者Jignesh Gohel
相关产品推荐
相关产品推荐

