ruby-on-rails - وحدة تحكم واحدة تقدم باستخدام وجهات نظر وحدة تحكم أخرى




view controller render (4)

لدي كيستيونكونترولر لدي الآن أنوثكستيونكونترولر مع الإجراءات التي ينبغي أن تجعل باستخدام قوالب وجزئيات في التطبيق / وجهات النظر / السؤال / هل هذا ممكن؟ يبدو أنه ينبغي أن يكون.

لقد حاولت

render :template => "question/answer"

ولكن answer.html.erb يتضمن جزئية وأحصل على أخطاء مثل

"نموذج مفقود other_question / _my_partial.erb في مسار عرض"

لذلك هناك طريقة لإخبار القضبان "علاج أنوذركستيونكونترولر كما لو كونستروكونترولر والبحث عن وجهات النظر وجزئيات في التطبيق / وجهات النظر / السؤال"؟ أو سوف تضطر إلى إنشاء التطبيق / وجهات النظر / another_question - الأمر الذي سوف يسبب الازدواجية (وهذا لا يمكن أن يكون الطريق القضبان).

شكر


Answers

يمكنك تحقيق ذلك مع:

render 'question/answer'

يجب أن يعمل تقديم النموذج فعليا

 render :template => "question/answer"

المشكلة التي تواجهها هي من جزئية تبحث في المكان الخطأ. الإصلاح بسيط، مجرد جعل جزئياتك المطلقة في أي قوالب المشتركة. على سبيل المثال، يجب أن يكون السؤال / answer.html.erb

<%= render :partial => 'question/some_partial' %>

بدلا من المعتاد

<%= render :partial => 'some_partial' %> 


أدعوك لقراءة سلسلة Jesse Storimer لا أحد يفهم GIL قد يساعدك على فهم أفضل لبعض الداخلية MRI.

لقد وجدت أيضا Pragmatic التزامن مع روبي ، الأمر الذي يلفت الانتباه. لديها بعض الأمثلة للاختبار في وقت واحد.

تحرير: بالإضافة إلى ذلك يمكن أن أوصي بالمادة إزالة config.threadsafe! قد لا تكون ذات صلة بـ Rails 4 ، ولكنها تشرح خيارات التكوين ، والتي يمكن استخدام أحدها للسماح بالتزامن.

دعونا نناقش الجواب على سؤالك.

يمكن أن يكون لديك عدة خيوط (باستخدام التصوير بالرنين المغناطيسي) ، حتى مع بوما. يضمن GIL أن مؤشر ترابط واحد فقط نشط في كل مرة ، وهذا هو القيد الذي يميزه المطورون على أنه مقيد (بسبب عدم التنفيذ المتوازي الحقيقي). ضع في اعتبارك أن GIL لا تضمن سلامة الخيط. هذا لا يعني أن المواضيع الأخرى ليست قيد التشغيل ، بل هي في انتظار دورهم. يمكنهم التداخل (يمكن أن تساعد المقالات في فهم أفضل).

اسمحوا لي أن أوضح بعض المصطلحات: عملية عامل ، موضوع. تعمل عملية في مساحة ذاكرة منفصلة ويمكن أن تخدم عدة خيوط. يتم تشغيل خيوط العملية نفسها في مساحة ذاكرة مشتركة ، وهي العملية الخاصة بها. مع مؤشرات الترابط فإننا نعني مؤشرات روبي في هذا السياق ، وليس مؤشرات الترابط CPU.

في ما يتعلق بتكوين سؤالك وريبو GitHub الذي شاركته ، أعتقد أن التكوين المناسب (استخدمت Puma) هو إعداد 4 عمال و 1 إلى 40 موضوعًا. الفكرة هي أن عامل واحد يخدم علامة تبويب واحدة. كل علامة تبويب ترسل ما يصل إلى 10 طلبات.

اذا هيا بنا نبدأ:

أنا أعمل على أوبونتو على جهاز ظاهري. لذا قمت أولاً بتمكين 4 نوى في إعداد الآلة الافتراضية (وبعض الإعدادات الأخرى التي اعتقدت أنها قد تساعد). يمكنني التحقق من هذا على جهازي. لذلك ذهبت مع ذلك.

Linux command --> lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                4
On-line CPU(s) list:   0-3
Thread(s) per core:    1
Core(s) per socket:    4
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 69
Stepping:              1
CPU MHz:               2306.141
BogoMIPS:              4612.28
L1d cache:             32K
L1d cache:             32K
L2d cache:             6144K
NUMA node0 CPU(s):     0-3

