Subprojects Behind OpenResty

API7.ai

September 12, 2022

OpenResty (NGINX + Lua)

كيفية استخراج كود Lua من ملف nginx.conf والحفاظ عليه قابل للقراءة والصيانة؟ الحل بسيط جدًا. دعونا نرى كيفية تنفيذ ذلك باستخدام OpenResty.

أولاً، قم بإنشاء دليل يسمى lua. ثم سنضع جميع ملفات .lua فيه.

$ mkdir lua

$ cat lua/hello.lua
ngx.say("hello, world")

ثانيًا، استخدم content_by_lua_block لاستبدال content_by_lua_file في ملف nginx.conf.

pid logs/nginx.pid;
events {
  worker_connections 1024;
}

http {
  server {
    listen 8080;
    location / {
      content_by_lua_file lua/hello.lua;
      }
    }
  }

ثالثًا، أعد تشغيل خدمات OpenResty، وستكون العملية قد اكتملت!

$ sudo kill -HUP `cat logs/nginx.pid`

باستخدام content_by_lua_file، يمكننا تحديث ملف Lua مباشرة بدلاً من تحديث nginx.conf. ولكن هناك بعض الأسئلة:

  1. نستخدم مسارًا نسبيًا في قسم content_by_lua_file lua/hello.lua. كيف يجد OpenResty ملف Lua الفعلي؟
  2. بعد تعديل أكواد Lua، نحتاج إلى إعادة تشغيل OpenResty لتفعيل التغييرات، هل هناك طريقة لتصحيح الأخطاء بكفاءة؟
  3. كيف يمكن إضافة الدليل الذي يحتوي على ملفات Lua إلى مسار البحث الخاص بـ OpenResty؟

أشجعك على التفكير في هذه الأسئلة، حيث يمكن الإجابة عليها جميعًا في الوثائق الرسمية. لهذا السبب أؤكد دائمًا على أهمية الوثائق.

بالنسبة للسؤال الأول، إذا تم إعطاء مسار نسبي، فعند بدء OpenResty، سيتم إضافة البادئة -p PATH من معلمات بدء تشغيل OpenResty ودمج المسار النسبي في مسار مطلق. بهذه الطريقة، يمكن لـ OpenResty العثور على ملف Lua بسلاسة.

المشكلة الثانية هي أن كود Lua يتم تحميله عند الطلب الأول ويتم تخزينه مؤقتًا بشكل افتراضي. لذا في كل مرة تقوم بتغيير ملف Lua المصدر، يجب عليك إعادة تحميل OpenResty لتفعيل التغييرات. يمكنك تجنب إعادة التحميل عن طريق إيقاف تشغيل lua_code_cache في nginx.conf. ومع ذلك، من الضروري ملاحظة أن هذه الطريقة يمكن استخدامها مؤقتًا فقط للتطوير والتصحيح. لذا إذا كنت تقوم بالنشر في بيئة إنتاجية، يجب عليك تمكين التخزين المؤقت. وإلا، سيكون له تأثير كبير على الأداء.

بالنسبة للسؤال الأخير، يوفر OpenResty توجيه lua_package_path لتعيين مسار البحث لوحدات Lua. على سبيل المثال، يمكننا تعيين lua_package_path إلى $prefix/lua/?.lua;;:

  • $prefix هو -p PATH في معلمات بدء التشغيل.
  • /lua/?.lua يشير إلى جميع الملفات في دليل Lua ذات اللاحقة .lua.
  • الفاصلة المنقوطة الأخيرة تمثل مسار البحث المدمج.

هيكل الدليل بعد التثبيت

بعد فهم برنامج hello world الأول، دعنا نتعمق ونرى كيف يبدو هيكل الدليل الخاص بـ OpenResty بعد تثبيته وما هي الملفات الموجودة فيه.

نقوم أولاً بتمرير الخيار -V لمعرفة مكان OpenResty. بالنسبة للنتيجة التالية، قمت بحذف العديد من معلمات تجميع الوحدات، والتي سنضيفها لاحقًا:

$ openresty -V

nginx version: openresty/1.13.6.2
built by clang 10.0.0 (clang-1000.10.44.4)
built with OpenSSL 1.1.0h  27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/openresty/1.13.6.2/nginx ...

أستخدم brew لتثبيت OpenResty على جهاز Mac الخاص بي. المسار هو /usr/local/Cellar/openresty/1.13.6.2/nginx، وقد يختلف عن بيئتك. يحتوي هذا المسار على أدلة bin، luajit، lualib، nginx، pod وغيرها. من الضروري فهم معنى هذه المجلدات حتى نتمكن من تعلم OpenResty بشكل أفضل. لذا دعونا نلقي نظرة عليها واحدة تلو الأخرى.

