OpenResty: تحويل NGINX إلى خادم تطبيق كامل

OpenResty: تحويل NGINX إلى خادم تطبيق كاملنعيد نشر نص التقرير من المؤتمر HighLoad ++ 2016 ، الذي عقد في سكولكوفو بالقرب من موسكو في الفترة من 7 إلى 8 نوفمبر من العام الماضي. فلاديمير بروتاسوف يوضح كيفية توسيع وظائف NGINX باستخدام OpenResty و Lua.

مرحباً بالجميع ، اسمي فلاديمير بروتاسوف ، أنا أعمل في شركة Parallels. سأخبرك قليلا عن نفسي. أمضيت ثلاثة أرباع حياتي في كتابة الكود. أصبحت مبرمجًا حتى النخاع بالمعنى الحرفي: أرى أحيانًا رمزًا في أحلامي. ربع العمر هو التطور الصناعي ، كتابة التعليمات البرمجية التي تدخل مباشرة إلى الإنتاج. رمز يستخدمه البعض منكم ولكن لا يعرفونه.

لإعلامك بمدى سوء الأمر. عندما كنت صغيرًا ، دخلت وأعطوني قاعدتي بيانات تيرابايت. إنه الآن هنا للجميع حمولة عالية. ذهبت إلى المؤتمرات وسألت: "أيها الرجال ، أخبروني ، هل لديك بيانات ضخمة ، هل كل شيء رائع؟ كم عدد القواعد التي لديك هناك؟ أجابوني: "لدينا 100 جيجابايت!" قلت: "رائع ، 100 جيجابايت!" وفكرت في نفسي كيف أحفظ وجه البوكر بدقة. تعتقد ، نعم ، الرجال رائعون ، ثم تعود وتبدأ في العبث بقواعد البيانات التي يبلغ حجمها تيرابايت متعددة. وهذا هو كونك مبتدئًا. هل يمكنك أن تتخيل ما هي الضربة؟

أعرف أكثر من 20 لغة برمجة. هذا ما كان عليّ اكتشافه في سياق العمل. يعطونك رمزًا بلغة Erlang ، و C ، و C ++ ، و Lua ، و Python ، و Ruby ، ​​وفي شيء آخر ، وعليك قطع كل شيء. بشكل عام ، كان علي أن. لم يكن من الممكن حساب الرقم الدقيق ، ولكن في مكان ما تم فقد الرقم حوالي 20.

نظرًا لأن الجميع هنا يعرف ما هو Parallels وماذا نفعل ، فلن أتحدث عن مدى روعتنا وماذا نفعل. سأخبرك فقط أن لدينا 13 مكتبًا حول العالم ، وأكثر من 300 موظف ، وتطوير في موسكو وتالين ومالطا. إذا كنت ترغب في ذلك ، يمكنك الانتقال إلى مالطا والانتقال إليها ، إذا كان الجو باردًا في الشتاء وتحتاج إلى تدفئة ظهرك.

على وجه التحديد ، يكتب قسمنا بلغة Python 2. نحن في مجال الأعمال وليس لدينا وقت لتقديم تقنيات عصرية ، لذلك نحن نعاني. لدينا Django ، لأنه يمتلك كل شيء ، وأخذنا الفائض وألقينا به بعيدًا. أيضا MySQL و Redis و NGINX. لدينا أيضًا الكثير من الأشياء الرائعة الأخرى. لدينا MongoDB ، لدينا أرانب تتجول ، ليس لدينا أي شيء - لكنها ليست لي ، وأنا لا أفعل ذلك.

OpenResty

قلت عن نفسي. دعونا نرى ما سأتحدث عنه اليوم:

  • ما هو OpenResty وماذا يؤكل؟
  • لماذا نعيد اختراع العجلة عندما يكون لدينا Python و NodeJS و PHP و Go وغيرها من الأشياء الرائعة التي يسعد الجميع بها؟
  • وبعض الأمثلة الواقعية. اضطررت إلى قطع التقرير كثيرًا ، لأنني حصلت عليه لمدة 3,5 ساعة ، لذلك ستكون هناك أمثلة قليلة.

