我有一个 sinatra 应用程序设置为使用win32-service
gem 作为服务运行。该应用程序启动正常,但一段时间后中断。但是根据服务状态,它仍在运行,但我似乎无法从外部或计算机本身访问它,修复它的唯一方法是停止它,删除它,重新安装服务并启动它.
该应用程序通常是自我部署的(由于构建管道,但仅当我推送更新时),由于厨师而安装和运行,其设置方式是厨师服务器每 5 分钟运行一次它的所有食谱,我认为这会中断我的应用程序不知何故,但我不确定如何。
任何见解将不胜感激。
ps 我意识到我没有发布任何代码,但这只是因为我不确定有什么帮助,告诉我你需要看到什么,我会发布它。
编辑:原来它与厨师无关:
多亏了一些日志记录,我知道我的应用程序在停止响应 5 秒健康 ping(由清漆完成)之前运行了大约 57 分钟,并且厨师运行每 30 分钟发生一次,他们没有共同进入,因此问题是厨师-无关。
让我说清楚,状态仍然是“运行”,所以它没有停止,日志也没有报告会导致守护进程停止运行的错误。
编辑:
这是我的守护进程代码:
class DemoDaemon < Daemon
def service_main
Object.const_get("GG_Web_#{C_NAME}").run! port: PORT, server: 'thin'
while running?
sleep 100
File.open(Logfile, "a"){ |f| f.puts "#{Time.now} - Service is running" }
end
end
def service_stop
File.open(Logfile, "a"){ |f| f.puts "#{Time.now} - Service stopped" }
exit!
end
end
DemoDaemon.mainloop
编辑:
我注意到应用程序似乎在 50 分钟左右停止响应,给予或接受没有日志输出(即异常、服务停止等),应用程序状态响应为running
. 万一你问,它 100% 不是厨师,因为我在盒子上禁用了厨师客户端,应用程序仍然停止响应。
编辑:
此外,它实际上并没有打印Service is running
到Service stopped
日志文件中。
编辑:我已经把它缩小了很多,我知道它不是:
- 厨师
- 源代码加载机制
- 执行主要操作的应用程序部分,即处理请求、从数据库加载数据等(我有两个应用程序有相同的问题,无论导致什么都与两者相同)
我已经回滚到没有这个问题的 gem 的早期版本,它仍然在做。
只剩下一件事(我能想到的),win32-system
我用来创建应用程序主循环的 gem 以及它与 sinatra 的交互。
这是我用来注册应用程序的代码:
binary_path = "#{self.rubypath} #{ROOT.gsub('/','\\')}boot_as_service.rb"
Service.create({
service_name: NAME,
service_type: Service::WIN32_OWN_PROCESS,
description: "#{DESCRIPTION}, running on: #{HOST}:#{PORT}",
start_type: Service::AUTO_START,
error_control: Service::ERROR_NORMAL,
binary_path_name: binary_path,
load_order_group: 'Network',
dependencies: ['W32Time', 'Schedule'],
display_name: NAME
})
主要应用类:
class GG_Web_My_APP < Sinatra::Base
set :show_exceptions, true
set :root, ROOT + NAME
set :server, 'thin'
set :scss, {:style => :compact, :debug_info => false}
Compass.add_project_configuration(File.join(settings.root, 'config', 'compass.rb'))
Tilt.register Tilt::ERBTemplate, 'html.erb'
enable :logging
logging_file = File.open((Object.const_defined?('Logfile') ? Logfile : 'C:\\app.log'), "a")
logging_file.sync = true
use Rack::CommonLogger, logging_file
if ENV['APPLICATION_NAME']
set :environment, :production
set :bind, '0.0.0.0'
end
get '/css/:name.css' do
content_type 'text/css', :charset => 'utf-8'
scss :"/assets/css/#{params[:name]}", Compass.sass_engine_options
end
helpers Sinatra::FormHelpers
helpers Sinatra.const_get("GG_Web_#{C_NAME}")::Helpers
register Sinatra.const_get("GG_Web_#{C_NAME}")::Api
register Sinatra.const_get("GG_Web_#{C_NAME}")::Actions
end
您已经看到了我用来将应用程序作为守护程序运行的代码。
我真的需要帮助来解决这个问题,我完全不知道是什么导致了这个问题以及如何解决它。
编辑:好吧,我现在又确认了一件事,这不是我的代码中导致它的任何东西。它仍然死了,但我在本地机器上运行的版本没有。它是在服务器上运行的东西,导致它变得无响应。
进一步编辑:
原来这根本不是问题,我仍然一无所获
编辑:
好吧,我不能让它撒谎,所以我回去了,我设法让我的应用程序作为一个守护进程运行,而不使用 system32 守护进程类,你猜怎么着,它仍然徘徊到大约 50 分钟后(好吧 45 分钟这个time) ,好吧,因为我在没有服务 gem 的情况下启动它并且它仍然挂起,我想知道它还能是什么。什么可能导致 sinatra 挂起?
此外,如果我ping localhost
得到回复(0% 丢失)但如果我使用 curl 则无法连接。
编辑:
在系统地剥离所有内容直到它只是一个 hello world 应用程序之后,我可以肯定地说这与我的 ruby 代码无关。至此,我是:
- 使用 rackup 将应用程序作为进程启动(尽管我必须手动终止主线程但应用程序仍然运行),而不是将代码包装在守护程序中并运行它。
- 关闭日志记录
- 摆脱了指南针/ sass(认为这可能会挂起,因为更少对其他人显然是这样做的,而且我意识到我没有使用它附带的任何功能,所以保留它没有意义)
- 注释掉所有模块,只有:
get '/' do 'Hello World' end
毕竟它仍然死了,到那时它只是一个纯粹的 sinatra 'hello world' 应用程序;所以要么 sinatra 有问题(我怀疑其他人会遇到这个问题),要么很可能是服务器上的某些东西导致了它。
服务器上可能导致它的原因我不知道。但至少我离解决这个问题更近了一步。