• Mina 升 1.0 后的差异 at 2017年1月18日

    你就不能发给完整的部署过程,拿出一段来看有点片面,看源码应该没问题:shared_dirs, link_shared_paths,

  • midori 百日记 at 2016年12月24日

    #13楼 @dsh0416 上述列举的场景并不单纯是 CPU 密集操作,还有第三方网络请求库,这些请求库底层使用的是类似 Net::HTTP 这类 block IO;而此框架将其异步化的思路是实用 await/defer,而此方式本身利用的是 EM 的线程池;现实场景中,你的 web 程序中每个 action 或多或少都会调用几个外部请求(像是数据库操作、缓存操作等等),这时的整体效率未必会比 thin 这类多线程方案高。当然,你可以使用类似 Midori::Postgres(也即 EventMachine::Protocols::Postgres3)的方案来缓解这种情况;但是否稳定易用高效,感觉就不好说啦。综上,个人总觉得 README 的 benchmark 不太公平。

    PS1: 文中的 Midori::Route 应该是 Midori::API,前者根本好像没有 get 这类方法吧;
    PS2: puma 并没有使用 EM 来实现异步 IO,而是自己实现了一套 Reactor 模式的异步 IO;
    PS3: 建议实现 cluster 后,benchmark 测试增加个多进程多线程模式下 puma 做对比,我比较好奇是否真的能有很大性能提升;当然测试中的 action 能够涉及网络请求和一些简单操作,而不是单纯的 helloworld;

  • Bootstrap 下拉菜单不显示 at 2016年12月24日

    data_toggle -> data-toggle

  • midori 百日记 at 2016年12月18日

    这么说吧:

    1. receive_data 是在 EM.run 这个主线程中执行的
    2. chain.call(fiber.resume) -> receive_new_request(data) -> get 路由的代码块也是在这个主线程中执行的
    3. 由此造成的问题是,当出现下述情况时,整个应用服务器只能响应一个请求:
      • 请求体较大的请求,耗费 parse 时间
      • 响应体较大的请求,耗时 send_data 时间
      • get 中执行耗时操作时。上述 sleep 1 只是举例,现实场景是,开发者使用的第三方网络请求库,随机性的 CPU 密集型操作等等。

    比如,下述 benchmark 代码(比 sinatra on thin 差了一倍):

    require 'em-midori'
    
    class Route < Midori::API
      get '/' do
        '0' * 1024 * 1024 * [1, 2, 4, 6, 8, 16, 32, 64].sample
      end
    end
    Midori::Runner.new(Route).start
    

    假定能用 Promise 方式解决,其实也只是将这些随机性的耗时操作 defer 到了 EM 的线程池,这做法其实就是 thin 的实现啊。 然后这个框架提供的 Midori::File,Midori::Postgres 之类,这些就是 em-synchrony。所以,我才说这个框架本质上还是 thin + em-synchrony。而 尽可能减少在业务层加入异步相关的语法 这点在没有语言的支持上是很难做到,关键问题在第三方程序库;另外难以保证 Promise 的方式是可靠的,且性能不低于常规方式。

  • midori 百日记 at 2016年12月17日

    只不过阻塞问题有个巨大的特点,那就是一处阻塞,处处阻塞。Ruby 中常用的数据库连接、文件 IO 都是一些阻塞模型。一旦涉及数据库,Sinatra on Thin 的性能就会显著下滑。本质上来说,这件事情毫无道理,因为数据库的运算和 Web 框架无关,之和数据库程序有关。但由于 Web 程序一直在等待数据库返回而不去处理手上的事物了,这才导致了性能上的下滑。

    难道这个框架不是这样的?看测试用例,直接将并发量变为一啦(目测是 Midori::Server#receive_data 是在 EM 的主线程中执行的,而 resume 的 Fiber 在此会堵塞主线程):

    require 'em-midori'
    class Route < Midori::API
      get '/' do
        sleep 1; ''
      end
    end
    Midori::Runner.new(Route).start
    

    如果你说要改成这样:

    require 'em-midori'
    
    class Route < Midori::API
      get '/' do
        await(defer { sleep 1 }); ''
      end
    end
    Midori::Runner.new(Route).start
    

    确实可以。

    然后呢?这个框架要做的难道不就是 thin + em-synchrony 嘛?这跟 一旦涉及数据库,Sinatra on Thin 的性能就会显著下滑。 有啥关系?😅

  • 没必要为每个 action 设置 locales,偶觉得更好的方法是使用 around_action + I18n.with_locale,遵从谁申请谁释放的原则就可以啦。具体可以参考这篇文章 Working with Locales and Time Zones in Rails

  • rails test 报错, 关于 sqlite3 at 2016年12月05日

    这种 C 扩展的问题果断去官网看啊,貌似是这个:https://github.com/sparklemotion/sqlite3-ruby/issues/195。上面提了两个方案,一个是禁用 spring,一个是重新编译链接到别的版本的 sqlite3 。

  • 吐槽几点和 gem 本身相关的内容:

    • 软件包的可执行目录,现在推荐使用 bundle gem 默认生成时的 exe,而不是 bin,理由可以参见这篇博文:https://bundler.io/blog/2015/03/20/moving-bins-to-exe.html
    • allowed_push_host 这个字段目的是支持私有仓库,要么直接删除这几行代码,要么将 rubygems.org 加进去,何必弄一半,强迫症看着心慌
    • add_dependency 中的依赖最好限定版本,毕竟 gem 没有 Gemfile.lock 文件保障

    PS:个人比较推荐看 rubygems 官方的 guides,内容还是比较齐全的

  • rmmseg-cpp 无法安装 at 2016年11月18日

    gem install rmmseg-cpp

  • 蛤,蛤,蛤

趣味でヒーローをやっている者だ