إطلاق الحلول المخصصة: توظيف Apache APISIX و Node-Red بتناغم

March 6, 2024

Ecosystem

الخلفية

يحتاج العديد من مستخدمي Apache APISIX إلى تخصيص في البيئات المؤسسية لتلبية متطلبات محددة في سيناريوهات معينة، على الرغم من أن APISIX يحتوي على العديد من الميزات المدمجة القوية.

غالبًا ما يختار المستخدمون كتابة الإضافات (plugins) بلغة Lua وتثبيتها على مثيلات APISIX للاستخدام. ومع ذلك، فإن لغة Lua لديها جمهور محدود نسبيًا. على الرغم من أنها سهلة التعلم، إلا أن إتقانها ليس بالأمر السهل، وتنفيذ منطق تحويل البيانات المعقد في Lua يمكن أن يصبح معقدًا للغاية. حاليًا، يتم تعريض جزء فقط من الخطافات (hooks) بواسطة Java Plugin Runner للمطورين للاستدعاء، مما يتطلب تعديلات على الكود المصدري لـ Java Plugin Runner للوظائف التي لا يتم دعمها مباشرة.

يوضح الرسم البياني أدناه ثلاثة أنماط شائعة لاستخدام الإضافات: تعمل إضافات Lua مباشرة داخل نواة APISIX؛ يتواصل Plugin Runner عبر RPC مع Plugin Runners بلغات مثل Java و Golang وغيرها؛ ويتم تحويل إضافات WASM إلى بايت كود وتشغيلها داخليًا في نواة APISIX.

الإضافات وبرامج تشغيل الإضافات في APISIX

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

لحل هذه المشكلة، تم اقتراح نهج جديد لتعزيز قدرات Apache APISIX. يتضمن هذا النهج استخدام الإضافات المدمجة فقط في Apache APISIX لتكوين القدرات الشائعة مثل المصادقة والحد من المعدل، مع وضع المنطق المخصص الجديد في خدمات خارجية. يمكن أن تكون الخدمة الخارجية إما برنامجًا ثنائيًا أو خدمة API أخرى، والتي سيتم التعامل معها كخدمة علوية (upstream) لـ APISIX. ستتعامل هذه الخدمة الخارجية مع الطلبات والاستجابات مثل البرمجيات الوسيطة (middleware). يمكن أيضًا تطبيق هذا النهج على بوابات API أو خدمات الوكيل الأخرى.

وصف السيناريو