أولاً، الدليل المهم bin.

$ ll /usr/local/Cellar/openresty/1.13.6.2/bin

total 320
-r-xr-xr-x  1 ming  admin    19K  3 27 12:54 md2pod.pl
-r-xr-xr-x  1 ming  admin    15K  3 27 12:54 nginx-xml2pod
lrwxr-xr-x  1 ming  admin    19B  3 27 12:54 openresty -> ../nginx/sbin/nginx
-r-xr-xr-x  1 ming  admin    62K  3 27 12:54 opm
-r-xr-xr-x  1 ming  admin    29K  3 27 12:54 resty
-r-xr-xr-x  1 ming  admin    15K  3 27 12:54 restydoc
-r-xr-xr-x  1 ming  admin   8.3K  3 27 12:54 restydoc-index

يحتوي هذا على كل من OpenResty CLI resty الذي ذكرناه في القسم السابق والملف التنفيذي الأساسي، openresty، وهو في الواقع رابط رمزي لـ nginx. أما الأدوات الأخرى في الدليل، فلا شك أنها، مثل resty، جميعها نصوص Perl.

من بينها، opm هو أداة إدارة الحزم التي تسمح لنا بإدارة جميع أنواع الحزم الخارجية، والتي سيتم تغطيتها في قسم لاحق؛ و restydoc، صديق قديم من القسم الأول، هو عارض الوثائق المقدم من OpenResty، والذي يسمح لنا بعرض وثائق OpenResty و NGINX.

$ restydoc -s ngx.say
$ restydoc -s proxy_pass

المثالان أعلاه يستفسران عن واجهة برمجة تطبيقات OpenResty وأوامر NGINX على التوالي. restydoc هي أداة مفيدة جدًا لمهندسي الخوادم للتركيز على التطوير.

بعد تصفح دليل bin، دعنا ننتقل إلى دليل pod.

أولاً، دعنا نؤكد أن pod هنا لا علاقة له بمفهوم pod في Kubernetes. بدلاً من ذلك، pod هي لغة ترميز تستخدم في Perl لكتابة وثائق وحدات Perl. ويحتوي هذا الدليل على وثائق OpenResty، NGINX، lua-resty-*، و LuaJIT، والتي يتم ربطها جميعًا مع restydoc المذكور سابقًا.

التالي هما الدليلان المألوفان NGINX و luajit. هذان الدليلان سهلان الفهم. يحتويان بشكل أساسي على الملفات التنفيذية والتبعيات الخاصة بـ NGINX و LuaJIT وهما حجر الزاوية في OpenResty. يقول الكثيرون أن OpenResty يعتمد على Lua، ولكن هذا غير دقيق. كما نرى أعلاه، OpenResty يعتمد في الواقع على LuaJIT.

في الواقع، في المراحل المبكرة، كان OpenResty يأتي مع كل من Lua و LuaJIT، ويمكننا تحديد ما إذا كنا نريد استخدام Lua أو LuaJIT عن طريق خيارات التجميع. ولكن Lua يتم إهمالها الآن، ويتم دعم LuaJIT فقط بسبب أدائه الأعلى.

أخيرًا، دعنا نلقي نظرة على دليل lualib. يحتوي على مكتبات Lua المستخدمة في OpenResty، وتنقسم بشكل أساسي إلى دليلين: ngx و resty.

  • يحتوي دليل ngx على أكواد Lua من مشروع lua-resty-core الرسمي، والذي يعتمد على إعادة تنفيذ واجهة برمجة تطبيقات OpenResty باستخدام FFI. سأشرح في فصل خاص لماذا نحتاج إلى إعادة تنفيذها.
  • يحتوي دليل resty على أكواد Lua من مشاريع lua-resty-* المختلفة، والتي سنتطرق إليها لاحقًا.

بعد فهم هيكل الدليل، دعنا نلقي نظرة على المشاريع الفرعية لـ OpenResty.

نظرة عامة على مشروع OpenResty

عند الحديث عن OpenResty، سنفكر في lua-nginx-module. نعم، هذه الوحدة النمطية C لـ NGINX هي بالفعل جوهر OpenResty، لكنها لا تعادل OpenResty. يطلق العديد من المهندسين على OpenResty اسم ngx + lua، وهو أيضًا ما يتم استخدامه في الكتب والمؤتمرات التقنية. هذا ليس دقيقًا ولا يتم تشجيعه من قبل مجتمع OpenResty.

دعني أتحدث عن السبب وما هي المشاريع الأخرى المرتبطة بجانب lua-nginx-module في OpenResty.

