Puma هو خادم HTTP 1.1 بسيط وسريع ومتعدد الخيوط ومتوازي للغاية لتطبيقات Ruby/Rack .
Puma هو خادم لتطبيقات HTTP التي تعمل بنظام Rack والمكتوبة بلغة Ruby. إنها:
تم تصميم Puma في الأصل كخادم لـ Rubinius، ويعمل أيضًا بشكل جيد مع Ruby (MRI) وJRuby.
في التصوير بالرنين المغناطيسي، يوجد قفل VM عالمي (GVL) يضمن أن مؤشر ترابط واحد فقط يمكنه تشغيل كود روبي في المرة الواحدة. ولكن إذا كنت تقوم بالكثير من عمليات حظر الإدخال والإخراج (مثل مكالمات HTTP إلى واجهات برمجة التطبيقات الخارجية مثل Twitter)، فإن Puma لا تزال تعمل على تحسين إنتاجية التصوير بالرنين المغناطيسي من خلال السماح بانتظار إجراء الإدخال والإخراج بالتوازي. لا تحتوي تطبيقات Ruby المتوازية حقًا (TruffleRuby، JRuby) على هذا القيد.
$ gem install puma
$ puma
بدون وسيطات، ستبحث puma عن ملف Rackup (.ru) في دليل العمل المسمى config.ru
.
ستقوم Puma بالتثبيت/الترجمة مع دعم مقابس SSL، على افتراض أن ملفات تطوير OpenSSL مثبتة على النظام.
إذا لم يكن النظام مثبتًا عليه ملفات تطوير OpenSSL، فسوف تقوم Puma بتثبيت/تجميع، لكنها لن تسمح باتصالات SSL.
Puma هو الخادم الافتراضي لـ Rails، المضمن في ملف Gemfile الذي تم إنشاؤه.
ابدأ خادمك باستخدام أمر rails
:
$ rails server
لا تتوفر العديد من خيارات التكوين وميزات Puma عند استخدام rails server
. يوصى باستخدام الملف القابل للتنفيذ الخاص بـ Puma بدلاً من ذلك:
$ bundle exec puma
يمكنك تشغيل تطبيق Sinatra الخاص بك مع Puma من سطر الأوامر مثل هذا:
$ ruby app.rb -s Puma
من أجل تكوين Puma فعليًا باستخدام ملف التكوين، مثل puma.rb
، تحتاج إلى استخدام ملف puma
القابل للتنفيذ. للقيام بذلك، يجب عليك إضافة ملف Rackup إلى تطبيق Sinatra الخاص بك:
# config.ru
require './app'
run Sinatra :: Application
يمكنك بعد ذلك بدء تطبيقك باستخدام:
$ bundle exec puma
توفر بوما العديد من الخيارات. راجع puma -h
(أو puma --help
) للحصول على قائمة كاملة بخيارات CLI، أو راجع Puma::DSL
أو dsl.rb.
يمكنك أيضًا العثور على العديد من أمثلة التكوين كجزء من مجموعة الاختبار.
لأغراض تصحيح الأخطاء، يمكنك تعيين متغير البيئة PUMA_LOG_CONFIG
بقيمة وستتم طباعة التكوين المحمل كجزء من عملية التمهيد.
يستخدم بوما تجمع الخيوط. يمكنك تعيين الحد الأدنى والحد الأقصى لعدد سلاسل الرسائل المتوفرة في التجمع باستخدام العلامة -t
(أو --threads
) :
$ puma -t 8:32
ستقوم Puma تلقائيًا بقياس عدد المواضيع، من الحد الأدنى حتى الحد الأقصى، بناءً على مقدار حركة المرور الموجودة. الافتراضي الحالي هو 0:16
وفي التصوير بالرنين المغناطيسي هو 0:5
. لا تتردد في التجربة، ولكن احرص على عدم تعيين الحد الأقصى لعدد الخيوط على عدد كبير، حيث قد تستنفد الموارد الموجودة على النظام (أو تتسبب في التنافس على قفل الجهاز الظاهري العالمي، عند استخدام التصوير بالرنين المغناطيسي).
انتبه إلى أن Puma تقوم أيضًا بإنشاء سلاسل رسائل من تلقاء نفسها لأغراض داخلية (مثل التعامل مع العملاء البطيئين). لذا، حتى لو حددت -t 1:1، توقع إنشاء حوالي 7 سلاسل في تطبيقك.
تقدم Puma أيضًا "الوضع المجمع". fork
الوضع المجمعة للعمال من عملية رئيسية. لا يزال لدى كل عملية فرعية مجموعة مؤشرات ترابط خاصة بها. يمكنك ضبط عدد العمال باستخدام العلامة -w
(أو --workers
) :
$ puma -t 8:32 -w 3
أو باستخدام متغير البيئة WEB_CONCURRENCY
:
$ WEB_CONCURRENCY=3 puma -t 8:32
لاحظ أن سلاسل الرسائل لا تزال تستخدم في الوضع المجمع، وإعداد إشارة مؤشر الترابط -t
يكون لكل عامل، لذلك -w 2 -t 16:16
سوف ينتج 32 مؤشر ترابط إجمالاً، مع 16 في كل عملية عاملة.
إذا تم تعيين متغير البيئة WEB_CONCURRENCY
على "auto"
وكانت جوهرة concurrent-ruby
متاحة في تطبيقك، فستقوم Puma بتعيين عدد العمليات المنفذة على نتيجة المعالجات المتاحة.
لإجراء مناقشة متعمقة حول المفاضلات بين إعدادات سلسلة المحادثات وعدد العمليات، راجع مستنداتنا.
في الوضع المجمع، يمكن لـ Puma "التحميل المسبق" لتطبيقك. يؤدي هذا إلى تحميل كل كود التطبيق قبل التفرع. يؤدي التحميل المسبق إلى تقليل إجمالي استخدام الذاكرة لتطبيقك من خلال ميزة نظام التشغيل التي تسمى النسخ عند الكتابة.
إذا تم تعيين متغير البيئة WEB_CONCURRENCY
على قيمة > 1 (ولم يتم تحديد --prune-bundler
)، فسيتم تمكين التحميل المسبق افتراضيًا. بخلاف ذلك، يمكنك استخدام علامة --preload
من سطر الأوامر:
$ puma -w 3 --preload
أو، إذا كنت تستخدم ملف تكوين، فيمكنك استخدام preload_app!
طريقة:
# config/puma.rb
workers 3
preload_app!
لا يمكن استخدام التحميل المسبق مع إعادة التشغيل المرحلية، نظرًا لأن إعادة التشغيل المرحلية تقتل العمال وتعيد تشغيلهم واحدًا تلو الآخر، ويقوم التحميل المسبق بنسخ رمز الرئيسي إلى العمال.
عند استخدام الوضع المجمع، يوفر تكوين DSL الخاص بـ Puma خطافات before_fork
و on_worker_boot
لتشغيل التعليمات البرمجية عند تشغيل شوكات العملية الرئيسية والعمال الفرعيين على التوالي.
يوصى باستخدام هذه الخطافات مع preload_app!
وإلا فإن الثوابت التي تم تحميلها بواسطة تطبيقك (مثل Rails
) لن تكون متاحة داخل الخطافات.
# config/puma.rb
before_fork do
# Add code to run inside the Puma master process before it forks a worker child.
end
on_worker_boot do
# Add code to run inside the Puma worker process after forking.
end
بالإضافة إلى ذلك، يوجد خطاف on_refork
يُستخدم فقط في وضع fork_worker
، عندما تقوم العملية الفرعية للعامل 0 بتفرع عامل حفيد:
on_refork do
# Used only when fork_worker mode is enabled. Add code to run inside the Puma worker 0
# child process before it forks a grandchild worker.
end
من المهم ملاحظة الاعتبارات التالية عندما تقوم روبي بتفرع عملية فرعية:
SocketError
و Errno::EPIPE
و EOFError
.ولذلك نوصي بما يلي:
before_fork
و on_refork
لفصل اتصالات مأخذ توصيل الوالدين عند التفرع، حتى لا يتم نسخها عن طريق الخطأ إلى العملية الفرعية.on_worker_boot
لإعادة تشغيل أي سلاسل رسائل خلفية على الطفل المتشعب. يوفر تكوين DSL الخاص بـ Puma خطافات دورة حياة العملية الرئيسية on_booted
و on_restart
و on_stopped
والتي يمكن استخدامها لتحديد كتل التعليمات البرمجية لتشغيلها في كل حدث:
# config/puma.rb
on_booted do
# Add code to run in the Puma master process after it boots,
# and also after a phased restart completes.
end
on_restart do
# Add code to run in the Puma master process when it receives
# a restart command but before it restarts.
end
on_stopped do
# Add code to run in the Puma master process when it receives
# a stop command but before it shuts down.
end
إذا واجه Puma خطأً خارج سياق التطبيق الخاص بك، فسوف يستجيب برسالة خطأ نصية بسيطة تبلغ 400/500 (راجع Puma::Server#lowlevel_error
أو server.rb). يمكنك تحديد سلوك مخصص لهذا السيناريو. على سبيل المثال، يمكنك الإبلاغ عن الخطأ إلى خدمة تتبع الأخطاء التابعة لجهة خارجية (في هذا المثال، شريط القوائم):
lowlevel_error_handler do | e , env , status |
if status == 400
message = "The server could not process the request due to an error, such as an incorrectly typed URL, malformed syntax, or a URL that contains illegal characters. n "
else
message = "An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact [email protected] n "
Rollbar . critical ( e )
end
[ status , { } , [ message ] ]
end
قم بربط Puma بمقبس يحتوي على العلامة -b
(أو --bind
) :
$ puma -b tcp://127.0.0.1:9292
لاستخدام مقبس UNIX بدلاً من TCP:
$ puma -b unix:///var/run/puma.sock
إذا كنت بحاجة إلى تغيير أذونات مقبس UNIX، فما عليك سوى إضافة معلمة umask:
$ puma -b 'unix:///var/run/puma.sock?umask=0111'
هل تحتاج إلى القليل من الأمان؟ استخدم مآخذ SSL:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
localhost
، لاستخدام التطوير): تدعم Puma جوهرة localhost
للشهادات الموقعة ذاتيًا. يعد هذا مفيدًا بشكل خاص إذا كنت تريد استخدام Puma مع SSL محليًا، وستعمل الشهادات الموقعة ذاتيًا مع حالة الاستخدام الخاصة بك. حاليًا، لا يمكن استخدام التكامل إلا في التصوير بالرنين المغناطيسي.
تقوم Puma تلقائيًا بتكوين SSL عند تحميل جوهرة localhost
في بيئة development
:
أضف الجوهرة إلى ملف Gemfile الخاص بك:
group ( :development ) do
gem 'localhost'
end
واطلب ذلك ضمنيًا باستخدام المجمع:
require "bundler"
Bundler . require ( :default , ENV [ "RACK_ENV" ] . to_sym )
بدلًا من ذلك، يمكنك طلب الجوهرة في ملف التكوين الخاص بك، إما config/puma/development.rb
أو config/puma.rb
أو تعيينها عبر خيار -C
cli:
require 'localhost'
# configuration methods (from Puma::DSL) as needed
بالإضافة إلى ذلك، يجب أن تستمع Puma إلى مقبس SSL:
$ puma -b ' ssl://localhost:9292 ' -C config/use_local_host.rb
# The following options allow you to reach Puma over HTTP as well:
$ puma -b ssl://localhost:9292 -b tcp://localhost:9393 -C config/use_local_host.rb
لاستخدام أو تجنب تشفير SSL محدد لـ TLSv1.2 والإصدارات الأقدم، استخدم خيارات ssl_cipher_filter
أو ssl_cipher_list
.
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&ssl_cipher_filter=!aNULL:AES+SHA'
$ puma -b 'ssl://127.0.0.1:9292?keystore=path_to_keystore&keystore-pass=keystore_password&ssl_cipher_list=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA'
لتكوين مجموعات تشفير TLSv1.3 المتاحة، استخدم خيار ssl_ciphersuites
(غير متوفر لـ JRuby).
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&ssl_ciphersuites=TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256'
راجع https://www.openssl.org/docs/man1.1.1/man1/ciphers.html للتعرف على تنسيق مرشح التشفير والقائمة الكاملة لمجموعات التشفير.
قم بتعطيل TLS v1 باستخدام خيار no_tlsv1
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
لتمكين علامات التحقق المقدمة من OpenSSL، استخدم verification_flags
(غير متوفرة لـ JRuby):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN'
يمكنك أيضًا تعيين علامات تحقق متعددة (من خلال فصلها بفاصلة):
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN,CRL_CHECK'
قائمة العلامات المتاحة: USE_CHECK_TIME
, CRL_CHECK
, CRL_CHECK_ALL
, IGNORE_CRITICAL
, X509_STRICT
, ALLOW_PROXY_CERTS
, POLICY_CHECK
, EXPLICIT_POLICY
, INHIBIT_ANY
, INHIBIT_MAP
, NOTIFY_POLICY
, EXTENDED_CRL_SUPPORT
، USE_DELTAS
، CHECK_SS_SIGNATURE
، TRUSTED_FIRST
، SUITEB_128_LOS_ONLY
، SUITEB_192_LOS
، SUITEB_128_LOS
، PARTIAL_CHAIN
، NO_ALT_CHAINS
، NO_CHECK_TIME
(انظر https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_hostflags.html#VERIFICATION-FLAGS).
لتمكين فك تشفير وقت التشغيل لمفتاح SSL مشفر (غير متوفر لـ JRuby)، استخدم key_password_command
:
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&key_password_command=/path/to/command.sh'
يجب أن يكون الأمر key_password_command
:
على سبيل المثال:
#! /bin/sh
echo " this is my password "
يمكن استخدام key_password_command
مع key
أو key_pem
. إذا لم يتم تشفير المفتاح، فلن يتم استدعاء الملف القابل للتنفيذ.
تحتوي Puma على تطبيق مدمج للحالة والتحكم يمكن استخدامه للاستعلام عن Puma والتحكم فيه.
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
سيبدأ Puma خادم التحكم على منفذ المضيف المحلي 9293. ستحتاج جميع الطلبات إلى خادم التحكم إلى تضمين رمز التحكم (في هذه الحالة، token=foo
) كمعلمة استعلام. وهذا يسمح بالمصادقة البسيطة. قم بمراجعة Puma::App::Status
أو Status.rb لمعرفة ما يتوفر في تطبيق الحالة.
يمكنك أيضًا التفاعل مع خادم التحكم عبر pumactl
. سيؤدي هذا الأمر إلى إعادة تشغيل Puma:
$ pumactl --control-url 'tcp://127.0.0.1:9293' --control-token foo restart
لرؤية قائمة خيارات pumactl
، استخدم pumactl --help
.
يمكنك أيضًا توفير ملف تكوين بالعلامة -C
(أو --config
):
$ puma -C /path/to/config
إذا لم يتم تحديد ملف تكوين، فستبحث Puma عن ملف تكوين على config/puma.rb
. إذا تم تحديد بيئة (عبر علامة --environment
أو من خلال متغيرات البيئة APP_ENV
أو RACK_ENV
أو RAILS_ENV
)، تبحث Puma عن ملف تكوين في config/puma/<environment_name>.rb
ثم ترجع إلى config/puma.rb
.
إذا كنت تريد منع Puma من البحث عن ملف التكوين في تلك المواقع، فقم بتضمين علامة --no-config
:
$ puma --no-config
# or
$ puma -C "-"
الآثار الجانبية الأخرى لإعداد البيئة هي ما إذا كان سيتم إظهار تتبعات المكدس (في development
أو test
)، ومن المحتمل أن يؤثر ضبط RACK_ENV على البرامج الوسيطة التي تبحث عن هذه القيمة لتغيير سلوكها. القيمة الافتراضية لـ puma RACK_ENV هي development
. يمكنك رؤية جميع قيم التكوين الافتراضية في Puma::Configuration#puma_default_options
أوconfig.rb.
قم بزيارة Puma::DSL
أو dsl.rb لرؤية جميع الخيارات المتاحة.
تتضمن Puma القدرة على إعادة تشغيل نفسها. عندما يكون متاحًا (التصوير بالرنين المغناطيسي، Rubinius، JRuby)، يقوم Puma بإجراء "إعادة تشغيل سريعة". هذه هي نفس الوظيفة المتوفرة في Unicorn و NGINX والتي تبقي مآخذ الخادم مفتوحة بين عمليات إعادة التشغيل. وهذا يضمن عدم إسقاط أي طلبات معلقة أثناء حدوث عملية إعادة التشغيل.
للمزيد، راجع وثائق إعادة التشغيل.
يستجيب بوما لعدة إشارات. يمكن العثور على دليل تفصيلي لاستخدام إشارات UNIX مع Puma في وثائق الإشارات.
بعض الأنظمة الأساسية لا تدعم جميع ميزات Puma.
بالنسبة لإصدارات التصوير بالرنين المغناطيسي 2.2.7 و2.2.8 و2.2.9 و2.2.10 و2.3.4 و2.4.1، قد ترى stream closed in another thread (IOError)
. قد يكون سبب ذلك خطأ روبي. يمكن إصلاحه بالجوهرة https://rubygems.org/gems/stopgap_13632:
if %w( 2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1 ) . include? RUBY_VERSION
begin
require 'stopgap_13632'
rescue LoadError
end
end
لدى Puma دعم لكابيسترانو بجوهرة خارجية.
بالإضافة إلى ذلك، تتمتع Puma بدعم للشيطان المضمن عبر جوهرة Puma-daemon Ruby. تستعيد الجوهرة خيار daemonize
الذي تمت إزالته من Puma بدءًا من الإصدار 5، ولكن فقط لـ MRI Ruby.
من الشائع استخدام أجهزة مراقبة العمليات مع Puma. توفر شاشات مراقبة العمليات الحديثة مثل systemd أو rc.d مراقبة مستمرة وإعادة تشغيل لزيادة الموثوقية في بيئات الإنتاج:
أدلة المجتمع:
ابحث عن تفاصيل المساهمة في دليل المساهمة.
Puma هي حقوق الطبع والنشر لشركة Evan Phoenix والمساهمين، ومرخصة بموجب ترخيص BSD 3-Clause. راجع ملف الترخيص المرفق للحصول على التفاصيل.