IO

2010-03-03 21 views
5

अवरुद्ध करने से बचने के लिए रूबी फाइबर का उपयोग कैसे करें मुझे S3 में निर्देशिका में फ़ाइलों का एक समूह अपलोड करने की आवश्यकता है। चूंकि अपलोड करने के लिए आवश्यक 90% से अधिक समय http अनुरोध समाप्त होने के लिए प्रतीक्षा कर रहा है, इसलिए मैं उनमें से कई को किसी भी तरह निष्पादित करना चाहता हूं।IO

क्या फाइबर मुझे इसके साथ मदद कर सकते हैं? उन्हें इस तरह की समस्या को हल करने के तरीके के रूप में वर्णित किया गया है, लेकिन मैं किसी भी तरह से सोच नहीं सकता कि मैं http कॉल ब्लॉक के दौरान कोई काम कर सकता हूं।

किसी भी तरह से मैं धागे के बिना इस समस्या को हल कर सकता हूं?

+0

तो, क्या कोई खुद फाइबर पर टिप्पणी कर सकता है? क्या मैं यह मानने में सही हूं कि फाइबर के पास "पृष्ठभूमि में सामान नहीं है" शक्तियां हैं? –

उत्तर

3

मैं 1.9 में फाइबर पर नहीं कर रहा हूँ, लेकिन 1.8.6 से नियमित रूप से धागे इस समस्या को हल कर सकते हैं। एक कतार http://ruby-doc.org/stdlib/libdoc/thread/rdoc/classes/Queue.html

प्रलेखन में उदाहरण को देखते हुए, आपका उपभोक्ता वह हिस्सा है जो अपलोड करता है। यह एक यूआरएल और एक फाइल 'उपभोग' करता है, और डेटा अपलोड करता है। निर्माता आपके प्रोग्राम का हिस्सा है जो काम करता रहता है और अपलोड करने के लिए नई फाइलें पाता है। फिर अपने 'निर्माता' कोड में

t = Thread.new do 
    upload_file(param1, param2) 
end 
@all_threads << t 

, पर बाद में (जो, याद है, की जरूरत नहीं है:

आप एक बार में एकाधिक फ़ाइलों को अपलोड करना चाहते हैं, बस एक नया थ्रेड प्रत्येक फ़ाइल के लिए लांच अपने स्वयं के सूत्र में हो, यह मुख्य कार्यक्रम हो सकता है):

@all_threads.each do |t| 
    t.join if t.alive? 
end 

कतार या तो एक @member_variable या एक $ वैश्विक हो सकता है।

+1

हालांकि मेरे फाइबर क्वेस्टिनो ने अनुत्तरित नहीं किया है –

1

आप धागे के बजाय इस के लिए अलग प्रक्रियाओं इस्तेमाल कर सकते हैं:

#!/usr/bin/env ruby 

$stderr.sync = true 

# Number of children to use for uploading 
MAX_CHILDREN = 5 

# Hash of PIDs for children that are working along with which file 
# they're working on. 
@child_pids = {} 

# Keep track of uploads that failed 
@failed_files = [] 

# Get the list of files to upload as arguments to the program 
@files = ARGV 


### Wait for a child to finish, adding the file to the list of those 
### that failed if the child indicates there was a problem. 
def wait_for_child 
    $stderr.puts " waiting for a child to finish..." 
    pid, status = Process.waitpid2(0) 
    file = @child_pids.delete(pid) 
    @failed_files << file unless status.success? 
end 


### Here's where you'd put the particulars of what gets uploaded and 
### how. I'm just sleeping for the file size in bytes * milliseconds 
### to simulate the upload, then returning either +true+ or +false+ 
### based on a random factor. 
def upload(file) 
    bytes = File.size(file) 
    sleep(bytes * 0.00001) 
    return rand(100) > 5 
end 


### Start a child uploading the specified +file+. 
def start_child(file) 
    if pid = Process.fork 
     $stderr.puts "%s: uploaded started by child %d" % [ file, pid ] 
     @child_pids[ pid ] = file 
    else 
     if upload(file) 
      $stderr.puts "%s: done." % [ file ] 
      exit 0 # success 
     else 
      $stderr.puts "%s: failed." % [ file ] 
      exit 255 
     end 
    end 
end 


until @files.empty? 

    # If there are already the maximum number of children running, wait 
    # for one to finish 
    wait_for_child() if @child_pids.length >= MAX_CHILDREN 

    # Start a new child working on the next file 
    start_child(@files.shift) 

end 


# Now we're just waiting on the final few uploads to finish 
wait_for_child() until @child_pids.empty? 

if @failed_files.empty? 
    exit 0 
else 
    $stderr.puts "Some files failed to upload:", 
     @failed_files.collect {|file| " #{file}" } 
    exit 255 
end 
2

अपने वास्तविक सवालों के जवाब देने के लिए:

रेशे बिल्कुल इस के साथ मेरी मदद कर सकते हैं?

नहीं वे नहीं कर सकते हैं। जोर्ग डब्ल्यू मिट्टाग explains why best