OpenResty هو NGINX. بفضله ، لدينا خادم ويب كامل ، وهو مكتوب جيدًا ، ويعمل بسرعة. أعتقد أن معظمنا يستخدم NGINX في الإنتاج. تعلمون جميعًا أنه سريع ورائع. لقد قاموا بإنشاء إدخال / إخراج متزامن رائع فيه ، لذلك لا نحتاج إلى تدوير أي شيء بنفس الطريقة التي تم بها تدوير gevent في Python. Gevent رائع ، رائع ، ولكن إذا كتبت C-code وحدث خطأ ما في gevent ، فسوف تصاب بجنون عند تصحيحه. كانت لدي خبرة: استغرق الأمر يومين كاملين لمعرفة الخطأ الذي حدث هناك. إذا لم يقم شخص ما بالحفر لبضعة أسابيع من قبل ، ووجد المشكلة ، وكتبها على الإنترنت ، ولم يعثر عليها Google ، فسنصاب بالجنون تمامًا.

NGINX تقوم بالفعل بالتخزين المؤقت والمحتوى الثابت. لا داعي للقلق بشأن كيفية القيام بذلك بطريقة إنسانية ، حتى لا تبطئ في مكان ما ، حتى لا تفقد الواصفات في مكان ما. يعد Nginx مناسبًا جدًا للنشر ، ولست بحاجة إلى التفكير فيما يجب أن تأخذه - WSGI و PHP-FPM و Gunicorn و Unicorn. تم تثبيت Nginx ، وتم إعطاؤه للمسؤولين ، فهم يعرفون كيفية التعامل معه. يعالج Nginx الطلبات بطريقة منظمة. سأتحدث عن هذا بعد قليل. باختصار ، لقد مر بمرحلة عندما وافق للتو على الطلب ، وعندما قام بمعالجته ، وعندما قدم المحتوى إلى المستخدم.

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

  • القياس. إنها صغيرة. يوفر LuaJIT في مكان ما حوالي 100-200 كيلو بايت من حمل الذاكرة والحد الأدنى من حمل الأداء.
  • سرعة. يكون مترجم LuaJIT قريبًا من لغة C في العديد من المواقف ، وفي بعض المواقف يفقده إلى Java ، وفي بعض الحالات يتفوق عليه. لفترة من الوقت ، تم اعتباره حالة من الفن ، أروع مترجم JIT. الآن هناك أبرد ، لكنها ثقيلة جدًا ، على سبيل المثال ، نفس محرك V8. بعض مترجمي JS و Java HotSpot أسرع في بعض النقاط ، لكنهم ما زالوا يخسرون في بعض النقاط.
  • سهل التعلم. إذا كان لديك ، على سبيل المثال ، قاعدة بيانات Perl ولم تقم بالحجز ، فلن تجد مبرمجي Perl. لأنهم ليسوا هناك ، تم أخذهم جميعًا بعيدًا ، وتعليمهم طويل وصعب. إذا كنت تريد مبرمجين لشيء آخر ، فقد يتعين أيضًا إعادة تدريبهم أو العثور عليهم. في حالة Lua ، كل شيء بسيط. يمكن لأي مبتدئ تعلم Lua في ثلاثة أيام. استغرق الأمر مني حوالي ساعتين لمعرفة ذلك. بعد ساعتين ، كنت أكتب بالفعل كودًا في الإنتاج. بعد حوالي أسبوع ، ذهب مباشرة إلى الإنتاج وغادر.

نتيجة لذلك ، يبدو كما يلي:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

يوجد الكثير هنا. جمعت OpenResty مجموعة من الوحدات ، كل من luash و engins. ولديك كل شيء جاهز - منتشر ويعمل.

أمثلة

كفى من كلمات الأغاني ، دعنا ننتقل إلى الكود. هنا القليل من Hello World:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

ماذا هنالك؟ هذا هو موقع المحركات. لا داعي للقلق ، نحن لا نكتب التوجيه الخاص بنا ، ولا نأخذ بعض التوجيهات الجاهزة - لدينا بالفعل في NGINX ، نحن نعيش بشكل جيد وكسل.

content_by_lua_block عبارة عن كتلة تنص على أننا نقدم محتوى باستخدام برنامج Lua النصي. نأخذ متغير engins remote_addr وانزلقها فيه string.format. هذا هو نفس sprintf، فقط في Lua ، صحيح فقط. ونعطيها للعميل.

نتيجة لذلك ، سيبدو كما يلي:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

