2014-09-16 14 views
6

Chúng tôi đang sử dụng Ruby 2.1.2, Rails 3.2.19 với JQuery 1.11, đường dẫn nội dung không được sử dụng (vì vậy không sử dụng JQuery-ujs, nhưng đang sử dụng rails.js liên quan một cách rõ ràng). Đối với hầu hết người dùng, JQuery và các plugin phổ biến có liên quan khác đang được lấy từ Google CDN (bao gồm jquery.form 3.50). Máy chủ web bị ảnh hưởng là Ubuntu 14.04, Nginx 1.6 và Hành khách 4.x.Rack ném EOFError (nội dung xấu)

Đối với khoảng 10% người sử dụng trên máy chủ sản xuất của chúng tôi (tải dường như không quan trọng), chúng tôi đang nhận được một đống đổ như thế này, chủ yếu cho một URL nhưng có những người khác:

/gems/rack-1.4.5/lib/rack/multipart/parser.rb:74 in "block in fast_forward_to_first_boundary" 
/gems/rack-1.4.5/lib/rack/multipart/parser.rb:72 in "loop" 
/gems/rack-1.4.5/lib/rack/multipart/parser.rb:72 in "fast_forward_to_first_boundary" 
/gems/rack-1.4.5/lib/rack/multipart/parser.rb:15 in "parse" 
/gems/rack-1.4.5/lib/rack/multipart.rb:25 in "parse_multipart" 
/gems/rack-1.4.5/lib/rack/request.rb:336 in "parse_multipart" 
/gems/rack-1.4.5/lib/rack/request.rb:201 in "POST" 
/gems/actionpack-3.2.19/lib/action_dispatch/http/request.rb:237 in "POST" 
/gems/actionpack-3.2.19/lib/action_dispatch/http/parameters.rb:10 in "parameters" 
/gems/actionpack-3.2.19/lib/action_dispatch/http/filter_parameters.rb:31 in "filtered_parameters" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/rails3/action_controller.rb:31 in "process_action" 
/gems/actionpack-3.2.19/lib/abstract_controller/base.rb:121 in "process" 
/gems/actionpack-3.2.19/lib/abstract_controller/rendering.rb:45 in "process" 
/gems/actionpack-3.2.19/lib/action_controller/metal.rb:203 in "dispatch" 
/gems/actionpack-3.2.19/lib/action_controller/metal/rack_delegation.rb:14 in "dispatch" 
/gems/actionpack-3.2.19/lib/action_controller/metal.rb:246 in "block in action" 
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:73 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:73 in "dispatch" 
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:36 in "call" 
/gems/journey-1.0.4/lib/journey/router.rb:68 in "block in call" 
/gems/journey-1.0.4/lib/journey/router.rb:56 in "each" 
/gems/journey-1.0.4/lib/journey/router.rb:56 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/routing/route_set.rb:608 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/rack/error_collector.rb:50 in "traced_call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:55 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/rack/agent_hooks.rb:26 in "traced_call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:55 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/rack/browser_monitoring.rb:23 in "traced_call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:55 in "call" 
/gems/oink-0.10.1/lib/oink/middleware.rb:17 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/warden-1.2.3/lib/warden/manager.rb:35 in "block in call" 
/gems/warden-1.2.3/lib/warden/manager.rb:34 in "catch" 
/gems/warden-1.2.3/lib/warden/manager.rb:34 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/best_standards_support.rb:17 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/etag.rb:23 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/conditionalget.rb:25 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/head.rb:14 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/params_parser.rb:21 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/flash.rb:242 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:210 in "context" 
/gems/rack-1.4.5/lib/rack/session/abstract/id.rb:205 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/cookies.rb:341 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/activerecord-3.2.19/lib/active_record/query_cache.rb:64 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/activerecord-3.2.19/lib/active_record/connection_adapters/abstract/connection_pool.rb:479 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/callbacks.rb:28 in "block in call" 
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:405 in "_run__3807242266783802268__call__1942732928323145202__callbacks" 
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:405 in "__run_callback" 
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:385 in "_run_call_callbacks" 
/gems/activesupport-3.2.19/lib/active_support/callbacks.rb:81 in "run_callbacks" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/callbacks.rb:27 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/sendfile.rb:102 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/remote_ip.rb:31 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/debug_exceptions.rb:16 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/show_exceptions.rb:56 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/railties-3.2.19/lib/rails/rack/logger.rb:32 in "call_app" 
/gems/railties-3.2.19/lib/rails/rack/logger.rb:18 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/actionpack-3.2.19/lib/action_dispatch/middleware/request_id.rb:22 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/methodoverride.rb:21 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/runtime.rb:17 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/activesupport-3.2.19/lib/active_support/cache/strategy/local_cache.rb:72 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-1.4.5/lib/rack/lock.rb:15 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/rack-cache-1.2/lib/rack/cache/context.rb:136 in "forward" 
/gems/rack-cache-1.2/lib/rack/cache/context.rb:245 in "fetch" 
/gems/rack-cache-1.2/lib/rack/cache/context.rb:185 in "lookup" 
/gems/rack-cache-1.2/lib/rack/cache/context.rb:66 in "call!" 
/gems/rack-cache-1.2/lib/rack/cache/context.rb:51 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/railties-3.2.19/lib/rails/engine.rb:484 in "call" 
/gems/railties-3.2.19/lib/rails/application.rb:231 in "call" 
/gems/railties-3.2.19/lib/rails/railtie/configurable.rb:30 in "method_missing" 
/gems/rack-1.4.5/lib/rack/urlmap.rb:64 in "block in call" 
/gems/rack-1.4.5/lib/rack/urlmap.rb:49 in "each" 
/gems/rack-1.4.5/lib/rack/urlmap.rb:49 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/gems/sass-3.2.19/lib/sass/plugin/rack.rb:54 in "call" 
/gems/newrelic_rpm-3.9.3.241/lib/new_relic/agent/instrumentation/middleware_tracing.rb:57 in "call" 
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/rack/thread_handler_extension.rb:74 in "process_request" 
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/request_handler/thread_handler.rb:141 in "accept_and_process_next_request" 
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/request_handler/thread_handler.rb:109 in "main_loop" 
/var/www/.rvm/gems/ruby-2.1.2/gems/passenger-4.0.45/lib/phusion_passenger/request_handler.rb:448 in "block (3 levels) in start_threads" 

