• Rails 6.1 正式发布了~! at 2020年12月10日

    nice!

  • 如果改为服务器渲染 那绑定的 js 交互还存在么?

  • 暂时没有 我猜是不是可以通过 turbolinks:load 解决?

  • 是会遇到先空后刷出 react 组件的问题

    因为 html 在正常 dom 加载完毕之后就会进行渲染

  • 只是习惯吧

    愿意的话,你可以在 nginx 上处理

    或者给 link_to 打个猴子补丁 (不推荐)

  • 不知道为什么,我后置的 if 还挺符合直觉的?

    我一般用在 return xxx if xxx 中

    感觉这种用法会减少很多嵌套

    最后剩下的逻辑就特别简单

  • 使用过程中发现安装脚本跟我的环境稍微有点冲突

    其实老哥你既然用 ruby 作为依赖 install.sh 也可以用 ruby 来消除各种系统的兼容性问题

    我在安装的时候就遇到

     bash ./install.sh                                                                                                                                                                                          master
    readlink: illegal option -- f
    usage: readlink [-n] [file ...]
    usage: dirname path
    

    以及 7z 的问题,其实甚至可以用 ruby 的 gem zip 解的

  • 赞~

    陡然看到 gitee.com 的地址还有些反应不过来

    但是 真的酷毙了~

  • 不太赞同“但如果只在某个局部使用就有点为了 React 而 React 的意思了”

    react 的本质是 state => ui, state 变 ui 变

    如果 有较高密度的 数据变化引起的 ui 变化,就适合 react

    所谓 react 生态我是觉得挑自己想要的就好 不需要全站数据刷新的时候就没必要上 redux, 量少 localstorage 也是够用的。

    也可以参考下这里

    https://ruby-china.org/topics/38603

  • 震惊部空降了

  • 简单的或者需要 seo 的用 stimulus,复杂的用 react/vue

  • tailwind 最好的地方就是 你想咋变就咋变

    bootstrap 我真记不住他的 css 结构 每次改个样式都很麻烦

  • 主要大多数人认为所谓的 react 是 react + redux + react router + immutable + hook + webpack plugins + fetch,axios 啥的

    而且一上就要从头开始 搞个 all in react 的前端项目,光弄明白初始化配置,刚接触的人一个星期都不一定能搞定。

    其实 react 可以单纯的在某个局部使用,只依赖 react.js 甚至连 webpack 都不用配置,直接怼进去都可以,

    一旦意识到 其实 react 的本质就是 state => ui 后,就可以在觉得依赖数据变化的 UI component 使用 react 了

  • 哇 现在都不玩 bootstrap 上 tailwindcss 了呀

  • 楼主这种可能是对业务级别代码抽象之后,比较方便

    其实公司流程指定的好的话,这种挺方便的

    其实这个也是编程界的传统手艺了,在很多年前 ORM 不是很成熟的时候,

    大家上三层架构,很多语言都会有所谓的 代码生成器的存在

    另外其实 rails 周边也有一些对常见流程的代码的整合,

    比如 gorails 小胖子 弄的 https://www.railsbytes.com 我就特别喜欢

  • 在 Rails 中集成第三方登录 at 2020年08月18日

    哈哈哈 史诗级问题

  • 高并发的电商 at 2020年08月14日

    其实就是个秒拍系统

    秒拍系统的核心理念就是

    能不动数据库就不动数据库

    那么如何在不动数据库的情况下,解决用户高并发的问题呢? 高并发下,要守住两个底线:

    • 库存不能为负
    • 下单成功,且付款成功的,一定要购买成功

    将秒拍抢购进行进一步的分析:

    1. 用户首先获得购买资格(库存足够 + 用户下单)
    2. 用户付款,安排发货

    其实并发压力就在 1 上,2 无所谓,毕竟付款成功后回调大多数系统都有 retry 机制,问题不大。 至于解决并发压力最好的方式就是让这些变成串行通过,

    最简单方式自然是 利用 redis 的原子性来进行操作

    方案 1:硬来

    redis 记录库存数量,待秒杀开始时,进来的请求进行下单操作,DECR 后的读书如果>=0,则建立订单,注意,这里一定要利用 decr 的原子性,在此判断之前,不要有任何数据库操作,否则数据库会爆

    if redis.decr(SKU_STOCK_GATE) >= 0 # 在此之前不要有数据库读写操作
      create_order(current_user, sku) #这里最好是个异步, 否则也可能造成数据库抖动
    end
    

    这种最基础的方式有一个麻烦之处,如果有一个买家想一次购买 N 个商品,就比较头疼了,因为我们很可能遇到这样的情况,库存只有 1, 但是此时用户要买 2 个或者更多

    如果需求是:如果是多个购买,则允许最小购买数,那就无所谓,系统可以将其转化为单位为 1 的订单,但是大部分是:如果数量不够,就建立订单失败。

    因为包含了多个购买,所以就不能用 decr 而是要用 decrby 2 了 此时 SKU_STOCK_GATE 为 1,redis 操作完毕后,GATE 值为 -1 不满足 GATE 条件,不能购买了。 库存不变

    但是此时就有个麻烦的地方:
    STOCK_GATE 已经小于 0 了,但是真实的库存是 1

    此时,如果再有人购买一个库存,也会提示失败了

    也就是说,这种方案的弊病就是:

    有可能出现 库存还有,但是无法进行购买了

    其实我们可以发现,大于 1 的购买,STOCK_GATE 有几种可能

    1. 在 STOCK_GATE 操作之前,STOCK_GATE 就已经为负数。这种分俩情况,第一种情况是,前置操作是 单一购买,以及前置操作是大于 1 的购买,用递归的思想,后者一定开始于前置是单一购买或 0 购买,而没人买的话,不存在库存不足的问题,所以 这种问题简化成:前置是单一购买,且操作前 STOCK_GATE 已经为负,这种情况很好理解,就是没库存了,购买失败

    2. STOCK_GATE 在操作前后,都为正,所以没啥说的,正常购买

    3. STOCK_GATE 在操作钱为 正,操作后为负,这种是库存不够,购买失败,理应回退库存

    但是这里就有个问题,因为要拿到 decr 之前的数据,所以要先 get 一下数据,超过 1 次操作 redis 的话, 整个操作就不保证原子性了,当并发高的时候,就会出大问题,例如:

    账户 A 和账户 B 请求同时 一起进来

    有可能出现这样的情况,假设 key 的值是 0,当 k <0 的时候,跳出判断,否则执行减 1, A 和 B 一起发生 GET 请求,A 先返回 GET 请求,ruby 执行下一句 让 redis 执行 decr - 1,但是正当 ruby 要通知 redis,但 redis 还没执行的时候 B 的 ruby 的 GET 命令先到达了 redis , 此时 redis 也返回 0 于是根据 ruby 的逻辑,B 也会执行 -1

    解决这类问题,自然是锁

    改进后的方案 2:lock

    使锁来保证判断的时候只有单线程,不会出现数据脏读

    begin
      block_result = lock_manager.lock!("SKU_LOCK_KEY", 2000) do
        pre_gate_value = redis.get('SKU_STOCK_GATE')
        return false if pre_gate_value <= 0  # 库存没有了
    
        after_gate_value = redis.decrby(SKU_STOCK_GATE, num
        if after_gate_value >=0 
          return true  #可以购买
        else
          redis.incrby(SKU_STOCK_GATE, num) # 将扣除的加回来
          return false  #
        end  
      end
    rescue Redlock::LockError
      # 锁超时, 理论上来说这里只有redis 和最简单的判断操作, 很难超时, 最好接入人工检查
    end
    

    通过锁可以解决问题

    但是这种方案有没有啥其他的问题呢?

    比较麻烦,自己维护锁,万一锁超时,检查起来也很烦躁

    于是到了我觉得最简单的方案 3,排队。

    方案 3:排队

    即当发生抢购的时候,利用 redis,在一定时间内,给每个参加购买的人一个号码即可,之后入队。

    因为 push 本身靠的是 redis 来保持原子性,所以无所谓。

    之后拿一个进程单独处理这个队列,不符合的就直接 next,因为是独立处理,所以压根不存在并发问题,也就没有锁的概念。

    但是这种的缺点也很明显,即订单生成时间与用户无关,只与 进程处理时间有关,但是其实这个时候秒杀用户基本也都在线,就算建立的订单最后他没支付,重新将库存加上即可。

  • 国际团队用的真不少

    国内介于网络原因 估计不太适用普通公司

    我是被 command + j 震惊的 无敌好用

  • Rails 单元测试相关 at 2020年07月29日

    咱俩应该是一个症状 我这也是 406 的 bug

  • "至少开发过几百行的 worker"

    将几百行的逻辑都塞到一个 worker 里,不太好测试,出错了 retry 也比较难定位

    建议抽象出来,一一测试

  • 😂 😂 😂 知道真相的我眼泪掉下来 谁说 rails 耗机器的

  • 先弄,弄出来了市场上跑一圈,效果好就好 效果不好就当练手

  • 恰好自己拿 esp 8266 实现了个 mqtt

    楼主可以发一个 跟 ruby 相关的 实现 mqtt client 的内容,纯介绍的话 容易被当做广告贴处理

  • ps 是使用的 swarm 的

    类似这样的配置么

    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 5s
    

    另外还有个地方还想请教下

    就是 docker 下 静态文件夹 public 的管理。

    因为配置等原因,我们还是期望 nginx 不在容器中运行 puma 提供的服务,本身我们可以依赖 upstream, 但是静态文件这块就有点尴尬,

    之前我们的做法是 有个 container 专门接受从外层主机挂载的目录 /tmp/public, 之后这个镜像 run 的指令就是 cp -r public /tmp/public

    这样外层的机器就获得了镜像里的 public 文件夹,但是我觉得这种方式属于取巧的邪道

    能否参考下您的解决方案 或者 有人能好心分享下么?

  • 哈哈 我正准备问 嘛时候可以把 backbone 换一下口味

  • anycable 已经更新到了 1.0 版本 看着性能还是不错的 10000 个 client 95% 也就 1 秒

    clients:  1000    95per-rtt: 196ms    min-rtt:   2ms    median-rtt:  33ms    max-rtt: 252ms
    clients:  2000    95per-rtt: 296ms    min-rtt:   2ms    median-rtt:  48ms    max-rtt: 596ms
    clients:  3000    95per-rtt: 462ms    min-rtt:   2ms    median-rtt: 101ms    max-rtt: 694ms
    clients:  4000    95per-rtt: 670ms    min-rtt:   3ms    median-rtt:  72ms    max-rtt: 1382ms
    clients:  5000    95per-rtt: 712ms    min-rtt:   3ms    median-rtt: 101ms    max-rtt: 1526ms
    clients:  6000    95per-rtt: 739ms    min-rtt:   3ms    median-rtt:  99ms    max-rtt: 2901ms
    clients:  7000    95per-rtt: 745ms    min-rtt:   2ms    median-rtt: 231ms    max-rtt: 2800ms
    clients:  8000    95per-rtt: 950ms    min-rtt:   2ms    median-rtt: 173ms    max-rtt: 3109ms
    clients:  9000    95per-rtt: 1133ms   min-rtt:   3ms    median-rtt: 185ms    max-rtt: 4084ms
    clients: 10000    95per-rtt: 1033ms   min-rtt:   3ms    median-rtt: 248ms    max-rtt: 2671ms
    

    https://github.com/anycable/anycable/blob/master/benchmarks/2020-06-30.md

  • 目前使用 docker-compose 的时候出现一个问题

    在升级 image 完毕后, 重新运行 docker-compose 的时候 这个时候新的 docker image 有启动时间 这段时间会 502

    大概几秒,docker 里的 puma 启动完毕后就没这个现象了

  • Twitter 上被 Hey 刷屏了 at 2020年06月17日

    感觉自己用邮件还没有用到那么强....

  • 最近大家开始折腾 ActionCable 了呀

  • 是重启 docker 后恢复原始吧

    docker 的特性

    如果不想 建议将 homeland 的页面挂载出来