استخدمت مشروع GitHub المشترك وعدّلته قليلاً. لقد قمت بإنشاء ملف تكوين Puma يسمى puma.rb (وضعه في دليل config ) مع المحتوى التالي:

workers Integer(ENV['WEB_CONCURRENCY'] || 1)
threads_count = Integer(ENV['MAX_THREADS'] || 1)
threads 1, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
  #ActiveRecord::Base.establish_connection
end

افتراضيا Puma بدأ مع 1 عامل و 1 موضوع. يمكنك استخدام متغيرات البيئة لتعديل هذه المعلمات. فعلت كذلك:

export MAX_THREADS=40
export WEB_CONCURRENCY=4

لبدء بوما مع هذا التكوين كتبت

bundle exec puma -C config/puma.rb

في دليل تطبيق Rails.

لقد فتحت المتصفح بأربعة علامات تبويب لاستدعاء عنوان URL للتطبيق.

بدأ الطلب الأول في حوالي الساعة 15:45:05 وكان آخر طلب حوالي الساعة 15:49. هذا هو الوقت المنقضي من 4 دقائق و 39 ثانية. كما يمكنك مشاهدة معرف الطلب في ترتيب غير مصنف في ملف السجل. (انظر أدناه)

تنام كل مكالمة API في مشروع GitHub لمدة 15 ثانية. لدينا أربع علامات تبويب ، تحتوي كل منها على 10 مكالمات API. هذا يجعل الحد الأقصى للوقت المنقضي من 600 ثانية ، أي 10 دقيقة (في وضع تسلسلي صارم).

وستكون النتيجة المثالية من الناحية النظرية متوازية وكل الوقت المنقضي ليس بعيداً عن 15 ثانية ، لكنني لم أتوقع ذلك على الإطلاق. لم أكن متأكداً مما نتوقعه كنتيجة بالضبط ، لكني كنت لا أزال متفاجئاً (مع الأخذ بعين الاعتبار أني ركضت على آلة افتراضية وأن التصوير بالرنين المغناطيسي مقيد بواسطة GIL وبعض العوامل الأخرى). كان الوقت المنقضي من هذا الاختبار أقل من نصف الحد الأقصى للوقت المنقضي (في الوضع التسلسلي الصارم) ، قلصنا النتيجة إلى أقل من النصف.

EDIT اقرأ المزيد حول Rack :: Lock الذي يلف كتفًا حول كل طلب (المقالة الثالثة أعلاه). لقد وجدت الخيار config.allow_concurrency = true ليكون config.allow_concurrency = true زمنيًا. كان التحذير قليلاً لزيادة تجمع الاتصال (على الرغم من أن الطلب لم يكن الاستعلام عن قاعدة البيانات التي يتعين تعيينها وفقا لذلك) ؛ عدد مؤشرات الترابط القصوى هو افتراضي جيد. 40 في هذه الحالة.

اختبرت التطبيق باستخدام jRuby وكان الوقت المنقضي الفعلي 2 دقيقة ، مع allow_concurrency = true.

اختبرت التطبيق مع التصوير بالرنين المغناطيسي وكان الوقت المنقضي الفعلي 1 دقيقة و 47 ثانية ، مع allow_concurrency = true. كانت هذه مفاجأة كبيرة بالنسبة لي. هذا ما فاجأني حقا ، لأنني توقعت أن يكون التصوير بالرنين المغناطيسي أبطأ من JRuby. لم يكن. هذا يجعلني أتساءل عن مناقشة واسعة النطاق حول الاختلافات في السرعة بين التصوير بالرنين المغناطيسي وجربي.

مشاهدة الردود على علامات التبويب المختلفة هي "أكثر عشوائية" الآن. يحدث أن تكتمل علامة التبويب 3 أو 4 قبل علامة التبويب 1 ، التي طلبتها أولاً.

أعتقد أنه بسبب عدم وجود ظروف سباق ، يبدو أن الاختبار جيد. ومع ذلك ، لست متأكدًا من النتائج الواسعة للتطبيق إذا قمت بتعيين config.allow_concurrency = true في تطبيق حقيقي.

لا تتردد في التحقق من ذلك واسمحوا لي أن أعرف أي تعليقات قد يكون لدى القراء. لا يزال لدي استنساخ على الجهاز الخاص بي. أخبرني إن كنت مهتم.