Trước một nâng cấp lên JQuery 1.11 từ 1.5 (!), lỗi này đã không xảy ra (hoặc nếu nó đã làm, nó rất hiếm). Chúng tôi cho đến nay đã không thể tái tạo lỗi này trên máy chủ dàn dựng của chúng tôi hoặc trong môi trường phát triển. Một người hỗ trợ đã nhìn thấy nó trên sản xuất một lần (tôi đã thử nhiều lần), nhưng không thể nhân rộng trên dàn dựng (mà là cùng một môi trường như sản xuất, mặc dù nguồn lực nhỏ hơn). Di chuyển JQuery không hiển thị bất kỳ vấn đề nào khi nó chạy và, như tôi đã nói, có vẻ như nó hoạt động với hầu hết người dùng; trong các phiên gỡ lỗi không có gì có vẻ không ổn. Không có mô hình rõ ràng cho hệ điều hành/nền tảng hoặc trình duyệt (cố gắng để tái sản xuất trên một số và các bản ghi không chỉ ra một mô hình mặc dù khó để sàng lọc đủ để chắc chắn). URL chính có liên quan là dành cho # thao tác mới trên trình điều khiển biểu mẫu. Chúng tôi có một số biểu mẫu khác trong nền tảng và chúng không hiển thị bất kỳ vấn đề nào.

Vì tôi không thể tạo lại, nên không thể trích đoạn mã - tôi không biết phải xác định điều gì.

giải thích của tôi về các lỗi cho đến nay (dựa trên dòng đầu tiên trong ngăn xếp dump) là một trong ba điều:

  1. nội dung là khác đúng, nhưng không hoàn toàn được hình thành bằng cách nào đó,
  2. nội dung vẫn chưa được hình thành cho thấy một lỗi Ruby (mặc dù lẽ JS)
  3. mã hóa xấu (tôi đang sử dụng form_for trong Ruby và thậm chí ném vào "multipart: true" để được rõ ràng)

Tôi thấy Rack đã xử lý vấn đề EOFError nhiều phần có liên quan trong 4.x, nhưng chúng tôi đang chạy Rails 3.2.19 khóa chúng tôi ở phiên bản cũ hơn và nâng cấp lên Rails 4.x là không thực tế tại thời điểm này. Là một thử nghiệm, tôi đã thử JQuery trở lại thấp đến 1,7 nhưng dường như không thay đổi hành vi (bất kỳ cũ hơn và tôi phải thả các bản cập nhật mã cần thiết cho JQuery 1.8+).

