تشغيل وظائف متوازية متعددة في الخلفية باستخدام Rails
-
05-07-2019 - |
سؤال
في تطبيق Ruby on Rails الخاص بي، أحتاج إلى تنفيذ 50 مهمة خلفية بالتوازي.تقوم كل مهمة بإنشاء اتصال TCP بخادم مختلف، وتلقي بعض البيانات وتحديث كائن السجل النشط.
أعرف حلولًا مختلفة لأداء هذه المهمة ولكن أيًا منها بالتوازي.على سبيل المثال، يمكن أن يكون Late_job (DJ) حلاً رائعًا إذا كان بإمكانه تنفيذ جميع المهام بالتوازي.
أيه أفكار؟شكرًا.
المحلول
بعض الأفكار...
فقط لأنك تحتاج إلى قراءة 50 موقعًا وتريد بطبيعة الحال القيام ببعض الأعمال الموازية لا يعني أنك بحاجة إلى 50 عملية أو موضوع.تحتاج إلى تحقيق التوازن بين التباطؤ والنفقات العامة.ماذا عن وجود 10 أو 20 عملية لكل منها قراءة عدد قليل من المواقع؟
اعتمادًا على نوع روبي الذي تستخدمه، كن حذرًا بشأن الخيوط الخضراء، فقد لا تحصل على النتيجة الموازية التي تريدها
قد ترغب في هيكلتها مثل inetd العكسي من جانب العميل والاستخدام
connect_nonblock
وIO.select
للحصول على الاتصالات المتوازية التي تريدها من خلال جعل جميع الخوادم تستجيب بشكل متوازٍ.لا تحتاج حقًا إلى معالجة متوازية للنتائج، كل ما تحتاجه هو التوافق مع جميع الخوادم بالتوازي، لأن هذا هو المكان الذي يوجد فيه زمن الوصول حقًا.
لذلك، شيء من هذا القبيل من مكتبة المقبس...قم بتوسيع نطاقه ليشمل العديد من الاتصالات المتميزة...
require 'socket'
include Socket::Constants
socket = Socket.new(AF_INET, SOCK_STREAM, 0)
sockaddr = Socket.sockaddr_in(80, 'www.google.com')
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EINPROGRESS
IO.select(nil, [socket])
begin
socket.connect_nonblock(sockaddr)
rescue Errno::EISCONN
end
end
socket.write("GET / HTTP/1.0\r\n\r\n")
# here perhaps insert IO.select. You may not need multiple threads OR multiple
# processes with this technique, but if you do insert them here
results = socket.read
نصائح أخرى
ومن الممكن فعلا لتشغيل العمال delayed_job المتعدد.
http://github.com/collectiveidea/delayed_job :
# Runs two workers in separate processes.
$ RAILS_ENV=production script/delayed_job -n 2 start
$ RAILS_ENV=production script/delayed_job stop
وهكذا، من الناحية النظرية، يمكن تنفيذ فقط:
$ RAILS_ENV=production script/delayed_job -n 50 start
وهذا سوف تفرخ 50 عمليات، ولكن أنا لست متأكدا ما إذا كان من شأنه أن يكون الموصى بها اعتمادا على موارد النظام الذي تقوم بتشغيل هذه جرا.
وخيار بديل يتمثل في استخدام المواضيع . ببساطة تفرخ موضوع جديد لكل من فرص العمل الخاص بك.
وشيء واحد أن يتحمل هو العقل مع هذا الأسلوب هو أن ActiveRecord
لا موضوع آمنة. يمكنك ان تجعل من موضوع آمن باستخدام الإعداد التالي:
ActiveRecord::Base.allow_concurrency = true
ومنذ كنت تعمل مع القضبان، وأنصح لك استخدام delayed_job للقيام بذلك بدلا من تقسيم قبالة في المواضيع أو الشوك. السبب هو - التعامل مع مهلة والاشياء عند المستعرض ينتظر يمكن أن يكون الألم الحقيقي. هناك طريقتان يمكنك اتخاذها مع DJ
والأول هو - تفرخ 50+ العمال. اعتمادا على البيئة الخاصة بك وهذا قد يكون ذاكرة جميلة حل ثقيل، ولكنه يعمل كبيرة. ثم عندما تحتاج إلى تشغيل عملك، فقط للتأكد من إنشاء 50 وظيفة فريدة من نوعها. إذا كان هناك الكثير من سخام الذاكرة وتريد أن تفعل الأمور على هذا النحو، وجعل بيئة منفصلة يتم جردت أسفل، وتحديدا لعمالك.
والطريقة الثانية هي إنشاء وظيفة واحدة يستخدم الضفيرة :: موضوع لتشغيل 50 طلبات TCP المتزامنة الخاص بك. يمكنك معرفة المزيد حول هذا الموضوع هنا: http://curl-multi.rubyforge.org/ وبهذه الطريقة، يمكن أن يكون لديك معالج واحد خلفية تشغيل جميع طلبات TCP الخاص بك في نفس الوقت.