افتح الصفحة الرئيسية لمشروع OpenResty على GitHub، وسترى أن OpenResty يحتوي على 68 مشروعًا عامًا، والتي تنقسم بشكل عام إلى الفئات السبع التالية. دعني أقدمها باختصار حتى تحصل على انطباع أولي وتتعلمها بسرعة.

وحدات NGINX C

تسمية مشاريع OpenResty موحدة، وتلك المسماة *-nginx-module هي وحدات NGINX C.

يوجد أكثر من 20 وحدة C في OpenResty، ويمكننا العثور عليها باستخدام openresty -V، والذي استخدمناه في بداية هذا القسم.

$ openresty -V

nginx version: openresty/1.13.6.2
built by clang 10.0.0 (clang-1000.10.44.4)
built with OpenSSL 1.1.0h  27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/local/Cellar/openresty/1.13.6.2/nginx --with-cc-opt='-O2 -I/usr/local/include -I/usr/local/opt/pcre/include -I/usr/local/opt/openresty-openssl/include' --add-module=../ngx_devel_kit-0.3.0 --add-module=../echo-nginx-module-0.61 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2rc3 --add-module=../set-misc-nginx-module-0.32 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.08 --add-module=../srcache-nginx-module-0.31 --add-module=../ngx_lua-0.10.13 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.33 --add-module=../array-var-nginx-module-0.05 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.7 --add-module=../ngx_stream_lua-0.0.5 --with-ld-opt='-Wl,-rpath,/usr/local/Cellar/openresty/1.13.6.2/luajit/lib -L/usr/local/lib -L/usr/local/opt/pcre/lib -L/usr/local/opt/openresty-openssl/lib' --pid-path=/usr/local/var/run/openresty.pid --lock-path=/usr/local/var/run/openresty.lock --conf-path=/usr/local/etc/openresty/nginx.conf --http-log-path=/usr/local/var/log/nginx/access.log --error-log-path=/usr/local/var/log/nginx/error.log --with-pcre-jit --with-ipv6 --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_auth_request_module --with-http_secure_link_module --with-http_random_index_module --with-http_geoip_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-threads --with-dtrace-probes --with-stream --with-stream_ssl_module --with-http_ssl_module

هنا --add-module= يتبعها وحدة C لـ OpenResty. الأساسية منها هي lua-nginx-module و stream-lua-nginx-module، الأولى للتعامل مع حركة الطبقة السابعة والثانية لقيادة حركة الطبقة الرابعة.

بعض هذه الوحدات النمطية C تتطلب اهتمامًا خاصًا ولا يوصى بها، على الرغم من أنها يتم تجميعها في OpenResty بشكل افتراضي. على سبيل المثال، redis2-nginx-module، redis-nginx-module، و memc-nginx-module تستخدم للتفاعل مع Redis و Memcached. كانت هذه المكتبات C موصى بها من قبل OpenResty في المراحل المبكرة، ولكن تم استبدالها بـ lua-resty-redis و lua-resty-memcached بعد إضافة ميزة cosocket، ويتم صيانتها بشكل غير نشط.

لن تقوم OpenResty بتطوير المزيد من مكتبات NGINX C لاحقًا، ولكنها ستركز على مكتبة Lua القائمة على cosocket، وهي المستقبل.

مكتبات lua-resty-*

يحتوي مستودع OpenResty الرسمي على 18 مكتبة lua-resty-*، بما في ذلك Redis، MySQL، Memcached، WebSocket، DNS، التحكم في حركة المرور، معالجة السلاسل، التخزين المؤقت داخل العملية، وغيرها من المكتبات القياسية. بالإضافة إلى المكتبات الرسمية التي تأتي معها، هناك المزيد من المكتبات الخارجية. وهي ضرورية، وسنخصص المزيد من الوقت لهذه المكتبات في القسم التالي.

فرع LuaJIT الذي يتم صيانته ذاتيًا

تحتفظ OpenResty بفرع LuaJIT الخاص بها بالإضافة إلى تصحيح OpenSSL الخاص بها. في عام 2015، أعلن مؤلف LuaJIT Mike Pall عن تقاعده للعثور على مشرف جديد لـ LuaJIT، لكن Mike لم يجد مشرفًا مناسبًا. وهو الآن يقوم بشكل أساسي بصيانة إصلاح الأخطاء، وقد تم تعليق تطوير الميزات الجديدة، لذا تحتفظ OpenResty بفرع LuaJIT الخاص بها.

مقارنة بـ Lua، تضيف LuaJIT الكثير من الوظائف الأساسية والفريدة، ولكن ليس الكثير من المهندسين يعرفون عنها، لذا فهي مهارات شبه مخفية سأقدمها لاحقًا.

إطار الاختبار

