【问题标题】:How to send response but continue execution in Sinatra?如何在 Sinatra 中发送响应但继续执行?
【发布时间】:2012-09-01 22:22:21
【问题描述】:

我正在制作一个小型 sinatra 应用程序。它会进行几次 Redis 调用,返回数据,然后进行最后一次 Redis 调用以保存“统计信息”。

到目前为止,如果我想提前终止请求(基于输入),我发现可以使用halt

# code code
halt send_blank if is_blocked? SETTINGS, host
# code code

最后我想要这样的东西:

response.body = JSON.generate(outgoing)
# update user
STATISTICS.hset('u:' + userID, 'data', JSON.generate({'ip' => request.ip, 'time' => Time.now.to_f.to_s}))

是否可以发送响应然后进行 5~ ms redis 写入,这样客户端就不必等待了?无论我在哪里或如何放置最终统计 redis 调用,它都会将响应的发送延迟一些毫秒 - 无法欺骗 sinatra。

这可以在 Node 中轻松完成,但只需编写我想要完成的内容,它会在响应发送后触发;据我了解,这里的代码会在返回响应之前阻止执行大约 5 毫秒。

我尝试过使用 after .. do 过滤器,它们可以正常工作,只是除了 response.body 中的数据之外,你不能向它们传递任何东西——这意味着你不能向过滤器传递任何不是即将被输出! 可以通过分配给 post("/") 范围之外的变量来避免这个问题,但是每秒有 100 多个请求,我希望你能看到如何通过各种“全局”交换数据会成为一个大问题。

这看起来很简单,但我找不到比 .. 文档中的过滤器更好的东西了。

我可以创建一个线程或其他东西来使 redis.hset() 进程非阻塞,这样行吗?好像是在硬核它。

谢谢!

【问题讨论】:

    标签: ruby performance sinatra redis rack


    【解决方案1】:

    分叉 redis 写入应该可以工作。

    类似这样的:

    response.body = JSON.generate(outgoing)
    fork do
        # update user
        redis = Redis.new(:host => "your_host_name", :port => your_port_number)
        redis.hset('u:' + userID, 'data', JSON.generate({'ip' => request.ip, 'time' => Time.now.to_f.to_s}))
    end
    

    【讨论】:

    • 在 Heroku 上的 sinatra 中分叉似乎出现问题:***检测到 glibc *** ruby​​:双重释放或损坏(!prev):0x0000000003824b20 *** app[web.1]:== ===== 回溯:========= app[web.1]: /lib/libc.so.6(+0x775b6)[0x7fef9d8385b6] app[web.1]: /lib/libc. so.6(cfree+0x73)[0x7fef9d83ee83]
    • 原生线程在 MRI 上不可用,只有 jRuby 和 Rubinius。我可以推荐鲁比纽斯吗?
    猜你喜欢
    • 2011-04-19
    • 2021-02-20
    • 1970-01-01
    • 2022-10-08
    • 2018-09-19
    • 2018-03-24
    相关资源
    最近更新 更多