لدينا سلسلة من الخدمات التي توفر خدمات استعلام البيانات في الأعلى (يستخدم هذا المقال https://api-ninjas.com/api كمثال). على سبيل المثال، يمكن استرداد أحدث معلومات الطقس ومعلومات البلد (مثل الناتج المحلي الإجمالي للبلد، اسم العاصمة، ووحدة العملة) بناءً على اسم المدينة.

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

تحليل المشكلة

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

المتطلبات التي نقدمها في هذه المدونة تتضمن تحليل معلمات محددة من طلبات العملاء ثم بناء طلبات لاسترداد البيانات من خدمات علوية مختلفة. ومع ذلك، قضينا الكثير من الوقت في التعامل مع معاملات خارج كتابة الأعمال. لذلك، بالنسبة لهذا النوع من المنطق الذي يتضمن تحويل المعلمات، تحويل التنسيق، أو الاستدعاءات الخارجية، يمكننا اعتماد نهج أخف وأكثر بديهية، وهو بالضبط المشكلة التي يمكن لـ Node-Red حلها.

مقدمة عن Node-Red

Node-RED هو أداة برمجة قائمة على التدفق قوية وسهلة الاستخدام مناسبة لأتمتة ومعالجة تدفقات البيانات عبر مجالات مختلفة. واجهة البرمجة الخاصة بها، مكتبة العقد الغنية، وقابلية التوسع المرنة تسمح لنا ببناء تدفقات معقدة بسرعة وتنفيذ سيناريوهات تطبيقية متنوعة. فيما يلي بعض العقد التي يوفرها Node-RED:

  • عقدة HTTP_IN: تعرض نقطة نهاية لاستدعاء الخدمات الخارجية، والتي سنستخدمها كخدمة علوية لـ APISIX.

  • عقدة Function: تسمح للمطورين بكتابة دوال برمجية بلغة JavaScript لتعديل، حذف، إلخ، المدخلات/المخرجات.

  • عقدة Switch: تسمح للمطورين بتعيين مجموعة من الشروط للدخول إلى العقدة التالية المحددة عند استيفاء شرط معين.

  • عقدة HTTP_Request: يمكن تعيين URL، إلخ، لإرسال البيانات إلى هذه النقطة النهاية عبر Node-RED عند تنفيذ سير العمل بالكامل.

  • عقدة Change: يمكن إضافة، تعديل، أو حذف قيم محددة لكائن معين.

  • عقدة HTTP_Response: تُستخدم لإرجاع الاستجابات إلى العملاء.

بالإضافة إلى العقد المذكورة أعلاه، يوفر Node-RED أيضًا العديد من العقد المدمجة الأخرى. سيظهر هذا المقال للقراء كيفية تنفيذ المتطلبات المذكورة أعلاه عبر Node-RED.

عرض مثال

إعداد البيئة

سنقوم بنشر المكونات المطلوبة من خلال الحاويات، باستخدام Droplet من DigitalOcean كموارد الخادم.

$ doctl compute ssh-key list

ID          Name             FingerPrint
25621060    Zhiyuan Ju       2c:84:b7:d8:14:0a:a0:0f:ca:fe:ca:24:06:a4:fe:39

$ doctl compute droplet create \
    --image docker-20-04 \
    --size s-2vcpu-4gb-amd \
    --region sgp1 \
    --vpc-uuid 646cf2b8-03d8-4f48-b7c8-57cdee60ad27 \
    --ssh-keys 25621060 \
    apisix-nodered-docker-ubuntu-s-2vcpu-4gb-amd-sgp1-01
  
$ doctl compute droplet list

ID           Name                                                    Public IPv4       Private IPv4    Public IPv6    Memory    VCPUs    Disk    Region    Image                                   VPC UUID                                Status    Tags    Features                            Volumes
404094941    apisix-nodered-docker-ubuntu-s-2vcpu-4gb-amd-sgp1-01    143.198.192.64    10.104.0.3                     4096      2        80      sgp1      Ubuntu Docker 25.0.3 on Ubuntu 22.04    646cf2b8-03d8-4f48-b7c8-57cdee60ad27    active            droplet_agent,private_networking

نشر Apache APISIX

سنستخدم APISIX Quickstart لبدء مثيل جديد من APISIX، للوثائق التفصيلية يرجى الرجوع إلى https://docs.api7.ai/apisix/getting-started/.

$ curl -sL https://run.api7.ai/apisix/quickstart | sh

نشر Node-RED

يوفر Node-RED طرقًا متعددة للنشر، وسنقوم بالنشر بسرعة عبر Docker ودمجه مع البيئة الحالية. لمزيد من التفاصيل حول النشر، يرجى الرجوع إلى الوثائق الرسمية: https://nodered.org/docs/getting-started/.

عند نشر Node-RED، تأكد من إضافة الحاوية إلى شبكة APISIX لضمان قدرتها على التواصل مع APISIX والتعامل مع الطلبات.

$ docker run -d -it -p 1880:1880 -v $PWD/configs/nodered/data:/data --network=apisix-quickstart-net --name mynodered -u Node-Red:dialout nodered/Node-Red

تكوين Node-RED

  1. للتعامل مع الطلبات التي تدخل Node-RED من APISIX، يحتاج Node-Red إلى التحقق مما إذا كانت المعلمات في الطلب موجودة وصالحة. إذا كانت المعلمات مفقودة أو غير صالحة، سيتم إرجاع رسالة خطأ. إذا كانت صالحة، سيتم تنفيذ العقدة التالية. في هذا السيناريو المحدد، نسمح فقط باستعلام البيانات لمدينتين، ستوكهولم (city=stockholm) وبرلين (city=berlin).

استخدام Node-Red للتحقق من المعلمات

  1. بمجرد دخول الطلب إلى العقدة التالية، يحتاج Node-RED إلى تحديد نوع البيانات المطلوبة. في هذا السيناريو، هناك ثلاثة أنواع: معلومات الطقس (scope=weather)، معلومات البلد الذي تقع فيه المدينة (scope=country)، والناتج المحلي الإجمالي للبلد الذي تقع فيه المدينة (scope=gdp).

استخدام Node-Red لتحديد نوع البيانات

  1. إذا كانت كل من معلمات City و Scope صالحة، سيحدد Node-RED أي API لاسترداد البيانات بناءً على قيمة scope. بعد تعيين URL، Method، Payload، X-API-Key، إلخ، ستقوم عقدة Node-RED بالوصول إلى النقطة النهاية المقابلة لاسترداد البيانات عند التنفيذ.

اختيار API لاسترداد البيانات بناءً على scope

  1. عند استرداد البيانات لـ scope=gdp، يحتاج Node-RED إلى استخراج قيمة GDP من جسم الاستجابة لـ API الخارجي. يمكن القيام بذلك باستخدام عقدة Change للاستخراج أو عقدة Function.

تحليل قيمة GDP من جسم استجابة API الخارجي

  1. أخيرًا، سيقوم Node-RED بإرجاع البيانات المعالجة إلى APISIX، والتي ستمررها إلى العميل. يظهر الرسم البياني النهائي لـ Node-RED أدناه.

مخطط تدفق يجمع بين APISIX و Node-Red

إنشاء مسارات APISIX

لجعل خدمة Node-Red متاحة للعملاء، نحتاج إلى استخدام APISIX كوكيل عكسي للنقاط النهاية التي يتم تعريضها بواسطة Node-Red. فيما يلي الخطوات التي تحتاج إلى اتباعها:

  1. إنشاء مسار APISIX وتعيين mynodered:1880 كخدمة علوية لهذا المسار. بهذه الطريقة، سيتم توجيه جميع الطلبات المرسلة إلى هذه النقطة النهاية إلى خدمة Node-Red.

  2. تمكين المصادقة باستخدام المفتاح (Key Authentication) لضمان أن الطلبات التي تحمل مفتاح API صالح فقط هي التي يمكنها اجتياز المصادقة والوصول إلى خدمة Node-Red.

باتباع الخطوات المذكورة أعلاه، يمكننا تعريض خدمة Node-Red للعملاء بشكل آمن وضمان أن المستخدمين المصرح لهم فقط يمكنهم الوصول إليها.

$ curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT -d '
{
  "id": "proxy-global-data-endpoint",
  "uri": "/global-data",
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "mynodered:1880": 1
    }
  },
  "plugins": {
    "key-auth": {}
  }
}'

