• 赞!ruby gems 也有国内镜像就好了,gems.ruby-china.org 太慢了,而且经常出现下载 gem 失败的情况,搞得我只能用 vendor/cache 的方案来做部署,有点小麻烦。

  • 自己用 errbit 搭一套服务,它的数据格式兼容 airbrake,客户端 sdk 就有 airbrake, 薄荷现在是这么做的。

  • 很赞!选对了方向,努力才有效果,不要用战术的勤奋掩盖战略的懒惰,每天都要留够思考的时间。这次收听 robbin 大牛的分享很有收获。

  • Ruby 上海学习之旅 at 2016年02月26日

    谢谢支持,欢迎再次到薄荷坐一坐,:)

  • 如果执行周期很频繁,比如每分钟执行一次,可以用 sidekiq-cron,这样能避免频繁加载 rails 环境,提升效率。如果周期很长,我觉得还是用 crontab 比较好,干净独立,依赖少,不会有干扰。

  • 用 rake 任务 + crontab,使用 whenever 管理部署。 需要注意的是,处理逻辑不要全堆在 rake 文件里,而是放在 model 或者 service 中,rake 只作为调度控制,这样容易写测试。然后是日志和异常监控,日志最好打到单独文件,不要和 web 日志混在一块,异常监控可以用第三方服务或自建 errbit。

  • 好用,刚刚设置了一下,立竿见影。

  • 整体策略有问题,应该在数据库层面做过滤,而不是把数据拉到 Ruby 进程做过滤。 把几百万的数据拉回来过滤,涉及到网络传输,分配大量内存建立对象,难以优化。如果在数据库层面做过滤,配合好的索引,速度有数量级的提升。

  • 很棒的分享!深入浅出,有实际的例子和执行结果为证,很有说服力。 ruby fiber 特性偏底层,大部分情况都接触不到,所以看起来会比较吃力的,得趁机再去温习基础知识。如果要在实际项目中利用,估计得封装成 gem,屏蔽一些底层东西。

  • #9 楼 @rubyfan1 要严格推行单元测试和代码 review 说难也不难,顶住压力,把它作为工作考核的重要部分就可以。上面提到的一系列工具都可以作为参考测量工具。

  • 最重要的不是工具,而是意识和方法。我认为保障 Ruby 代码质量最有效的两个措施,一是单元测试,二代码 review。

  • #16 楼 @rivid 赞 我们迁移到 MySQL 是因为其它项目都用的是 MySQL,运维不熟悉 PostgreSQL,如果可以自由选择,也是倾向 PG 的。 另外,迁移比较痛苦是因为数据量很大,几张表有千万到亿级,不能在迁移过程中长时间宕机。 所以迁移的步骤是:

    1. 双写,同时写入 mongodb 和 mysql,从 mongodb 读;
    2. 双写,从 mysql 读;
    3. 只从 mysql 读写,移除 mongodb。
      这样有一个好处是,如果 2 有问题,可以随时回滚到 1,中间没有数据丢失。
  • 我们自己做过 Mongodb 到 MySQL 的迁移,过程十分痛苦,而且到现在还没有完全做完。

  • 赞!迁移数据库很累人的,真是勤奋!@huacnlee @rivid Rails 还是使用 ActiveRecord 顺手,Mongodb 不像看上去那么美女,这次迁移是值得的。

  • #55 楼 @gazeldx 谢谢,欢迎试用,欢迎提问和参与修改,:)

  • #37 楼 @gene_wu #38 楼 @arthur_h #39 楼 @lgn21st 好,那我就准备一个 topic,暂定是“基于 RabbitMQ 实现 rails 应用微服务间通信”,预计在 30 分钟左右。

  • #34 楼 @gene_wu 也许我可以贡献一个 topic,“基于 RabbitMQ 实现 Rails app 间通信实践”,主要想和大家分享薄荷使用 RabbitMQ 作为消息中间件实现微服务间的异步消息,事件广播和远程方法调用(RPC),不知道大家是否有兴趣?

  • 求一个类图的实现? at 2015年12月26日

    可以简单使用 source_location 方法获取某个方法定义的文件和位置。

    比如你有一个对象 bar,里面有一个方法 foo,bar 的定义比较复杂,搞不清 foo 在哪儿定义的,可以用下面方法打印位置

    puts bar.method(:foo).source_location

  • 这个主题好,我也尽量参加 +1

  • 在 Model 中使用 routes helper at 2015年10月30日

    最好不要在 model 中使用 view 的方法,MVC,VC 对 M 的依赖应该是单向的,这样比较简单,假如让 M 依赖 V,会带来不少麻烦。

    一个可能的解决方法是,view 层在调用 model 层,通过参数把数据(对象)传给 model。

  • 改成这样就可以了

    Rails.cache.fetch("rand_products", expires_in: 1.day) do
      Product.order('RAND()').limit(20).to_a
    end
    

    因为你原先缓存的 Product.order('RAND()').limit(20) 是一个 ActiveRecord::Relation 对象,直到使用数据的时候才进行实际查询, 使用 to_a 方法之后,会真正查询数据库,返回数据对象。

    1. 会话数据一般放在共享存储中,如放到 redis 或关系数据库,会话 id 一般就保存在 cookie 中;
    2. 应用的结构化数据,一般都是放在集中的数据里,比如 mysql, pg 或 mongodb, 为了性能可以使用缓存;
    3. 应用的非结构化数据,比如用户上传文件,简单的话可以放云存储中,比如七牛或又拍;另一种方式是搭网络共享文件存储系统,如 nfs, 或者分布式文件系统,如 moosefs, dfs 等等。
  • @quakewang 原来 ruby 和 @ 还有这等神奇用法,涨姿势了

  • Rails log 里就可以粗略看到(log 调成 debug 模式),也可以用 newrelic 做简单的 profiling,另外还有 ruby-prof。 Ruby 中的 Profiling 工具 https://ruby-china.org/topics/25856 Ruby Profiler 详解之 ruby-prof(I) https://ruby-china.org/topics/25959

  • 每个请求中,几大块的时间分别是多少(比如 controller, render, database, redis)? 有做 profiling 吗? 我猜效果不好的原因是:很大一块时间是在(controller + database)上,你目前使用缓存的方法只是减少了 render 的时间。

    1. 通过视图并没有避免 join,只是把 join 交给数据库视图处理而已,性能上和自己 join 应该没有多大区别。
    2. 有一种视图叫物化视图,pg, oracle 数据库有,mysql 没有。物化视图真正把数据生成了,所以避免了 join,性能上有提升,代价就是数据库要维护。
    3. 按正常的建模方法,rails 可以使用 eager load 和 cache,不一定非要 join,我认为更可控,性能也不会差。
  • :plus1: 关注是一个挺麻烦的问题,特别是当数据量上去之后,很容易出现性能瓶颈,为了解决这个问题薄荷用了不少方法,这篇文章里提到了 2 个比较有效的做法,但不仅限于此。

    @rei 考虑过分批处理。从逻辑上分析一定可以提升速度的,但是有些大 V 关注量实在太大,比如说 500 万,如果分成 100 批同时处理,估计频繁数据库读写瞬间对系统造成大的冲击,所以后来没有采用这种方法。

    @lithium4010 这个问题和你聊的的问题有些不一样。那个是解决大批量用户的系统广播问题,不过一样的地方在于:当数据量并发量上去之后,看似简单的设计很容易出现瓶颈,必须使用一些算法策略解决。

    文章里没有提到的一个大招是,区分活跃用户和僵尸用户(大部分互联网系统中,海量用户至少一半以上是僵尸用户),优秀处理活跃用户数据,尽量避免处理僵尸用户数据,如果僵尸用户再次造访,通过一个任务更新他的数据。

  • #15 楼 @lithium4010 我重新改正代码跑了测试,和你的结果不一样啊,缓存服务器在本机时数据如下:

              user     system      total        real
    1-1   0.550000   0.230000   0.780000 (  1.133004)
    2-1   1.280000   0.330000   1.610000 (  1.757418)
     10   0.430000   0.050000   0.480000 (  0.512793)
     30   0.330000   0.030000   0.360000 (  0.383506)
     50   0.320000   0.020000   0.340000 (  0.349198)
    100   0.290000   0.010000   0.300000 (  0.310068)
    

    在局域网内,如下:

              user     system      total        real
    1-1   0.660000   0.620000   1.280000 (  4.236520)
    2-1   1.400000   0.750000   2.150000 (  5.674942)
     10   0.450000   0.100000   0.550000 (  1.114594)
     30   0.420000   0.070000   0.490000 (  0.772291)
     50   0.410000   0.060000   0.470000 (  0.678551)
    100   0.380000   0.060000   0.440000 (  0.560123)
    

    多个单次读和批量读差异还是挺明显的。

    代码见 https://gist.github.com/xiewenwei/b55070b49a73f187c284

  • #15 楼 @lithium4010 非常感谢指出 benchmark 代码中的一个问题,请原谅我的疏忽。我修正了代码,重新跑了 benchmark,缓存服务器同在一台机器时差异不太多,在远程时差异还比较明显,但是没有上百倍的差距。

  • #42 楼 @lips ruby 工程师最主要的职责就是 app 后端开发,app 前端开发:iOS, Android 和 Web 前端工程师也非常欢迎。