لكن العودة إلى العالم الحقيقي. في الإنتاج ، لا أحد ينشر Hello World. عادةً ما ينتقل تطبيقنا إلى قاعدة البيانات أو إلى مكان آخر وفي معظم الأوقات ينتظر الرد.

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

فقط يجلس وينتظر. انها ليست جيدة جدا. عندما يأتي 100.000 مستخدم ، يكون الأمر صعبًا جدًا بالنسبة لنا. لذلك ، دعنا نستخدم تطبيقًا بسيطًا كمثال. سنبحث عن صور مثل القطط. لن نقوم فقط بالبحث فقط ، بل سنوسع الكلمات الرئيسية ، وإذا بحث المستخدم عن "القطط" ، فسنجد القطط والزغب وما إلى ذلك. نحتاج أولاً إلى الحصول على بيانات الطلب على الواجهة الخلفية. تبدو هكذا:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

سطرين يسمحان لك باختيار معلمات GET ، بدون تعقيدات. ثم ، على سبيل المثال ، نحصل على هذه المعلومات من قاعدة بيانات تحتوي على جدول حسب الكلمة الرئيسية والملحق باستخدام استعلام SQL عادي. كل شيء بسيط. تبدو هكذا:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

نحن نربط المكتبة resty.mysql، والتي لدينا بالفعل في المجموعة. لا نحتاج إلى تثبيت أي شيء ، كل شيء جاهز. حدد كيفية الاتصال وعمل استعلام SQL:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

إنه مخيف بعض الشيء ، لكنه يعمل. هنا 10 هو الحد. نسحب 10 سجلات ، نحن كسالى ، لا نريد إظهار المزيد. في SQL ، نسيت الحد الأقصى.

ثم نجد الصور لجميع الاستفسارات. نجمع مجموعة من الطلبات ونملأ جدول Lua يسمى reqsو افعل ngx.location.capture_multi.

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

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

نظرًا لأننا كسالى ولا نريد كتابة معالجة HTTP والتخزين المؤقت ، فسنجعل NGINX تفعل كل شيء من أجلنا. كما رأيت ، كان هناك طلب url/fetchها هو:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

نحن نجعلها بسيطة proxy_pass، وتحديد مكان التخزين المؤقت ، وكيفية القيام بذلك ، وكل شيء يعمل لصالحنا.

لكن هذا لا يكفي ، ما زلنا بحاجة إلى إعطاء البيانات للمستخدم. أبسط فكرة هي إجراء تسلسل لكل شيء إلى JSON ، بسهولة ، في سطرين. نعطي نوع المحتوى ، ونعطي JSON.

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

ماذا نفعل معها؟ بالطبع ، سوف نعطي المستخدم HTML. التوليد باستخدام المقابض ليس أمرًا تجاريًا ، لذلك نريد استخدام القوالب. توجد مكتبة لهذا الغرض lua-resty-template.

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

يجب أن تكون قد شاهدت الرسائل الثلاثة المخيفة OPM. يأتي OpenResty مع مدير الحزم الخاص به ، والذي يمكنك من خلاله تثبيت مجموعة من الوحدات المختلفة ، على وجه الخصوص ، lua-resty-template. إنه محرك قالب بسيط مشابه لقوالب Django. هناك يمكنك كتابة التعليمات البرمجية والقيام باستبدال متغير.

نتيجة لذلك ، سيبدو كل شيء كما يلي:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

أخذنا البيانات وعرضنا القالب مرة أخرى في سطرين. المستخدم سعيد ، لديه قطط. منذ أن قمنا بتوسيع الطلب ، حصل أيضًا على ختم الفراء للقطط. أنت لا تعرف أبدًا ، ربما كان يبحث عنها ، لكنه لم يستطع صياغة طلبه بشكل صحيح.

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

  • الطور الأول - الوصول، عندما جاء المستخدم للتو ، نظرنا إليه من خلال الرؤوس ، وعناوين IP ، والبيانات الأخرى. يمكنك تقطيعه على الفور إذا لم يعجبنا. يمكن استخدام هذا للحصول على إذن ، أو إذا تلقينا الكثير من الطلبات ، فيمكننا قطعها بسهولة في هذه المرحلة.
  • إعادة كتابة. إعادة كتابة بعض بيانات الطلب.
  • محتوى. نعطي المحتوى للمستخدم.
  • مرشح الرأس. قم بتغيير رؤوس الاستجابة. إذا استخدمنا proxy_pass، يمكننا إعادة كتابة بعض الترويسات قبل إعطائها للمستخدم.
  • مرشح الجسم. يمكننا تغيير الجسم.
  • سجل - تسجيل. من الممكن كتابة السجلات في elasticsearch بدون طبقة إضافية.