$ curl -i "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT -d '
{
  "username": "tom",
  "plugins": {
    "key-auth": {
      "key": "secret-key"
    }
  }
}'

التحقق من الطلبات

سنحاول عدة سيناريوهات بشكل منفصل للتحقق مما إذا كان APISIX و Node-Red يعملان كما هو متوقع:

السيناريو 1

  • وصف السيناريو: الوصول إلى API بمفتاح غير صحيح.

  • النتيجة المتوقعة: نظرًا لأن مفتاح API المقدم غير صحيح، يجب رفض الطلب وإرجاع رسالة الخطأ المقابلة.

$ curl http://143.198.192.64:9080/global-data -H "apikey: invalid-key" -i

HTTP/1.1 401 Unauthorized
Date: Mon, 04 Mar 2024 07:47:24 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/3.8.0

{"message":"Invalid API key in request"}

السيناريو 2

  • وصف السيناريو: الوصول إلى API بمفتاح صحيح، ولكن مع حقل City غير صالح.

  • النتيجة المتوقعة: نظرًا لأن معلمات الطلب لا تلبي المتطلبات، يجب إرجاع رسالة الخطأ المقابلة، مشيرة إلى أن حقل City غير صالح.

$ curl "http://143.198.192.64:9080/global-data?city=singapore&scope=country" -H "apikey: secret-key" -i

HTTP/1.1 400 Bad Request
Content-Type: application/json; charset=utf-8
Content-Length: 69
Connection: keep-alive
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
ETag: W/"45-IOhgB2XkDHi2Kt4PP42n1xa8Gys"
Date: Mon, 04 Mar 2024 07:48:02 GMT
Server: APISIX/3.8.0

{"errorCode":400,"message":"Allowed city Options: Stockholm, Berlin"}

السيناريو 3

  • وصف السيناريو: الوصول إلى API بمفتاح صحيح، وحقول City و Scope صالحة لاسترداد بيانات البلد.

  • النتيجة المتوقعة: يجب أن يكون الطلب ناجحًا، ويجب إرجاع المعلومات ذات الصلة عن البلد الذي تقع فيه City.

$ curl "http://143.198.192.64:9080/global-data?city=stockholm&scope=country" -H "apikey: secret-key" -i

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 947
Connection: keep-alive
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
ETag: W/"3b3-XDlm9OHfuUrWH+g42q8L1F2uu/o"
Date: Mon, 04 Mar 2024 07:48:26 GMT
Server: APISIX/3.8.0

