2011-01-10 31 views
6

Tôi đã dành vài ngày để tìm một số ví dụ không phải là echo-server cho eventmachine, nhưng dường như không có bất kỳ sự kiện nào. Hãy nói rằng tôi muốn viết một phần server chấp nhận một tập tin và viết nó vào một Tempfile:Cách viết các tập tin (lớn) với Ruby Eventmachine

require 'rubygems' 
require 'tempfile' 
require 'eventmachine' 

module ExampleServer 

    def receive_data(data) 
    f = Tempfile.new('random') 
    f.write(data) 
    ensure 
    f.close 
    end 

end 

EventMachine::run { 
    EventMachine::start_server "127.0.0.1", 8081, ExampleServer 
    puts 'running example server on 8081' 
} 

Viết đến tập tin sẽ chặn các lò phản ứng, nhưng tôi không nhận được như thế nào để làm điều đó 'Eventmachine phong cách'. Tôi có phải đọc dữ liệu trong các khối và ghi từng đoạn vào đĩa trong khối Em.next_tick không?

Nhờ sự giúp đỡ Andreas

Trả lời

1

Từ docs, có vẻ như bạn chỉ cần attach file (mặc dù như bạn chỉ ra, có thể không có giá trị, có vẻ như tùy chọn là sử dụng File.write/ie blocking ...) và send_data.

Mặc dù tôi nghĩ rằng bạn không thể trộn chặn/non-blocking IO với EM :(

Với nguồn dữ liệu là một ổ cắm, tôi đoán rằng sẽ được xử lý bởi EventMachine.

Có lẽ một câu hỏi cho google group ...

~ chris

+0

Chris, cảm ơn câu trả lời của bạn. [Câu trả lời này] (http://stackoverflow.com/questions/2749503/what-is-the-best-way-to-read-files-in-an-eventmachine-based-app) bởi tmm1 xung đột với những gì tài liệu nói (hoặc tôi hiểu lầm). Về cơ bản tôi đang cố gắng để làm một chuyển tập tin rất đơn giản (Đọc từ một ổ cắm và ghi nó vào đĩa) ... – Andreas

0

này rất giống với What is the best way to read files in an EventMachine-based app? (nhưng tôi muốn biết làm thế nào để đọc các tập tin một cách hiệu quả). có vẻ như không được bất kỳ non-blocking tập API, vì vậy th tốt nhất bạn có thể làm là viết các cụm ngắn với next_tick hoặc trì hoãn việc viết (với defer) để nó chạy trong một chuỗi riêng biệt (nhưng tôi không biết giải pháp đó hoạt động như thế nào).

1

Rất tiếc, các tệp không phản hồi tốt với các giao diện được chọn. Nếu bạn cần một cái gì đó hiệu quả hơn IO # viết (không chắc), thì bạn có thể sử dụng EIO.

EIO sẽ thực sự chỉ bỏ nhẹ lò phản ứng và cung cấp cho bạn một chút đệm. Nếu độ trễ cụ thể là một vấn đề, hoặc bạn có đĩa thực sự chậm, điều đó có thể hữu ích. Trong hầu hết các trường hợp khác, nó có lẽ chỉ là một loạt các nỗ lực cho lợi thế nhỏ.

3

Hai câu trả lời:

Câu trả lời lười biếng: chỉ sử dụng tính năng chặn ghi. EM đã truyền cho bạn các khối dữ liệu rời rạc, không phải một chuỗi khổng lồ. Vì vậy, triển khai ví dụ của bạn có thể hơi lệch. Bạn có chắc chắn muốn tạo một tempfile mới cho mỗi đoạn duy nhất mà EM đưa cho bạn không? Tuy nhiên, tôi sẽ tiếp tục giả định rằng mã mẫu của bạn đang hoạt động như dự định. Phải thừa nhận rằng, cách tiếp cận lười biếng phụ thuộc vào thiết bị bạn đang viết, nhưng cố gắng ghi đồng thời một số luồng lớn vào đĩa tại cùng một điểm sẽ là một nút cổ chai lớn và bạn sẽ mất lợi thế khi có một sự kiện dựa trên máy chủ anyway. Bạn sẽ chỉ kết thúc với tung hứng đĩa tìm kiếm tất cả các nơi, hiệu suất IO sẽ giảm mạnh, và như vậy sẽ hiệu suất máy chủ của bạn. Xử lý nhiều thứ cùng một lúc là ổn với RAM, nhưng một khi bạn bắt đầu giao dịch với các thiết bị khối và lập lịch trình IO, bạn sẽ gặp phải tình trạng tắc nghẽn hiệu suất bất kể bạn đang làm gì.

Tuy nhiên, tôi đoán bạn có thể muốn thực hiện một số ghi lâu vào đĩa cùng một lúc mà bạn muốn đáp ứng độ trễ thấp cho các yêu cầu nặng khác không phải IO. Vì vậy, có lẽ câu trả lời hay:

Sử dụng defer.

require 'rubygems' 
require 'tempfile' 
require 'eventmachine' 

module ExampleServer 

    def receive_data(data) 
    operation = proc do 
     begin 
     f = Tempfile.new('random') 
     f.write(data) 
     ensure 
     f.close 
     end 
    end 

    callback = proc do 
     puts "I wrote a file!" 
    end 

    EM.defer(operation, callback) 
    end 

end 

EventMachine::run { 
    EventMachine::start_server "127.0.0.1", 8081, ExampleServer 
    puts 'running example server on 8081' 
} 

Có, điều này không sử dụng luồng. Nó thực sự không phải là xấu trong trường hợp này: bạn không phải lo lắng về việc đồng bộ hóa giữa các chủ đề, bởi vì EM là tốt đẹp, đủ để xử lý này cho bạn. Nếu bạn cần đáp ứng, hãy sử dụng gọi lại, sẽ được thực thi trong luồng lò phản ứng chính khi chuỗi công nhân hoàn thành. Ngoài ra, GIL là một cái gì đó của một vấn đề không cho trường hợp này, kể từ khi bạn đang đối phó với IO chặn ở đây, và không cố gắng để đạt được đồng thời CPU. Nhưng nếu bạn có ý định viết tất cả mọi thứ vào cùng một tệp, bạn sẽ phải cẩn thận với việc trì hoãn, vì vấn đề đồng bộ hóa sẽ phát sinh khi các chuỗi của bạn có khả năng cố ghi vào cùng một tệp cùng một lúc.

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