سيبدو تفويضنا كما يلي:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

سنضيفه إلى ذلك locationالتي وصفناها من قبل ، ووضعنا الكود التالي هناك:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

نحن نتطلع لمعرفة ما إذا كان لدينا رمز ملف تعريف الارتباط. إذا لم يكن كذلك ، فإننا نرمي الإذن. المستخدمون ماكرون وقد يخمنون أنه يجب تعيين رمز ملف تعريف الارتباط. لذلك ، سنضعه أيضًا في Redis:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

رمز العمل مع Redis بسيط جدًا ولا يختلف عن اللغات الأخرى. في نفس الوقت ، كل المدخلات / المخرجات ، ما هو موجود ، ما هو هنا ، لا يتم حظره. إذا كتبت رمزًا متزامنًا ، فإنه يعمل بشكل غير متزامن. كما هو الحال مع gevent ، أحسنت فقط.

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

لنفعل التفويض نفسه:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

نقول إننا بحاجة إلى قراءة نص الطلب. نتلقى وسيطات POST ، تحقق من صحة تسجيل الدخول وكلمة المرور. إذا كان غير صحيح ، فإننا نرمي الإذن. وإذا كانت صحيحة ، فسنكتب الرمز المميز إلى Redis:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

لا تنس ضبط ملف تعريف الارتباط ، يتم ذلك أيضًا في سطرين:

OpenResty: تحويل NGINX إلى خادم تطبيق كامل