[{"gdp":556086,"sex_ratio":100.4,"surface_area":438574,"life_expectancy_male":80.8,"unemployment":6.7,"imports":158710,"homicide_rate":1.1,"currency":{"code":"SEK","name":"Swedish Krona"},"iso2":"SE","employment_services":80.7,"employment_industry":17.7,"urban_population_growth":1.1,"secondary_school_enrollment_female":157.9,"employment_agriculture":1.6,"capital":"Stockholm","co2_emissions":37.6,"forested_area":68.9,"tourists":7440,"exports":160538,"life_expectancy_female":84.4,"post_secondary_enrollment_female":82.1,"post_secondary_enrollment_male":52.7,"primary_school_enrollment_female":127.4,"infant_mortality":2,"gdp_growth":2.2,"threatened_species":98,"population":10099,"urban_population":87.7,"secondary_school_enrollment_male":148.1,"name":"Sweden","pop_growth":0.7,"region":"Northern Europe","pop_density":24.6,"internet_users":92.1,"gdp_per_capita":55766.8,"fertility":1.8,"refugees":310.4,"primary_school_enrollment_male":125.8}]

السيناريو 4

  • وصف السيناريو: الوصول إلى API بمفتاح صحيح، وحقول City و Scope صالحة لاسترداد بيانات GDP.

  • النتيجة المتوقعة: يجب أن يكون الطلب ناجحًا، ويجب إرجاع بيانات GDP للبلد الذي تقع فيه City.

$ curl "http://143.198.192.64:9080/global-data?city=stockholm&scope=gdp" -H "apikey: secret-key" -i

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 6
Connection: keep-alive
Access-Control-Allow-Origin: *
ETag: W/"6-j8I5kokycgWjCeKC1c2UfJW7AQY"
Date: Mon, 04 Mar 2024 07:48:48 GMT
Server: APISIX/3.8.0

556086

من خلال التحقق من هذه السيناريوهات الأربعة، يمكننا التأكد من أن APISIX و Node-Red يعملان كما هو متوقع ويمكنهما التعامل بشكل صحيح مع أنواع الطلبات المختلفة.

الخلاصة

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

  1. توجيه طلبات API والتحقق من الهوية: أولاً، باستخدام وظيفة التوجيه في Apache APISIX وإضافات المصادقة، يقوم APISIX بتوجيه طلبات العملاء إلى خدمة Node-Red عندما تكون بيانات الاعتماد المقدمة صالحة.

  2. معالجة الطلبات وتحويلها: في Node-Red، نقوم بإنشاء تدفق لمعالجة طلبات API الواردة. باستخدام عقدة HTTP input لاستقبال الطلبات من APISIX، نقوم بتحليل والتحقق من معلمات الطلب لضمان استيفائها لمتطلبات الأعمال.

  3. معالجة منطق الأعمال: بمجرد استلام طلب صالح، يمكننا تنفيذ منطق الأعمال في Node-Red. على سبيل المثال، إرسال طلبات إلى واجهات برمجة التطبيقات التجارية المختلفة بناءً على المعلمات لاسترداد البيانات واستخراج الحقول المطلوبة من الاستجابة. بعد الانتهاء من هذه العمليات، يتم إرجاع البيانات النهائية إلى APISIX.

  4. معالجة الأخطاء والتسجيل: أثناء المعالجة، إذا حدثت أي أخطاء أو استثناءات، يمكننا إضافة عقد معالجة الأخطاء في Node-Red للتعامل مع الحالات الاستثنائية. بالإضافة إلى ذلك، يمكننا استخدام عقد التسجيل لتسجيل المعلومات الرئيسية أثناء المعالجة لاستكشاف الأخطاء وإصلاحها لاحقًا، وهو ما لم يتم عرضه في هذا المثال.

من خلال الجمع بين APISIX و Node-Red، يمكننا تنفيذ عملية معالجة الطلبات الكاملة بشكل مرئي، بما في ذلك توجيه الطلبات، معالجة البيانات، منطق الأعمال، إلخ، دون الحاجة إلى كتابة كود أو إضافات معقدة. هذا الحل المرن والقابل للتخصيص يمكن أن يساعدنا في بناء وتعديل وظائف النظام بشكل أسرع، وتحسين كفاءة التطوير، وتقليل تكاليف التطوير، وضمان استقرار النظام وقابليته للتوسع.

Tags: