ماذا لو كان هناك تعارض بين قواعد Lua وتكوين NGINX؟
API7.ai
October 13, 2022
1. اسم ولغة OpenResty
س: لم أفهم حتى الآن أصل اسم OpenResty. أيضًا، OpenResty يعتمد على لغة Lua، فلماذا لا يتم استخدام لغات برمجة أخرى؟ على سبيل المثال، Shell، إلخ.
ج: بدأ OpenResty كمشروع شركة Yahoo!، والذي بدأ في أكتوبر 2007. تم أخذ اسم "Open" من OpenAPI، وتم أخذ "Resty" من rest API. في البداية، لم يكن OpenResty مخصصًا ليكون خادم ويب ومنصة تطوير، بل كان تطبيقًا مثل موقع ويب.
عندما تم إصدار OpenResty كمصدر مفتوح منذ أكثر من عقد، كانت هناك لغات قليلة جدًا تدعم التزامن غير الحاجز. وحتى الآن، لا تزال هناك لغات خلفية قليلة يمكنها تحقيق هذا المستوى من الأداء مع OpenResty. حاليًا، يستخدم المزيد من المطورين OpenResty في بوابات API وبرامج WAF الناعمة، وهو خيار طبيعي للمطورين.
أما بالنسبة للغة، فإن OpenResty ليس المشروع الوحيد الذي يدمج لغات تطوير أخرى في NGINX. على سبيل المثال، NGINX يدمج JS بشكل رسمي؛ هناك أيضًا مشاريع مفتوحة المصدر تدمج PHP في NGINX.
عادةً، يعتمد اختيار اللغة على عوامل مثل التزامن، JIT، وشعبية اللغة. بالنسبة لـ OpenResty، في عام 2007، كانت Lua بالفعل الخيار الأفضل. اتخذ OpenResty طريقًا ملتوًا باختيار perl بدلاً من Lua في إصداراته الأولى.
2. أولوية قواعد التكوين
س: عندما تتعارض قواعد Lua في OpenResty مع ملف تكوين NGINX، على سبيل المثال، تم تكوين قواعد rewrite في NGINX، وفي نفس الوقت يتم الرجوع إلى rewrite_by_lua_file، فما هي أولوية هاتين القاعدتين؟
ج: في الواقع، يعتمد ذلك على كيفية كتابة قاعدة rewrite في تكوين NGINX، سواء كانت break
أو last
، وهو ما تم ذكره في وثائق OpenResty الرسمية، مع نموذج كود:
location /foo {
rewrite ^ /bar;
rewrite_by_lua 'ngx.exit(503)';
}
location /bar {
...
}
في هذا التكوين لنموذج الكود، لن يتم تنفيذ ngx.exit(503)
.
ومع ذلك، إذا كتبتها كما يلي، سيتم تنفيذ ngx.exit(503)
.
rewrite ^ /bar break.
ومع ذلك، أنصح باستخدام OpenResty لإعادة الكتابة بدلاً من تكوين NGINX. لتجنب هذا الغموض، فإن الكثير من تكوينات NGINX غامضة نسبيًا وتتطلب منك الرجوع إلى الوثائق لفهمها بشكل متكرر.
3. لماذا يظهر خطأ في الكود الخاص بي؟
س: في دالة الجدول الخاصة بامتداد LuaJIT، لماذا يظهر الخطأ "module not found" عند تنفيذ السطور التالية بواسطة LuaJIT؟ أنا أستخدم LuaJIT الإصدار 2.0.5.
local new_tab = require('table.new')
# أو
require('table.clear')
# التنفيذ سيظهر خطأ
luajit: table_luajit.lua:1: module 'table.new' not found:
ج: هذان السطران من الكود يتطلبان LuaJIT الإصدار 2.1 ليعملا، وهو موثق هنا: https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218، يمكنك الاطلاع عليه.
كما ذكرنا، يجب أن تكون حذرًا بشكل خاص عند استخدام OpenResty، والذي يتطلب إصدارًا محددًا من LuaJIT ليعمل بشكل صحيح. يعتمد OpenResty على فرع LuaJIT 2.1 وقد أجرى العديد من التعديلات على LuaJIT.
لذلك، عند تشغيل الكود في هذا العمود، يرجى تذكر استخدام تثبيت OpenResty الرسمي. إذا قمت بإضافة lua-nginx-module
للتجميع فوق NGINX، ستواجه العديد من المشاكل!
4. الارتباك حول القيم الفارغة
س: بعض الأشياء المحيرة التي واجهتها هي ngx.null
، nil
، null
، و ""
. عندما بحثت على الويب، رأيت أن شخصًا قال إن null
هو تعريف لـ ngx.null
. عندما يعيد Redis نتيجة، غالبًا ما يتم تحديد ما إذا كانت النتيجة فارغة أم لا، فما هي القيمة التي يتم المقارنة بها عند إجراء هذا التحديد؟ هل هناك أي مشاكل أخرى تتعلق باستخدام هذه القيم؟ أنا لا أفهم هذه القيم بوضوح.
ج: قبل أن أجيب على سؤالك، أقترح عليك استخدام الكود التالي للعثور على مفتاح في lua-resty-redis
.
local res, err = red:get("dog")
هذا لأن nil في Lua لا يمكن استخدامه كقيمة في الجدول، لذا قام OpenResty بإدخال ngx.null
كقيمة فارغة في الجدول.
يمكننا طباعة ngx.null
ونوعه باستخدام الكود التالي.
# طباعة ngx.null
$ resty -e 'print(ngx.null)'
null
# طباعة النوع
$ resty -e 'print(type(ngx.null))'
userdata
كما ترى، ngx.null
ليس nil
، بل هو من نوع userdata
.
علاوة على ذلك، هناك العديد من القيم الفارغة في OpenResty، مثل cjson.null
، cdata``:NULL
وغيرها، والتي سأناقشها لاحقًا.
القيم الوحيدة الخاطئة في OpenResty هي nil
و false
. لذلك، عندما تكتب كودًا مثل if not res then
، يجب أن تكون حذرًا، ومن الأفضل تغييره إلى if res ~= nil and res ~= false then
، مع شيء مثل هذا، ومع تغطية حالات اختبارية مقابلة.
5. ما هي بوابة API بالضبط؟
س: ما هي بوابة API التي تم ذكرها في المقال؟ وما هي NGINX، Tomcat، Apache، وخوادم الويب الأخرى؟
ج: بوابة API هي بوابة تستخدم لإدارة الخدمات بشكل موحد. على سبيل المثال، الدفع، تسجيل الدخول للمستخدمين، إلخ، كلها خدمات مقدمة في شكل APIs، وتحتاج جميعها إلى بوابة للقيام بالأمان والمصادقة بشكل موحد.
يمكن لبوابة API أن تحل محل NGINX، Apache التقليدية للتعامل مع حركة المرور الشمالية-الجنوبية، ولكن أيضًا في بيئة الخدمات الصغيرة للتعامل مع حركة المرور الشرقية-الغربية، وهي أقرب إلى برمجيات وسيطة مرتبطة بالأعمال، بدلاً من خادم الويب الأساسي.
لمزيد من المعلومات حول مقدمة وتنفيذ بوابة API، يرجى الرجوع إلى Apache APISIX؛ Apache APISIX يعتمد على تنفيذ OpenResty.