المثال بسيط ، تخميني. بالطبع ، لن نقدم خدمة تُظهر القطط للناس. لكن من يعرفنا. لذلك دعونا نستعرض ما يمكن عمله في الإنتاج.

  • الحد الأدنى الخلفية. نحتاج في بعض الأحيان إلى إعطاء قدر كبير من البيانات إلى الواجهة الخلفية: في مكان ما نحتاج إلى استبدال التاريخ ، في مكان ما نحتاج إلى عرض نوع من القائمة ، قل عدد المستخدمين الموجودين على الموقع الآن ، أو قم بإغلاق عداد أو إحصائيات. شيء صغير جدًا. يمكن صنع بعض القطع البسيطة بسهولة بالغة. سيكون هذا سريعًا وسهلاً ورائعًا.
  • معالجة البيانات. في بعض الأحيان نرغب في تضمين إعلانات في صفحتنا ، ونأخذ هذه الإعلانات مع طلبات واجهة برمجة التطبيقات. هذا من السهل جدا القيام به هنا. لا نقوم بتحميل الواجهة الخلفية الخاصة بنا ، والتي تعمل بجد بالفعل. يمكنك أن تلتقط وتجمع هنا. يمكننا قولبة بعض JS أو ، على العكس من ذلك ، فصل شيء ما ومعالجته مسبقًا قبل إعطائه للمستخدم.
  • واجهة للخدمة المصغرة. هذه أيضًا حالة جيدة جدًا ، لقد نفذتها. قبل ذلك ، عملت في Tenzor ، وهي شركة تقارير إلكترونية تقدم تقارير لنحو نصف الكيانات القانونية في الدولة. لقد قدمنا ​​خدمة ، ويتم تنفيذ العديد من الأشياء هناك باستخدام نفس الآلية: التوجيه والتفويض والمزيد.
    يمكن استخدام OpenResty كغراء لخدماتك المصغرة لتوفير وصول واحد إلى كل شيء وواجهة واحدة. نظرًا لأنه يمكن كتابة الخدمات المصغرة بطريقة تجعلك تمتلك Node.js هنا ، فلديك PHP هنا ، ولديك Python هنا ، وهناك شيء من Erlang هنا ، ونحن نتفهم أننا لا نريد إعادة كتابة نفس الكود في كل مكان. لذلك ، يمكن توصيل OpenResty في المقدمة.

  • الإحصاء والتحليلات. عادة ما يكون NGINX عند المدخل ، وكل الطلبات تمر من خلاله. إنه في هذا المكان مناسب جدًا لجمعه. يمكنك حساب شيء ما على الفور وإلقائه في مكان ما ، على سبيل المثال ، نفس Elasticsearch أو Logstash أو مجرد كتابته في السجل ثم إرساله في مكان ما.
  • أنظمة متعددة المستخدمين. على سبيل المثال ، الألعاب عبر الإنترنت جيدة جدًا أيضًا. سيخبرك ألكسندر جلاديش اليوم في كيب تاون بكيفية إنشاء نموذج أولي سريع للعبة متعددة اللاعبين باستخدام OpenResty.
  • طلب التصفية (WAF). من المألوف الآن إنشاء جميع أنواع جدران الحماية لتطبيقات الويب ، وهناك العديد من الخدمات التي توفرها. بمساعدة OpenResty ، يمكنك أن تجعل نفسك جدار حماية لتطبيق الويب ، والذي سيقوم ببساطة وبسهولة بتصفية الطلبات وفقًا لمتطلباتك. إذا كان لديك Python ، فأنت تدرك أن PHP لن يتم حقنها لك بالتأكيد ، ما لم تقم ، بالطبع ، بتوليدها في أي مكان من وحدة التحكم. أنت تعلم أن لديك MySQL و Python. على الأرجح ، يمكنهم محاولة القيام بنوع من مسح الدليل وإدخال شيء ما في قاعدة البيانات. لذلك ، يمكنك تصفية الطلبات الغبية بسرعة وبتكلفة زهيدة في المقدمة.
  • تواصل اجتماعي. نظرًا لأن OpenResty يعتمد على NGINX ، فإنه يحتوي على مكافأة - هذا هو مجتمع NGINX. إنه كبير جدًا ، وقد تم بالفعل الإجابة على الكثير من الأسئلة التي لديك في البداية من قبل مجتمع NGINX.

    مطوري لوا. تحدثت بالأمس مع اللاعبين الذين حضروا يوم تدريب HighLoad ++ وسمعت أن لغة Tarantool هي الوحيدة المكتوبة بلغة Lua. ليس الأمر كذلك ، فالكثير من الأشياء مكتوبة بلغة لوا. أمثلة: OpenResty ، خادم Prosody XMPP ، محرك لعبة Love2D ، Lua مكتوب في Warcraft وأماكن أخرى. هناك الكثير من مطوري Lua ، ولديهم مجتمع كبير وسريع الاستجابة. تم الرد على جميع أسئلتي في Lua في غضون ساعات قليلة. عندما تكتب إلى القائمة البريدية ، توجد بالفعل مجموعة من الإجابات في بضع دقائق ، تصف ماذا وكيف وماذا. إنه لشيء رائع. للأسف ، مثل هذا المجتمع الصادق اللطيف ليس في كل مكان.
    OpenResty لديه GitHub ، حيث يمكنك فتح مشكلة إذا حدث شيء ما. توجد قائمة بريدية في مجموعات Google حيث يمكنك مناقشة القضايا العامة ، وهناك قائمة بريدية باللغة الصينية - لا تعرف أبدًا ، ربما لا تتحدث الإنجليزية ، ولكن لديك معرفة بالصينية.

نتائج

  • آمل أن أكون قادرًا على إيصال أن OpenResty هو إطار عمل ويب ملائم للغاية.
  • لها عتبة دخول منخفضة ، نظرًا لأن الكود مشابه لما نكتبه ، فإن اللغة بسيطة للغاية وأضيق الحدود.
  • إنه يوفر إدخال / إخراج غير متزامن بدون عمليات رد نداء ، ولن يكون لدينا شعرية كما يمكننا أحيانًا الكتابة في NodeJS.
  • إنه سهل النشر ، لأننا نحتاج فقط إلى NGINX مع الوحدة النمطية الصحيحة وكودنا ، وكل شيء يعمل على الفور.
  • مجتمع كبير وسريع الاستجابة.

لم أخبِر بالتفصيل كيف تتم عملية التوجيه ، فقد تبين أنها قصة طويلة جدًا.

شكرا لك!


Vladimir Protasov - OpenResty: تحويل NGINX إلى خادم تطبيق كامل

المصدر: www.habr.com

إضافة تعليق