Rails并发问题锁定

时间:2018-06-17 21:01:41

标签: ruby-on-rails concurrency puma

我有一个rails应用程序,其中一个动作永远不会完成然后超时。 请参阅下面的图表以获得更好的说明。

  1. 我的rails应用操作称为
  2. 操作将一些数据发布到另一个应用
  3. 另一个应用程序需要一些东西来完成计算并调用与第一个Rails应用程序不同的操作
  4. 其他应用获得响应并完成计算
  5. 其他应用响应rails应用POST请求
  6. 视图相应呈现
  7. architecture

    现在问题:其他应用永远不会从主应用获得响应。然而,在Rails应用程序请求超时后,响应被发送(当然太迟了)所以我认为它是以某种方式提示的。

    我不明白如何解决这个问题。我使用rails 5和Puma应该能够处理并行调用。它也不是本地问题,在产品中也是如此。

    我使用Heroku推荐的puma.rb配置

    @PostMapping(value="/borrow")
    public ResponseEntity<Void> postBorrowBook(@RequestBody RequestDTO requestBody) {
        requestBody.getPersonId();
        requestBody.getBookId();
        ...
    }
    

    我该怎么做才能解决这个问题?

    控制器:

    declare(...)

    辅助

    workers Integer(ENV['WEB_CONCURRENCY'] || 2)
    threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
    threads threads_count, threads_count
    
    preload_app!
    
    rackup      DefaultRackup
    port        ENV['PORT']     || 3000
    environment ENV['RACK_ENV'] || 'development'
    
    on_worker_boot do
      # Worker specific setup for Rails 4.1+
      # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
      ActiveRecord::Base.establish_connection
    end
    

    请求只是一个薄的包装

        # New method
        def live_preview_page
          preview_locale = params[:preview_locale]
          date = params[:date] # The date to preview
          page_id = params[:id]
          return if locale.nil? || locale =~ /not/ || date.nil?
          all_templates = Template.all.order('name ASC') # Maybe move to render_live_editor_page
          if date == "all"
            active_modules = @page.page_modules.order(rank: :asc)
          else
            active_modules = @page.page_modules.order(rank: :asc).to_a.valid_for(date: date.to_date)
            puts "Active modules: #{active_modules.count}"
          end
          active_modules_json = active_modules.each do |content_module|
            content_module.body = YAML.load(content_module.body).to_json
          end
          response = helpers.render_preview(active_modules, all_templates, preview_locale)
          renderer = ContentRenderer.new
          actionController = ActionController::Base.new
          rendered_helper = actionController.render_to_string(
            partial: '/pages/preview-helper-snippet', locals: {
            all_templates: all_templates, # For select when creating new modules
            modulesData: active_modules_json, # For rendering the JSON containing the data for the editor
            current_page: @page.id,
            localeLinks: renderer.generateStgPreviewURLs(SettingService.get_named_locales, @page.id),
            locale: preview_locale,
            all_locales: SettingService.locales_for_live_editor,
            all_sites_and_locales: SettingService.get_sites_and_locales
          })
          proxy_service = ProxyService.new
          proxy_service.get_page do |error, page_wrapper|
            # Note: Issue is that Vapor app generates warnings inline template : encountered \r in middle of line, treated as a mere space
            rendered_body_with_helper = response.body.force_encoding("UTF-8") + rendered_helper
            decorated_page = page_wrapper.gsub("__WIDGET__", rendered_body_with_helper)
            render inline: decorated_page
            return
          end
    
        end
    

1 个答案:

答案 0 :(得分:0)

以下答案(可能)不是您想要的答案-而是您需要的答案:

解决此问题的最佳方法是避免请求/响应逻辑中的循环(rails应用通过另一个应用调用自身)。

并发性可能有助于延迟问题的发作,但是只要存在循环,问题就总是会发生。

例如,假设您有100个来自客户端的Rails应用请求。

Rails将调用另一个应用程序,另一个应用程序的请求将作为请求号101排队。

这可以用100个线程解决(例如,10个工人,每个线程10个线程)...

但是您的应用程序如何处理200个客户请求?

这个周期是无止境的,体验到DoS的客户端越多,所需的并发性就越高。

唯一的解决方案是避免循环开始。

要么将其拆分为3个应用,要么(最好)避免微服务之间的依赖。