नहीं, आप फाइबर के साथ समवर्ती नहीं कर सकते हैं। फाइबर बस एक समेकन निर्माण नहीं हैं, वे नियंत्रण-प्रवाह निर्माण हैं, जैसे अपवाद। यह फाइबर का पूरा बिंदु है: वे समानांतर में कभी नहीं दौड़ते हैं, वे सहकारी होते हैं और वे निर्धारक होते हैं। फाइबर coroutines हैं। (वास्तव में, मैंने कभी नहीं समझा कि उन्हें कोरआउटिन क्यों नहीं कहा जाता है।)

रुबी में एकमात्र समेकन निर्माण थ्रेड है।

जब वह कहता है कि रुबी में एकमात्र समेकन संरचना थ्रेड है, याद रखें कि रुबी के कई अलग-अलग प्रत्यारोपण हैं और वे अपने थ्रेडिंग कार्यान्वयन में भिन्न होते हैं। इन मतभेदों के लिए एक बार फिर provides a great answer; और सही ढंग से निष्कर्ष निकाला है कि केवल जेआरबीई (जो मूल धागे में मैप किए गए जेवीएम धागे का उपयोग करता है) या आपकी प्रक्रिया को फोर्क करने का तरीका यह है कि आप वास्तविक समांतरता कैसे प्राप्त कर सकते हैं।

किसी भी तरह से मैं धागे के बिना इस समस्या को हल कर सकता हूं?

अपनी प्रक्रिया forking के अलावा, मैं भी है कि आप EventMachine और em-http-request की तरह कुछ पर देखने के सुझाव है। यह एक घटना संचालित, गैर-अवरुद्ध, reactor pattern आधारित HTTP क्लाइंट है जो असीमित है और धागे के ऊपरी हिस्से को नहीं लेता है।

+0

https://github.com/igrigorik/em-http-request/wiki/Parallel-Requests पर मल्टी इंटरफ़ेस के साथ सिंक्रनाइज़ करना देखें – Sairam

1

हारून पैटरसन (@tenderlove) लगभग ठीक तरह तुम्हारा वास्तव में वर्णन करने के लिए कारण है कि आप और कर सकते हैं चाहिए उपयोग धागे संगामिति अपनी स्थिति में प्राप्त करने के लिए एक उदाहरण का उपयोग करता है।

अधिकांश आई/ओ पुस्तकालय अब आईओ करते समय जीवीएल (ग्लोबल वीएम लॉक, या अधिकांश लोगों को जीआईएल या ग्लोबल इंटरप्रेटर लॉक के रूप में जानते हैं) को छोड़ने के लिए पर्याप्त स्मार्ट हैं। ऐसा करने के लिए सी में एक साधारण फ़ंक्शन कॉल है। आपको सी कोड के बारे में चिंता करने की ज़रूरत नहीं है, लेकिन आपके लिए इसका मतलब है कि उनके नमक के लायक अधिकांश आईओ पुस्तकालय जीवीएल जारी करने जा रहे हैं और अन्य धागे को निष्पादित करने की इजाजत दे रहे हैं जबकि आईओओ करने वाले धागे डेटा को वापस लौटने की प्रतीक्षा कर रहे हैं ।

यदि मैंने अभी जो कहा वह भ्रमित था, तो आपको इसके बारे में चिंता करने की आवश्यकता नहीं है। मुख्य बात यह है कि आपको यह जानने की जरूरत है कि यदि आप अपने HTTP अनुरोध (या उस मामले के लिए किसी अन्य I/O ऑपरेशन ... डेटाबेस, इंटरप्रोसेस संचार, जो कुछ भी) करने के लिए एक सभ्य पुस्तकालय का उपयोग कर रहे हैं, रूबी दुभाषिया (एमआरआई) दुभाषिया पर ताला जारी करने में सक्षम होने के लिए पर्याप्त स्मार्ट है और अन्य धागे को निष्पादित करने की इजाजत देता है जबकि एक धागा आईओ वापस लौटने की प्रतीक्षा करता है। यदि अगले धागे के पास अपना खुद का आईओ है, तो रूबी दुभाषिया वही काम करेगा (मानते हुए कि आईओ लाइब्रेरी रूबी की इस सुविधा का उपयोग करने के लिए बनाई गई है, जो मुझे विश्वास है कि ज्यादातर लोग इन दिनों हैं)।

तो, मैं जो कह रहा हूं उसे जोड़ने के लिए, धागे का उपयोग करें! आपको प्रदर्शन लाभ देखना चाहिए। यदि नहीं, तो यह देखने के लिए जांचें कि क्या आपकी http लाइब्रेरी सी में rb_thread_blocking_region() फ़ंक्शन का उपयोग कर रही है और यदि नहीं, तो पता लगाएं कि क्यों नहीं। शायद एक अच्छा कारण है, शायद आपको एक बेहतर पुस्तकालय का उपयोग करने पर विचार करने की आवश्यकता है।

हारून पैटरसन वीडियो के लिए लिंक यहाँ है: http://www.youtube.com/watch?v=kufXhNkm5WU

यह किसी दृश्य के लायक है, भले ही बस हंसते हुए के लिए, के रूप में हारून पैटरसन इंटरनेट पर सबसे मजेदार लोगों से एक है।

संबंधित मुद्दे