ruby-on-rails – Rails在多个实例/服务器上重新加载动态路由
我们如何在多个服务器/实例上强制Rails重新加载路由?
我们在5个实例上运行Google App-Engine中的多租户平台,我们希望所有站点都从后端定义自己的路由集.每当我们有一个新站点时,我们当前必须重新启动所有服务器才能访问新路由. 我们遵循这个guide,但它只适用于本地环境,并且不会在不重新启动服务器的情况下更新生产中所有服务器上的路由. 我们的路径文件如下所示: 的routes.rb Frontend::Application.routes.draw do root 'home#index' ... DynamicRoutes.load end LIB / dynamic_routes.rb def self.load Frontend::Application.routes.draw do Site.all.each do |site| site.routes.each do |custom_route| route_name = custom_route[0] route = custom_route[1] # write the route with the host constraint self.constraints(:host => site.hostname) do case route_name when :contact_form mapper.match "#{route}",to: 'contact_forms#new' as: "contact_#{site.id}" end ... end end end end end def self.reload Frontend::Application.reload_routes! end 每次更新路由或创建新站点后,我们都在运行DynamicRoutes :: reload 解决方法
我们终于找到了一个运行良好的解决方案,也没有太多影响性能.我们使用生产中的线程在请求??之间保持状态的事实.所以我们决定创建一个中间件来检查路由更改的最新时间戳,如果时间戳与Thread.current中保存的时间戳不同,我们强制使用Frontend :: Application.reload_routes!
配置/ production.rb Frontend::Application.configure do ... config.middleware.use RoutesReloader ... end 应用/中间件/ routes_reloader.rb class RoutesReloader SKIPPED_PATHS = ['/assets/','/admin/'] def initialize(app) @app = app end def call(env) if reload_required?(env) timestamp = Rails.cache.read(:routes_changed_timestamp) if Thread.current[:routes_changed_timestamp] != timestamp Frontend::Application.reload_routes! Thread.current[:routes_changed_timestamp] = timestamp end end @app.call(env) end private def reload_required?(env) SKIPPED_PATHS.none? { |word| env['PATH_INFO'].include?(word) } end end 应用程序/模型/ routes.rb中 class Routes < ActiveRecord::Base after_save :save_timestamp private def save_timestamp ts = Time.zone.now.to_i Rails.cache.write(:routes_changed_timestamp,ts,expires_in: 30.minutes) end end 优点: >您可以在某些路径上排除重新加载,例如/ assets /和/ admin / 注意事项: > New Threads将加载两次路由 但总体而言,我们没有发现任何性能下降. 我们多年来一直在努力解决这个问题,上面的解决方案是第一个真正帮助我们在多个线程上重新加载路由的解决方案. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |