2010-09-08 33 views
22

Tôi đang cố gắng truyền dữ liệu văn bản (XML/JSON) từ ứng dụng Rack (1.2.1) của Ruby (1.9.1p378) Sinatra (1.0). Các giải pháp được đề xuất (ví dụ: Is there a way to flush html to the wire in Sinatra) dường như không hoạt động - máy chủ chỉ chặn khi tôi mang lại các thành phần của một số luồng vô hạn (ví dụ: từ %w(foo bar).cycle). Tôi đã thử các máy chủ webrickthin làm máy chủ.Truyền dữ liệu từ ứng dụng Sinatra/Rack

Bất kỳ đề xuất nào về việc thực hiện việc này? Tôi có nên sử dụng http://sinatra.rubyforge.org/api/classes/Sinatra/Streaming.html và nếu có thì tôi sẽ sử dụng nó như thế nào trong đơn đăng ký của mình?

Trả lời

19

Không hỗ trợ Webrick hoặc Thin trực tuyến theo cách đó. Bạn có thể thử Mongrel hoặc Unicorn. Nếu bạn muốn sử dụng Thin hoặc Rainbows !, bạn phải móc vào vòng kiện để đạt được trực tiếp:

require 'sinatra' 

class Stream 
    include EventMachine::Deferrable 
    def initialize 
    @counter = 0 
    end 

    def each(&block) 
    if @counter > 10 
     succeed 
    else 
     EM.next_tick do 
     yield counter 
     each(&block) 
     end 
    end 
    end 
end 

get '/' do 
    Stream.new 
end 

Gần đây tôi đã viết một thi EventSource theo cách đó:

require 'sinatra' 

class EventStream 
    include EventMachine::Deferrable 
    def each 
    count = 0 
    timer = EventMachine::PeriodicTimer.new(1) do 
     yield "data: #{count += 1}\n\n" 
    end 
    errback { timer.cancel } 
    end 
end 

get '/' do 
    EventMachine.next_tick do 
    request.env['async.callback'].call [ 
     200, {'Content-Type' => 'text/event-stream'}, 
     EventStream.new ] 
    end 
    [-1, {}, []] 
end 

Nếu bạn muốn sử dụng Webrick để phát trực tuyến: here là bản vá.

+2

Thin có lợi thế của việc có thể để trả lời các yêu cầu khác trong khi trực tuyến. –

+0

Xác nhận rằng nó hoạt động với Mongrel. Cảm ơn Konstantin! – yawn

5

Bạn chắc chắn nên xem qua giá có thể Goliath web server. Nó hỗ trợ streaming out-of-the-box. Tôi đang sử dụng nó cho một phong cách firehose streaming api.

Goliath là cả một máy chủ ứng dụng và một khung nhẹ thiết kế để đáp ứng các mục tiêu sau: đầy đủ xử lý không đồng bộ, middleware hỗ trợ, cấu hình đơn giản, cao hiệu suất, và có lẽ hầu hết quan trọng, có thể đọc được và duy trì mã số .

+0

Dự án rất thú vị! Cảm ơn gợi ý! – yawn

7

Như Colin đã đề cập, Goliath có thể truyền dữ liệu phản hồi, cũng như gửi đến (tải lên tệp lớn). Có một ví dụ trong repo để truyền dữ liệu cho khách hàng: https://github.com/postrank-labs/goliath/blob/master/examples/stream.rb

Thay vì hẹn giờ, bạn có thể dễ dàng kết nối bất kỳ luồng dữ liệu nào khác để đẩy dữ liệu đến máy khách. Ví dụ: bạn có thể kết nối hàng đợi AMQP hoặc bất kỳ hàng đợi thư nào khác trực tiếp với Goliath và để cho nó hoạt động như một giao diện HTTP cho dữ liệu đó.

+0

Có cộng đồng nào cho goliath ở đâu đó không? Toàn bộ dự án dường như khá dễ bị chảy máu và tôi không chắc chắn về một số thứ như hỗ trợ cho việc chunking và nhận dạng các yêu cầu gọi lại ... – yawn

+1

Danh sách gửi thư là một nơi tuyệt vời để bắt đầu: https: // groups. google.com/forum/#!forum/goliath-io - có một nhóm người thích xem nó. Một số ứng dụng thú vị hơn đang được xây dựng với Goliath là tiếc là không ở nơi công cộng, nhưng điều đó sẽ thay đổi theo thời gian. Đó là chảy máu cạnh. :-) – igrigorik

31

Bắt đầu với Sinatra 1.3, bạn cũng có thể sử dụng streaming API mới:

get '/evented' do 
    stream(:keep_open) do |out| 
    EventMachine::PeriodicTimer.new(1) { out << "#{Time.now}\n" } 
    end 
end 
+0

Konstantin - tính năng này có hoạt động với TẤT CẢ máy chủ web hay chỉ các máy chủ web như Thin? Tôi đang gặp sự cố khi theo dõi mã ví dụ cho API phát trực tiếp mới sử dụng máy chủ chuẩn như Hành khách ... – wchrisjohnson

+1

Chỉ với các máy chủ web có sự kiện, như Thin, Rainbows! hoặc Ebb - nhưng Puma đang lên kế hoạch hỗ trợ điều này. –

+0

Phát trực tuyến mà không cần ': keep_open' hoạt động trên tất cả các máy chủ, nhưng sẽ không phát trực tiếp trên tất cả (cụ thể là không phải trên Webrick). –

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