Vì mã JQuery cần thay đổi đối với JS của chúng tôi, tôi nghi ngờ tôi đã bỏ lỡ một số thay đổi JS cần thiết, nhưng không có gì có vẻ không ổn. Cũng có một số thay đổi CSS gần đó, nhưng tôi không thấy nó có thể ảnh hưởng đến mọi thứ như thế nào (vì mọi thứ đã đi qua trong các môi trường thử nghiệm khác nhau của chúng tôi, những thay đổi khác cũng được đưa vào triển khai).

Tôi đã nghi ngờ các vấn đề JS chủ yếu, nhưng một số bài kiểm tra giới hạn về sản xuất (tôi phải cẩn thận trên máy chủ trực tiếp để không thể quá hung hăng) không hiển thị bất kỳ manh mối hoặc bất kỳ lỗi nào có liên quan .

Là nền tảng, tôi có trải nghiệm một năm với Ruby và JS (mặc dù nhiều năm trên các nền tảng lập trình khác) nên hoàn toàn có thể đó là điều cơ bản mà tôi không quen thuộc.

Tôi đang gặp khó khăn khi thu hẹp vị trí cần tập trung để xử lý vấn đề này. Bất kỳ lời khuyên nào để chẩn đoán hoặc giải quyết?

UPDATE (10/11/14) Tôi khỉ vá Rack::Multipart::Parser.fast_forward_to_first_boundary (cảm ơn, Isaac Betesh!) Để thêm dấu vết đăng nhập và khẳng định rằng nội dung đã thông qua để phân tích cú pháp là rỗng khi nó đạt đến mà chức năng (có nghĩa là, StringIO được gọi bởi @env['rack.input'] trong khi phân tích cú pháp nhiều lần sẽ không trả về dữ liệu nào). Lý thuyết của tôi bây giờ là nó sai mong đợi dữ liệu đa khi không có. Một lần nữa, điều này chỉ xảy ra liên tục và phân tích tốt cho nhiều lời gọi khác của cùng một trang này. Kể từ khi chúng tôi đang chạy theo Hành khách 4.x và Nginx, tôi đã không loại trừ một vấn đề đệm.

+1

Nếu bạn không thể nâng cấp Rack vì Rails 3 đang khóa phiên bản, hãy thử khỉ vá lớp cá nhân trong tệp ở đầu ngăn xếp dấu vết. Bạn có thể không tìm ra lý do tại sao điều này xảy ra nhưng nó vẫn có thể là giải pháp hiệu quả. –

+0

Tôi có thể, nhưng lo lắng về việc thay đổi mã chứng khoán trên sản xuất (vì tôi thực sự không thể kiểm tra nó trước mà không cần sao chép), có thể cho tôi manh mối mặc dù nó thay đổi hành vi và nếu nó giúp người dùng dễ dàng hơn, nó có thể có giá trị. Cảm ơn. – rdnewman

+0

Ngoài ra, cùng một mã này có vẻ tốt trước khi nâng cấp lên Jquery và các thay đổi liên quan đến JS (cho các thay đổi khác trong cùng triển khai một câu lệnh xác thực này). Vì vậy, sự thay đổi trong Jquery sẽ phải bằng cách nào đó kích hoạt sự thất bại trong Rack, vì vậy là lý do khác của tôi để do dự. – rdnewman

Trả lời

8

Điều này cuối cùng đã được giải quyết và tôi đăng những gì đã xảy ra trong trường hợp nó hữu ích cho người khác.

Tóm tắt Mã gốc chứa ajaxSubmit (thông qua plugin jquery.form) trong JS đã gửi biểu mẫu (dưới dạng POST) với mã hóa đa dạng/biểu mẫu (cho đến nay rất tốt). Bộ điều khiển đường ray xử lý việc gửi đã xử lý dữ liệu bình thường và sau đó chuyển hướng sang một href thứ hai (dưới dạng GET). Trình duyệt (có lẽ vẫn đang xử lý thông qua plugin jquery.form trước khi quay lại trình xử lý gọi lại là success) đã nhận được chuyển hướng và giữ lại loại mã hóa đa hình thức/dữ liệu. Khi rack nhận được GET với mã hóa multipart vẫn được chỉ định, nó balked vì không có dữ liệu multipart để phân tích cú pháp.

