在服务器进程中创建工作线程是一个坏主意吗?

我的服务器进程基本上是一个响应REST请求的API。

其中一些请求用于启动长时间运行的任务。

做这样的事情是个坏主意吗?

get "/crawl_the_web" do Thread.new do Crawler.new # this will take many many days to complete end end get "/status" do "going well" # this can be run while there are active Crawler threads end 

服务器每天不会处理超过1000个请求。

不是最好的主意….

使用后台作业运行器来运行作业。

POST /crawl_the_web应该只是将作业添加到作业队列中。 后台作业运行器将定期检查队列中的新作业并按顺序执行它们。

例如,您可以使用delayed_job ,设置一个单独的进程来轮询和运行作业。 如果您使用的是Heroku,则可以使用delayed_jobfunction在单独的后台worker / dyno中运行作业。

如果你这样做,你打算如何停止/重启你的sinatra应用程序? 当您最终部署应用程序时,您的应用程序可能会由unicorn,passenger / mod_rails等提供服务.Unicorn将管理其子进程的生命周期,并且它不会知道您可能已启动的这些长时间运行的线程那是一个问题。

如上所述,使用delayed_job,resque或任何其他基于队列的系统来运行后台作业。 您可以获得作业的持久性,获得水平可伸缩性(只需在更多节点上启动更多工作者)等。

在请求处理期间启动线程是个坏主意。

除此之外,你无法控制你的工作线程(以受控方式启动/停止它们),如果你在请求处理中启动一个线程,你很快就会遇到麻烦。 考虑一下发生了什么 – 请求结束并且流程准备好为下一个请求提供服务,而您的工作线程仍然运行并访问流程全局资源,如数据库连接,打开文件,相同的类变量和全局变量等等。 迟早,您的工作线程(或从中使用的任何库)将以某种方式影响主线程并破坏其他请求,并且几乎不可能进行调试。

你最好不要使用单独的工作进程。 例如delayed_job是一个非常小的依赖,易于使用。