rails项目升级(rails3->rails4)

拖延了很久的rails版本升级终于告一段落了,由于目前项目作为一个大的单体应用,在讨论了几次后还是确定把rails3升级到rails4版本,最终升级到rails5.

修复版本第一阶段:
rails3.2 - rails4.0.13

预备工作: 做好前期准备,比如人员分配(新功能迭代和升级工作的安排),升级中业务能不能间断等问题。确定升级方案。

最终我们采用了两版本同时跑生产环境,先给rails4版本少量流量,要保证单台服务器一旦遇到问题,随时停掉,然后追踪修复错误,逐步释放更多流量,循环执行直到项目正常运行。

具体升级步骤:

第一步:

补测试,可能很多项目由于开发周期原因,测试覆盖不足。这里建议请至少保证测试覆盖到公司的主业务,当然覆盖度越高越好。建议这个时候把持续集成给补上(如果没有的话)。

第二步:

仔细阅读升级文档:

升级文档
https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-3-2-to-rails-4-0

release文档:https://edgeguides.rubyonrails.org/4_0_release_notes.html

一些踩过坑的博客如:http://www.recursion.org/incremental-rails-upgrade/

第三步

动手,按照升级文档修改代码,升级gem,并确保测试通过。

第四步

部署到staging服务器(连接到复制的一个线上数据库实例),录制线上流量测试,参考:https://ruby-china.org/topics/37756

第五步

通过newrelic追踪staging错误,修复错误,重复第四步的测试。

升级过程中遇到的坑:

Assets编译:

在rails4中asset编译的摘要算法发生了变化,也就是在rails3和rails4中相同内容编译出来的文件名是不同的,所以我们采取了将不同版本的机器的assets文件统一放到共享目录下,保证不同机器可以准确访问到assets资源。

json的time格式兼容:

rails4中时间格式"2018-12-04T16:54:40.000+08:00"不兼容rails3格式"2018-12-04T16:54:40+08:00"
导致安卓客户端时间格式解析失败。参考源码:

#  https://github.com/rails/rails/blob/master/activesupport/lib/active_support/time_with_zone.rb#L157

class ActiveSupport::TimeWithZone
  #Changing the as_json method to remove the milliseconds from TimeWithZone to_json result (just like in Rails 3)
  def as_json(options = {})
    if ActiveSupport::JSON::Encoding.use_standard_json_time_format
      xmlschema
    else
      %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
    end
  end
end

ActiveRecord查询结果类型问题:

rails3中.all方法返回的是Array,Rails4中返回的是ActiveRecord::Relation

unscoped行为不一致:
rails3中查询语句

"SELECT `offline_charges`.* FROM `offline_charges`  WHERE `offline_charges`.`chargeable_id` = 4357 AND `offline_charges`.`chargeable_type` = 'RegRace'"

rails4中查询语句丢失关联条件

"SELECT `offline_charges`.* FROM `offline_charges`"

序列化和反序列化问题:

在rails4中存入的是!ruby/hash:ActionController::Parameters
rails3中存入的是: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
serialize, Rails use YAML by default to convert the data, 异常捕捉:SerializationTypeMismatch

first方法的变化:
rails4中因为因为添加了order by条件可能会导致某些优化不太好的查询很慢。

# rails4中.first调用
Photo Load (14453.0ms)  SELECT `photos`.* FROM `photos` WHERE `photos`.`album_id` = 88281 ORDER BY `photos`.`id` ASC LIMIT 1

# rails3中.first调用
Photo Load (15.2ms)  SELECT `photos`.* FROM `photos` WHERE `photos`.`album_id` = 88281 LIMIT 1

Cache缓存问题:

经过尝试发现rails4中缓存的内容rails3可以正常访问,而rails3缓存的内容在rails4中乱码?
而在一个讨论中明确表示该功能不会做向前兼容,详见: https://github.com/rails/rails/issues/17923

处理该问题我们隔离了不同版本机器的缓存db,注意一些缓存数据可能需要持久化到数据库中,不然当两次相关的访问分发到了不同版本的机器上会出现问题(当然这个问题在后面有一个比较好的解决方法)。

strong_parameters问题:

rails4中引入了strong parameter, 所以如果保持rails3的mass assign写法不变并兼容rails4,可以通过在rails3中引入strong_parameters gem包,
否则会遇到类似YAML.parse时抛出no module ActionController::Parameters错误以及其他的一些问题.

Cookie问题:

Rails3中cookie仅仅做了Base64编码,但是在rails4中为了安全在编码的基础上又做了一次加密(encrypted),rails4中的加密操作就是通过配置secret_key_base实现的(该配置在rails4.1版本后会使用config/secrets.yml配置形式)。这里根据官方文档,由于我们还没有准备全部切换为rails4环境,我们暂不引入secret_key_base,
将两版本下的配置统一为:
Myapp::Application.config.secret_token = “the secret token”
请注意,你要等到100%的切换到rails4并且不需要切换回rails3时再配置secret_key_base,因为rails4中基于新的secret_key_base生成的cookie是不可逆的。如果有其它的application或则js你的程序依赖你的程序提供assigned session cookies(或一般的assigned cookies),在你将两部分功能解耦前不要配置secret_key_base。

详见:https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#config-secrets-yml#action-pack

flash问题:
由于flash也是基于session的,兼容解决方案如下:

Errors like “NoMethodError: undefined method `sweep' for #

使用: https://stackoverflow.com/questions/30916375/errors-like-nomethoderror-undefined-method-sweep-for-hash-after-downgra/31186843

你可能感兴趣的:(rails项目升级(rails3->rails4))