Xin lỗi, phần lớn điều này không phải là bằng chứng trong OP của tôi. Và nó không rõ ràng với tôi tại sao điều này làm việc theo một phiên bản cũ hơn của JQuery và các plugin JQuery.form hoặc tại sao nó đôi khi thành công dưới JQuery mới/JQuery.form.

Giải pháp Tái cấu trúc bộ điều khiển để không còn chuyển hướng, mà trả lại URL (làm văn bản hiển thị) cho trình xử lý gọi lại success của ajaxSubmit gốc. Trình xử lý success bây giờ thực hiện AJAX GET trên URL được trả về, do đó rời khỏi luồng công việc còn nguyên vẹn nhưng tránh bất kỳ mã hóa nhiều phần tử nào trên yêu cầu GET.

tl; dr:

Trước khi mã đã bao giờ thay đổi, chúng tôi đã có một con đường liên quan đến Jquery.hình thức mà đi một cái gì đó như thế này (mã ví dụ không có nghĩa là để được thực thi, nhưng cũng giống như một minh hoạ):

của Ruby xem (trong HAML cho hình thức được gửi):

= form_for @someObject, html: {:multipart => true, :class => "someformclass"} do |f| 
    = f.error_messages 
    = hidden_field_tag :submitted, true 
    =# some more fields 
    %p.submits 
    = f.submit "Submit", class: "submit" 

của Ruby khiển:

class OurController < ApplicationController 
    layout false 
    before_filter :authenticate_user! 

    # some other actions 

    def create 
    # some processing 

    someObject.save 
    redirect_to new_feedback_path, :method => :get, :notice => "notice text", status: 303 
    end 

    # some other actions 
end 

JS:

$(document).on('click', '.someformclass .submit', function() { 
    ... 
    $(this).parents('form').ajaxSubmit({  // uses jquery.form 
    ... 
    beforeSubmit: function(someargs) { 
     ... blah blah 
    }, 
    success: function(responseText) { 
     // ... code to display flash message 
     if (typeof(window.history.pushState) == 'function') { 
     window.history.pushState('html', 'sometext', $.cookie('current_url')); 
     matchFiltersClass(window.location.pathname); 
     } else { 
     window.location.hash = '#!' + $.cookie('current_path'); 
     matchFiltersClass($.cookie('current_path')); 
     } 
     $('#main_content').html(responseText); 
    } 
    }); 
    return false; 
}); 

này được refactored như sau (một lần nữa, chỉ là một minh họa):

của Ruby xem (trong HAML cho hình thức được gửi): không thay đổi

của Ruby khiển:

class OurController < ApplicationController 
    layout false 
    before_filter :authenticate_user! 

    # some other actions 

    def create 
    # some processing 

    someObject.save 
    flash[:notice] = 'notice text' # NEW LINE 
    render text: new_feedback path, status: accepted #CHANGED LINE 
    end 

    # some other actions 
end 

JS: (! Cảm ơn, Dan Axtman)

$(document).on('click', '.someformclass .submit', function() { 
    ... 
    $(this).parents('form').ajaxSubmit({  // uses jquery.form 
    ... 
    beforeSubmit: function(someargs) { 
     ... blah blah 
    }, 
    success: function(responseText) { 
     // ... code to display flash message 
     $.get(responseText, function(data) {  // NEW LINE 
     if (typeof(window.history.pushState) == 'function') { 
      window.history.pushState('html', 'sometext', $.cookie('current_url')); 
      matchFiltersClass(window.location.pathname); 
     } else { 
      window.location.hash = '#!' + $.cookie('current_path'); 
      matchFiltersClass($.cookie('current_path')); 
     } 
     $('#main_content').html(responseText); 
     });  // NEW LINE 
    } 
    }); 
    return false; 
}); 

Giải pháp này đã được tìm thấy với một số giúp đỡ với một nhà phát triển địa phương và không phải không có một số tiền hợp lý của thời gian trong khai thác gỗ khỉ vá trong rack (nhờ, Isaac Betesh!). Ít nhất tôi đã học được điều gì đó về Rack và khỉ vá trong quá trình ...

Các vấn đề liên quan