GeekWeibo升级到 Rails 6.1

时隔一年半,期待已久的Rails 6.1 终于发布了。趁着双休,给 GeekWeibo 从Rails6.0 升级到了6.1。
升级主要有三步。

一、升级Gemfile里面各个gem的版本

为了避免一些gem版本的不兼容,我先本地gem install rails把系统的rails版本升级到6.1。然后使用 rails new demo61 创建了一个新app叫demo61。接着对比 demo61/Gemfile 和 geekweibo/Gemfile 里面各个gem的版本号,相应的升级一下版本号。主要diff如下:
NvOr8T

然后执行 bundle update

二、执行 rails app:update

前几天才知道原来还有 rails app:update这个命令,用于app升级。执行一下,按照提示,相应的覆盖或忽略一些文件更新。执行完了之后,很多bin文件和config文件都更新了。同时会生成两个新的active_storage的migration file。一个是给 active_storage_blobs table新增了一个 service_name column:

# This migration comes from active_storage (originally 20190112182829)
class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]
  def up
    unless column_exists?(:active_storage_blobs, :service_name)
      add_column :active_storage_blobs, :service_name, :string

      if configured_service = ActiveStorage::Blob.service.name
        ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)
      end

      change_column :active_storage_blobs, :service_name, :string, null: false
    end
  end

  def down
    remove_column :active_storage_blobs, :service_name
  end
end

另外一个是新增了一个active_storage_variant_records table

# This migration comes from active_storage (originally 20191206030411)
class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]
  def change
    create_table :active_storage_variant_records do |t|
      t.belongs_to :blob, null: false, index: false, type: :uuid
      t.string :variation_digest, null: false

      t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true
      t.foreign_key :active_storage_blobs, column: :blob_id
    end
  end
end

接着执行 rails db:migrate,一切正常。

三、使用systemd管理puma进程

我的项目是使用capistrano来部署的。执行完前面的两个步骤,本地试运行,解决掉一个gem的兼容性问题(后面会提到)之后。执行cap production deploy之后,提示没有 cap production puma:restart这个task。一番google之后,发现原来是puma 5 把daemon启动模式去掉了。相应的capistrano3-puma 5.0之后的版本,默认的task里面也自然没有这个启动模式了。
解决办法是使用systemdmonitpm2这些第三方的process monitor/manager。我因为不想折腾,所以采用linux(或者说ubuntu)自带的systemd。

在Capfile里面新增一行

# 在install_plugin Capistrano::Puma 之后
install_plugin Capistrano::Puma::Systemd

然后执行

cap puma:systemd:config    # 会生成一个systemd unit文件,并上传到服务器的/etc/systemd/system/文件夹下面。
cap puma:systemd:enable    # Enable上一步上传的service

然后再执行 cap production puma:restart,这个命令会在服务器上面会执行sudo systemctl restart puma这时候提示报错了,说systemd的service unit里面,ExecStart的命令格式有问题。我查看了一下,发现生成的unit文件里面,ExecStart这一行的内容是

ExecStart=~/.rvm/bin/rvm default do bundle exec puma -C /your/deploy/path/geekweibo/shared/puma.rb

我猜测是~/这个地方出错了。改成绝对路径

ExecStart=/home/username/.rvm/bin/rvm default do bundle exec puma -C /your/deploy/path/geekweibo/shared/puma.rb

然后在服务器上面执行 sudo systemctl daemon-reload,因为我们修改了unit文件,需要reload一下systemd daemon生效。

回到开发机,再次执行cap production puma:restart,果然就可以了。我猜测之所以 ~/这种写法会有问题,是因为我没有指定puma的user。

遇到的问题

不少朋友说升级6.1之后,遇到很多gem不兼容的情况。可能是因为我这个项目比较小,我这次升级,只遇到一个gem不兼容。那就是skylight-ruby gem(一个APM服务)。报了一个

NoMethodError (undefined method `instrument' for #<ActionView::TemplateRenderer:0x00007f9d9cc61ee8>)

这样的错。这个gem的Github issues里面也有不少人反映这个问题。据作者说,gem新版beta里面已经解决了,不过我不想采坑,所以没上beta,只是按照他们的说明,用了一个workaround,在config/application.rb里面加一行

config.skylight.probes -= %w[action_view]

解决了问题。

升级以后,有了哪些好处呢?

好像没发现。Rails 6.1 很多新增功能是针对multiple DB的,对我好像没什么影响。我主要是冲着strict loading和activestorage的permanent url来的。其中strict loading,在另外的一个小app里面开了strict loading by default,结果带来一些问题,于是又禁用了。而activestorage的permanent url,除了方法名使用 url 代替 service_url,其他好像也没发现什么区别。我原来使用 service_url 获取到的url,貌似也不会变?不清楚是不是我理解还不到位。

总体来说,因为项目比较小,这次升级还是比较顺利的,但好像也没带来什么特别的优势。所以,对于想升级的朋友,可以参考一下。

Leave a Reply