إطار اختبار OpenResty هو test-nginx، والذي تم تطويره أيضًا في Perl، وكما يمكنك أن ترى من الاسم، فهو مصمم خصيصًا لاختبار المشاريع المتعلقة بـ NGINX. جميع حالات الاختبار الرسمية لـ OpenResty لوحدات C ومكتبة lua-resty يتم تشغيلها بواسطة test-nginx. هذا نظام أقوى بكثير ومستقل، على عكس الأطر الشائعة القائمة على التأكيدات.

بعض مساهمي OpenResty لم يفهموا هذا الإطار الاختباري أيضًا ويقدمون أحيانًا طلبات سحب تحتوي على أكواد C و Lua معقدة ولكنهم غالبًا ما يخافون من فكرة كتابة حالات اختبار مقابلة. لذا إذا كنت قد نظرت إلى بعض حالات الاختبار في دليل /t لمشروع OpenResty وما زلت في حيرة، فلا تشك في نفسك بعد. معظم الناس كذلك.

بالإضافة إلى test-nginx، يقوم مشروع mockeagain بمحاكاة شبكة بطيئة، مما يسمح للبرامج بالقراءة والكتابة بايت واحد في كل مرة. هذه أداة مفيدة جدًا لخوادم الويب.

أدوات التصحيح

لقد بذل مشروع OpenResty الكثير من الجهد في كيفية تصحيح الأكواد بشكل علمي وديناميكي.

المشروعان openresty-systemtap-toolkit و stapxx هما أداتان تعتمدان على systemtap، وهي أداة تصحيح وتتبع ديناميكية. أكبر ميزة لاستخدام systemtap هي أنها تمكن من التحليل الحيوي دون أي تدخل في التطبيق الهدف.

على سبيل المثال، systemtap تشبه الذهاب إلى المستشفى وإجراء فحص CT، غير مؤلمة وغير محسوسة. والأفضل من ذلك، يمكن لـ systemtap إنشاء رسوم بيانية مرئية لتحليل الأداء، والتي سأصفها لاحقًا، لذا إليك رسم بياني لإعطائك فكرة.

رسم بياني متعلق بـ OpenResty

التغليف

نصوص تغليف OpenResty في أنظمة التشغيل المختلفة (مثل CentOS، Ubuntu، macOS، إلخ) مكتوبة يدويًا لتحقيق تحكم أفضل. عندما قدمنا هيكل الدليل بعد التثبيت، قمنا بتغطية هذه المشاريع المتعلقة بالتغليف: openresty-packaging و home-brew. إذا كنت مهتمًا بذلك، يمكنك تعلمه بنفسك، ولن أكرره هنا.

أدوات الهندسة

بالإضافة إلى هذه المشاريع الكبيرة، لدى OpenResty عدة أدوات هندسية مخفية إلى حد كبير.

على سبيل المثال، openresty-devel-utils هي مجموعة أدوات لتطوير OpenResty و NGINX. بالطبع، تم تطويرها أيضًا في Perl، ومعظم الأدوات غير موثقة. ولكن لمطوري OpenResty، هذه الأدوات مفيدة جدًا. سأبدأ باختيار عدد قليل منها وتقديمها باختصار.

  • lj-releng هي أداة فحص بسيطة وفعالة لأكواد LuaJIT، تشبه luacheck، ويمكنها العثور على مشاكل محتملة مع المتغيرات العامة.
  • reindex، والتي تعني إعادة بناء الفهرس، هي أداة لتنسيق حالات اختبار test-nginx، وإعادة ترتيب أرقام حالات الاختبار، وإزالة المسافات البيضاء الزائدة. reindex هي واحدة من الأدوات التي يستخدمها مطورو OpenResty يوميًا.
  • opsboy تستخدم للقيام بنشرات تلقائية. يتم استخدامها لنشر وقيادة اختبارات الانحدار التي تقوم بها OpenResty على مجموعات AWS EC2 قبل كل إصدار. لمزيد من المعلومات التفصيلية، يمكنك الرجوع إلى الوثائق الرسمية. opsboy هي لغة DSL تم تنفيذها في Perl. يحب مؤلفو OpenResty إنشاء لغات DSL مختلفة لحل المشاكل.

الخلاصة

اليوم، تعلمنا بشكل أساسي هيكل الدليل الخاص بـ OpenResty بعد التثبيت وبعض المشاريع الفرعية وراءه. بعد تعلم محتوى اليوم، آمل أن تتمكن من التعرف أكثر على مشاريع OpenResty. لقد تجاوزت OpenResty نطاق موازنة التحميل والوكيل العكسي لـ NGINX ووضعت نظامها البيئي الخاص. في المرة القادمة سنتحدث عن هذا بالتفصيل.

قراءة إضافية