للإجابة على أسئلتك بالترتيب:

  • أعتقد أن المثال الخاص بك صالح من خلال النتيجة. للتوافق ومع ذلك ، فمن الأفضل اختبار الموارد المشتركة (على سبيل المثال في المقالة الثانية).
  • في ما يتعلق ببياناتك ، كما هو مذكور في بداية هذه الإجابة ، يكون التصوير بالرنين المغناطيسي متعدد الخيوط ، لكنه مقيد بواسطة GIL إلى خيط نشط واحد في كل مرة. هذا يثير السؤال: مع التصوير بالرنين المغناطيسي ليس من الأفضل اختبار مع المزيد من العمليات وأقل المواضيع؟ لا أعلم حقًا أن التخمين الأول سيكون بالأحرى لا فرق أو لا. ربما يمكن لأحد أن يلقي الضوء على هذا.
  • المثال الخاص بك على ما يرام على ما أعتقد. فقط بحاجة إلى بعض التعديلات الطفيفة.

الملحق

سجل التطبيق ملف القضبان:

**config.allow_concurrency = false (by default)**
-> Ideally 1 worker per core, each worker servers up to 10 threads.

[3045] Puma starting in cluster mode...
[3045] * Version 2.11.2 (ruby 2.1.5-p273), codename: Intrepid Squirrel
[3045] * Min threads: 1, max threads: 40
[3045] * Environment: development
[3045] * Process workers: 4
[3045] * Preloading application
[3045] * Listening on tcp://0.0.0.0:3000
[3045] Use Ctrl-C to stop
[3045] - Worker 0 (pid: 3075) booted, phase: 0
[3045] - Worker 1 (pid: 3080) booted, phase: 0
[3045] - Worker 2 (pid: 3087) booted, phase: 0
[3045] - Worker 3 (pid: 3098) booted, phase: 0
Started GET "/assets/angular-ui-router/release/angular-ui-router.js?body=1" for 127.0.0.1 at 2015-05-11 15:45:05 +0800
...
...
...
Processing by ApplicationController#api_call as JSON
  Parameters: {"t"=>"15?id=9"}
Completed 200 OK in 15002ms (Views: 0.2ms | ActiveRecord: 0.0ms)
[3075] 127.0.0.1 - - [11/May/2015:15:49:44 +0800] "GET /api_call.json?t=15?id=9 HTTP/1.1" 304 - 60.0230
**config.allow_concurrency = true**
-> Ideally 1 worker per core, each worker servers up to 10 threads.

[22802] Puma starting in cluster mode...
[22802] * Version 2.11.2 (ruby 2.2.0-p0), codename: Intrepid Squirrel
[22802] * Min threads: 1, max threads: 40
[22802] * Environment: development
[22802] * Process workers: 4
[22802] * Preloading application
[22802] * Listening on tcp://0.0.0.0:3000
[22802] Use Ctrl-C to stop
[22802] - Worker 0 (pid: 22832) booted, phase: 0
[22802] - Worker 1 (pid: 22835) booted, phase: 0
[22802] - Worker 3 (pid: 22852) booted, phase: 0
[22802] - Worker 2 (pid: 22843) booted, phase: 0
Started GET "/" for 127.0.0.1 at 2015-05-13 17:58:20 +0800
Processing by ApplicationController#index as HTML
  Rendered application/index.html.erb within layouts/application (3.6ms)
Completed 200 OK in 216ms (Views: 200.0ms | ActiveRecord: 0.0ms)
[22832] 127.0.0.1 - - [13/May/2015:17:58:20 +0800] "GET / HTTP/1.1" 200 - 0.8190
...
...
...
Completed 200 OK in 15003ms (Views: 0.1ms | ActiveRecord: 0.0ms)
[22852] 127.0.0.1 - - [13/May/2015:18:00:07 +0800] "GET /api_call.json?t=15?id=10 HTTP/1.1" 304 - 15.0103
**config.allow_concurrency = true (by default)**
-> Ideally each thread serves a request.

Puma starting in single mode...
* Version 2.11.2 (jruby 2.2.2), codename: Intrepid Squirrel
* Min threads: 1, max threads: 40
* Environment: development
NOTE: ActiveRecord 4.2 is not (yet) fully supported by AR-JDBC, please help us finish 4.2 support - check http://bit.ly/jruby-42 for starters
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
Started GET "/" for 127.0.0.1 at 2015-05-13 18:23:04 +0800
Processing by ApplicationController#index as HTML
  Rendered application/index.html.erb within layouts/application (35.0ms)
...
...
...
Completed 200 OK in 15020ms (Views: 0.7ms | ActiveRecord: 0.0ms)
127.0.0.1 - - [13/May/2015:18:25:19 +0800] "GET /api_call.json?t=15?id=9 HTTP/1.1" 304 - 15.0640




ruby-on-rails view controller render