พัฒนาปลั๊กอินที่กำหนดเอง

คุณกำลังดูเอกสารประกอบของ Apigee Edge
ไปที่เอกสารประกอบของ Apigee X
ข้อมูล

Edge Microgateway เวอร์ชัน 3.1.x

ผู้ชม

หัวข้อนี้มีไว้สำหรับนักพัฒนาซอฟต์แวร์ที่ต้องการขยายฟีเจอร์ Edge Microgateway โดยการเขียนปลั๊กอินที่กำหนดเอง หากต้องการเขียนปลั๊กอินใหม่ คุณจำเป็นต้องมีประสบการณ์กับ JavaScript และ Node.js

ปลั๊กอิน Edge Microgateway ที่กำหนดเองคืออะไร

ปลั๊กอินคือโมดูล Node.js ที่เพิ่มฟังก์ชันการทำงานให้กับ Edge Microgateway โมดูลปลั๊กอินจะมีรูปแบบที่สอดคล้องกันและจัดเก็บไว้ในตำแหน่งที่ Edge Microgateway รู้จัก ซึ่งช่วยให้สามารถค้นพบและเรียกใช้ปลั๊กอินได้โดยอัตโนมัติ มีปลั๊กอินที่กำหนดไว้ล่วงหน้าหลายรายการเมื่อคุณติดตั้ง Edge Microgateway ซึ่งรวมถึงปลั๊กอินสำหรับการตรวจสอบสิทธิ์ การยับยั้งการเพิ่มขึ้น โควต้า และข้อมูลวิเคราะห์ โปรดดูคำอธิบายของปลั๊กอินที่มีอยู่เหล่านี้ในหัวข้อใช้ปลั๊กอิน

คุณสามารถเพิ่มฟีเจอร์และความสามารถใหม่ๆ ให้กับไมโครเกตเวย์ได้โดยเขียนปลั๊กอินที่กำหนดเอง โดยค่าเริ่มต้น Edge Microgateway เป็นพร็อกซีส่งผ่านที่ปลอดภัยซึ่งจะส่งคำขอและการตอบกลับโดยไม่มีการเปลี่ยนแปลงไปยังและจากบริการเป้าหมาย ปลั๊กอินที่กำหนดเองจะช่วยให้คุณโต้ตอบกับคำขอและการตอบกลับที่ไหลผ่าน Microgateway แบบเป็นโปรแกรมได้

ตำแหน่งที่จะใส่โค้ดปลั๊กอินที่กำหนดเอง

โฟลเดอร์สำหรับปลั๊กอินที่กำหนดเองจะรวมอยู่ในการติดตั้ง Edge Microgateway ที่นี่

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

โดยที่ [prefix] คือไดเรกทอรีคำนำหน้า npm ตามที่อธิบายใน " Edge Microgateway ได้รับการติดตั้งไว้ไว้ที่ใด" ใน การติดตั้ง Edge Microgateway

คุณสามารถเปลี่ยนไดเรกทอรีปลั๊กอินเริ่มต้นนี้ได้ ดูตำแหน่งที่จะพบปลั๊กอิน

การตรวจสอบปลั๊กอินที่กำหนดไว้ล่วงหน้า

ก่อนที่จะลองพัฒนาปลั๊กอินของตนเอง คุณควรตรวจสอบว่าไม่มีปลั๊กอินที่กำหนดไว้ล่วงหน้าที่ตรงตามความต้องการของคุณ ปลั๊กอินเหล่านี้อยู่ใน:

[prefix]/lib/node_modules/edgemicro/node_modules/microgateway-plugins

โดยที่ [prefix] คือไดเรกทอรีคำนำหน้า npm โปรดดูเพิ่มเติมที่ " Edge Microgateway ติดตั้งอยู่ที่ไหน" ในการติดตั้ง Edge Microgateway

โปรดดูรายละเอียดเพิ่มเติมที่หัวข้อปลั๊กอินที่กำหนดไว้ล่วงหน้าที่มาพร้อมกับ Edge Microgateway

เขียนปลั๊กอินง่ายๆ

ในส่วนนี้ เราจะแนะนำขั้นตอนที่จำเป็นในการสร้างปลั๊กอินง่ายๆ ปลั๊กอินนี้จะลบล้างข้อมูลการตอบกลับ (ไม่ว่าจะในรูปแบบใดก็ตาม) ด้วยสตริง "สวัสดีทุกคน" และสั่งพิมพ์ไปยังเทอร์มินัล

  1. หาก Edge Microgateway ทำงานอยู่ ให้หยุดการทำงานทันที
    edgemicro stop
    
  2. cd ไปยังไดเรกทอรีปลั๊กอินที่กำหนดเอง:

    cd [prefix]/lib/node_modules/edgemicro/plugins

    โดยที่ [prefix] คือไดเรกทอรีคำนำหน้า npm ตามที่อธิบายใน " Edge Microgateway ได้รับการติดตั้งไว้ไว้ที่ใด" ใน การติดตั้ง Edge Microgateway

  3. สร้างโปรเจ็กต์ปลั๊กอินใหม่ที่ชื่อว่า response-override และ cd ไปยังโปรเจ็กต์ดังกล่าว
    mkdir response-override && cd response-override
    
  4. สร้างโปรเจ็กต์ Node.js ใหม่:
    npm init
    
    กด Return หลายๆ ครั้งเพื่อยอมรับค่าเริ่มต้น
  5. ใช้เครื่องมือแก้ไขข้อความเพื่อสร้างไฟล์ใหม่ที่ชื่อ index.js
  6. คัดลอกโค้ดต่อไปนี้ลงใน index.js แล้วบันทึกไฟล์
    'use strict';
    var debug = require('debug')
    
    module.exports.init = function(config, logger, stats) {
    
      return {
       
        ondata_response: function(req, res, data, next) {
          debug('***** plugin ondata_response');
          next(null, null);
        },
        
        onend_response: function(req, res, data, next) {
          debug('***** plugin onend_response');
          next(null, "Hello, World!\n\n");
        }
      };
    }
    
  7. ตอนนี้คุณก็ได้สร้างปลั๊กอินแล้วและต้องการเพิ่มลงในการกำหนดค่า Edge Microgateway เปิดไฟล์ $HOME/.edgemicro/[org]-[env]-config.yaml โดยที่ org และ env คือชื่อองค์กร Edge และสภาพแวดล้อมของคุณ
  8. เพิ่มปลั๊กอิน response-override ลงในองค์ประกอบ plugins:sequence ดังที่แสดงด้านล่าง
          ...
          
          plugins:
            dir: ../plugins
            sequence:
              - oauth
              - response-override
              
          ...
    
  9. รีสตาร์ท Edge Microgateway
  10. เรียก API ผ่าน Edge Microgateway (การเรียก API นี้จะถือว่าคุณได้ตั้งค่าการกำหนดค่าเดียวกันกับบทแนะนำที่มีการรักษาความปลอดภัยคีย์ API ตามที่อธิบายไว้ในการตั้งค่าและการกำหนดค่า Edge Microgateway
    curl -H 'x-api-key: uAM4gBSb6YoMvTHfx5lXJizYIpr5Jd' http://localhost:8000/hello/echo
    Hello, World!
    

โครงสร้างของปลั๊กอิน

ตัวอย่างปลั๊กอินตัวอย่าง Edge Microgateway ต่อไปนี้แสดงรูปแบบที่ควรปฏิบัติตามเมื่อพัฒนาปลั๊กอินของคุณเอง ซอร์สโค้ดของปลั๊กอินตัวอย่างที่กล่าวถึงในส่วนนี้จะอยู่ใน plugins/header-uppercase/index.js.

  • ปลั๊กอินคือโมดูล NPM มาตรฐานที่มี package.json และ index.js ในโฟลเดอร์รูท
  • ปลั๊กอินต้องส่งออกฟังก์ชัน init()
  • ฟังก์ชัน init() จะมีอาร์กิวเมนต์ 3 รายการ ได้แก่ config, logger และ stats มีคำอธิบายอาร์กิวเมนต์เหล่านี้อยู่ในอาร์กิวเมนต์ของฟังก์ชัน init() ปลั๊กอิน
  • init() จะแสดงผลออบเจ็กต์ที่มีตัวแฮนเดิลฟังก์ชันที่มีชื่อ ซึ่งมีการเรียกใช้เมื่อเกิดเหตุการณ์บางอย่างขึ้นตลอดอายุของคำขอ

ฟังก์ชันของตัวแฮนเดิลเหตุการณ์

ปลั๊กอินต้องใช้ฟังก์ชันเครื่องจัดการเหตุการณ์เหล่านี้บางส่วนหรือทั้งหมด การใช้งานฟังก์ชันเหล่านี้ขึ้นอยู่กับคุณ คุณจะระบุฟังก์ชันใดก็ได้หรือไม่ก็ได้ และปลั๊กอินทั่วไปจะใช้ฟังก์ชันเหล่านี้อย่างน้อย 1 ชุด

ตัวแฮนเดิลเหตุการณ์โฟลว์คำขอ

ระบบจะเรียกใช้ฟังก์ชันเหล่านี้ในเหตุการณ์คำขอใน Edge Microgateway

  • onrequest
  • ondata_request
  • onend_request
  • onclose_request
  • onerror_request

onrequest function

โทรเมื่อเริ่มต้นคำขอของไคลเอ็นต์ ฟังก์ชันนี้จะเริ่มทำงานเมื่อ Edge Microgateway ได้รับไบต์แรกของคำขอ ฟังก์ชันนี้จะช่วยให้คุณเข้าถึงส่วนหัวของคำขอ, URL, พารามิเตอร์การค้นหา และวิธี HTTP ได้ หากเรียกใช้ครั้งถัดไปโดยใช้อาร์กิวเมนต์แรกที่เชื่อถือได้ (เช่น อินสแตนซ์ของข้อผิดพลาด) ระบบจะหยุดการประมวลผลคำขอ และระบบจะไม่เริ่มคำขอเป้าหมาย

ตัวอย่าง

onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-start'] = Date.now();
      next();
    }

ondata_request function

มีการเรียกใช้เมื่อได้รับข้อมูลจำนวนมากจากไคลเอ็นต์ ส่งผ่านข้อมูลคำขอไปยังปลั๊กอินถัดไปในลำดับปลั๊กอิน ระบบจะส่งค่าที่แสดงผลจากปลั๊กอินล่าสุดในลำดับไปยังเป้าหมาย กรณีการใช้งานทั่วไปที่แสดงด้านล่างคือการแปลงข้อมูลคำขอก่อนที่จะส่งไปยังเป้าหมาย

ตัวอย่าง

ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }

onend_request function

เรียกใช้เมื่อได้รับข้อมูลคำขอทั้งหมดจากไคลเอ็นต์แล้ว

ตัวอย่าง

onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    }

ฟังก์ชัน onclose_request

ระบุว่าการเชื่อมต่อไคลเอ็นต์ปิดแล้ว คุณอาจใช้ฟังก์ชันนี้ในกรณีที่การเชื่อมต่อไคลเอ็นต์ไม่น่าเชื่อถือ ระบบจะเรียกใช้เมื่อมีการปิดการเชื่อมต่อซ็อกเก็ตกับไคลเอ็นต์

ตัวอย่าง

onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    }

ฟังก์ชัน onerror_request

มีการเรียกใช้หากเกิดข้อผิดพลาดในการรับคำขอของไคลเอ็นต์

ตัวอย่าง

onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    }

เครื่องจัดการกิจกรรมขั้นตอนการตอบกลับ

ระบบจะเรียกใช้ฟังก์ชันเหล่านี้ในเหตุการณ์การตอบสนองใน Edge Microgateway

  • onresponse
  • ondata_response
  • onend_response
  • onclose_response
  • onerror_response

ฟังก์ชัน onresponse

เรียกใช้ในตอนต้นของการตอบสนองเป้าหมาย ฟังก์ชันนี้จะเริ่มทำงานเมื่อ Edge Microgateway ได้รับไบต์แรกของการตอบสนอง ฟังก์ชันนี้จะให้สิทธิ์เข้าถึงส่วนหัวการตอบกลับและรหัสสถานะ

ตัวอย่าง

onresponse: function(req, res, next) {      
    debug('plugin onresponse');     
    res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start'])    
    next();    
}


ฟังก์ชัน ondata_response

เรียกใช้เมื่อได้รับกลุ่มข้อมูลจากเป้าหมาย

ตัวอย่าง

ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    }


ฟังก์ชัน onend_response

เรียกใช้เมื่อได้รับข้อมูลคำตอบทั้งหมดจากเป้าหมายแล้ว

ตัวอย่าง

onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    }

ฟังก์ชัน onclose_response

แสดงว่าการเชื่อมต่อปลายทางปิดแล้ว คุณอาจใช้ฟังก์ชันนี้ในกรณีที่การเชื่อมต่อปลายทางไม่น่าเชื่อถือ ระบบจะเรียกใช้เมื่อการเชื่อมต่อซ็อกเก็ตกับเป้าหมายปิดอยู่

ตัวอย่าง

onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }


ฟังก์ชัน onerror_response

มีการเรียกใช้หากเกิดข้อผิดพลาดในการรับการตอบกลับเป้าหมาย

ตัวอย่าง

onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    }

สิ่งที่คุณจำเป็นต้องทราบเกี่ยวกับฟังก์ชันเครื่องจัดการเหตุการณ์ปลั๊กอิน

ระบบจะเรียกใช้ฟังก์ชันเครื่องจัดการเหตุการณ์ปลั๊กอินเพื่อตอบสนองต่อเหตุการณ์เฉพาะที่เกิดขึ้นขณะที่ Edge Microgateway ประมวลผลคำขอ API ที่ระบุ

  • ตัวแฮนเดิลฟังก์ชัน init() (ondata_request, ondata_response ฯลฯ) ต้องเรียกใช้โค้ดเรียกกลับ next() เมื่อประมวลผลเสร็จ หากคุณไม่เรียก next() การประมวลผลจะหยุดลงและคำขอจะค้าง
  • อาร์กิวเมนต์แรกไปยัง next() อาจเป็นข้อผิดพลาดที่จะทำให้การประมวลผลคำขอสิ้นสุดลง
  • ตัวแฮนเดิล ondata_ และ onend_ ต้องเรียกใช้ next() ด้วยอาร์กิวเมนต์ที่ 2 ที่มีข้อมูลซึ่งจะส่งไปยังเป้าหมายหรือไคลเอ็นต์ อาร์กิวเมนต์นี้อาจเป็นค่าว่างหากปลั๊กอินกำลังบัฟเฟอร์และมีข้อมูลไม่เพียงพอที่จะแปลงในขณะนี้
  • โปรดทราบว่าจะมีปลั๊กอินเพียงอินสแตนซ์เดียวที่ใช้ในการให้บริการคำขอและการตอบกลับทั้งหมด หากปลั๊กอินต้องการคงสถานะตามคำขอไว้ระหว่างการเรียก ปลั๊กอินจะบันทึกสถานะนั้นในพร็อพเพอร์ตี้ที่เพิ่มลงในออบเจ็กต์ request ที่ระบุ (req) ซึ่งมีอายุการใช้งานเป็นระยะเวลาของการเรียก API
  • ระมัดระวังหาข้อผิดพลาดทั้งหมดและเรียกใช้ next() ที่มีข้อผิดพลาด หากเรียกใช้ next() ไม่สำเร็จ จะส่งผลให้การเรียก API ค้าง
  • โปรดระวังอย่าทำให้หน่วยความจำรั่วไหลเนื่องจากอาจส่งผลต่อประสิทธิภาพโดยรวมของ Edge Microgateway และก่อให้เกิดข้อขัดข้องหากหน่วยความจำเต็ม
  • โปรดใช้โมเดล Node.js อย่างรอบคอบโดยอย่าทำงานที่ต้องใช้การประมวลผลในเทรดหลัก เนื่องจากอาจส่งผลเสียต่อประสิทธิภาพของ Edge Microgateway ได้

เกี่ยวกับฟังก์ชัน init() ของปลั๊กอิน

ส่วนนี้อธิบายอาร์กิวเมนต์ที่ส่งไปยังฟังก์ชัน init() ได้แก่ config, logger และ stats

การกำหนดค่า

ออบเจ็กต์การกำหนดค่าที่ได้รับหลังจากรวมไฟล์การกำหนดค่า Edge Microgateway กับข้อมูลที่ดาวน์โหลดจาก Apigee Edge เช่น ผลิตภัณฑ์และโควต้า คุณจะค้นหาการกำหนดค่าเฉพาะปลั๊กอินได้ในออบเจ็กต์นี้ config.<plugin-name>

หากต้องการเพิ่มพารามิเตอร์การกำหนดค่าที่ชื่อ param ด้วยค่า foo ลงในปลั๊กอินที่ชื่อ response-override ให้ใส่ไว้ในไฟล์ default.yaml

response-override:
    param: foo

จากนั้นคุณจะเข้าถึงพารามิเตอร์ในโค้ดปลั๊กอินได้ ดังนี้

// Called when response data is received
    ondata_response: function(req, res, data, next) {
      debug('***** plugin ondata_response');
      debug('***** plugin ondata_response: config.param: ' + config.param);
      next(null, data);
    },

ในกรณีนี้ คุณจะเห็น foo พิมพ์อยู่ในผลลัพธ์การแก้ไขข้อบกพร่องของปลั๊กอิน:

Sun, 13 Dec 2015 21:25:08 GMT plugin:response-override ***** plugin ondata_response: config.param: foo

logger

ตัวบันทึกระบบ ตัวบันทึกที่ใช้งานอยู่จะส่งออกฟังก์ชันเหล่านี้ โดยที่ออบเจ็กต์อาจเป็นสตริง, คำขอ HTTP, การตอบกลับ HTTP หรืออินสแตนซ์ข้อผิดพลาด

  • info(object, message)
  • warn(object, message)
  • error(object, message)

สถิติ

ออบเจ็กต์ที่มีจำนวนคำขอ การตอบกลับ ข้อผิดพลาด และสถิติรวมอื่นๆ ที่เกี่ยวข้องกับคำขอและการตอบกลับที่ไหลผ่านอินสแตนซ์ไมโครเกตเวย์

  • treqErrors - จำนวนคำขอเป้าหมายที่มีข้อผิดพลาด
  • treqErrors - จำนวนการตอบกลับเป้าหมายที่มีข้อผิดพลาด
  • statusCodes - ออบเจ็กต์ที่มีจำนวนโค้ดตอบกลับ:
{
  1: number of target responses with 1xx response codes
  2: number of target responses with 2xx response codes
  3: number of target responses with 3xx response codes
  4: number of target responses with 4xx response codes
  5: number of target responses with 5xx response codes
  }
  
  • requests - จำนวนคำขอทั้งหมด
  • Responses - จำนวนคำตอบทั้งหมด
  • Connections - จำนวนการเชื่อมต่อเป้าหมายที่ใช้งานอยู่

เกี่ยวกับฟังก์ชัน next()

เมธอดปลั๊กอินทั้งหมดต้องเรียกใช้ next() เพื่อประมวลผลเมธอดถัดไปในชุดต่อ (ไม่เช่นนั้นกระบวนการปลั๊กอินจะค้าง) ในวงจรของคำขอ วิธีแรกที่จะเรียกใช้คือ onrequest() และเมธอดถัดไปที่จะเรียกใช้คือเมธอด ondata_request() แต่ระบบจะเรียกใช้ ondata_request ก็ต่อเมื่อคำขอมีข้อมูล เช่น ในกรณีของคำขอ POST เท่านั้น วิธีการถัดไปที่เรียกคือ onend_request() ซึ่งจะเรียกใช้เมื่อการประมวลผลคำขอเสร็จสมบูรณ์ ระบบจะเรียกใช้ฟังก์ชัน onerror_* ในกรณีที่เกิดข้อผิดพลาดเท่านั้น และให้คุณจัดการข้อผิดพลาดด้วยรหัสที่กำหนดเองได้ หากต้องการ

สมมติว่ามีการส่งข้อมูลในคำขอ แล้วเรียก ondata_request() โปรดสังเกตว่าฟังก์ชันดังกล่าวเรียกใช้ next() ด้วยพารามิเตอร์ 2 รายการ ดังนี้

next(null, data);

ตามแบบแผน พารามิเตอร์แรกจะใช้เพื่อถ่ายทอดข้อมูลข้อผิดพลาด ซึ่งคุณสามารถจัดการในฟังก์ชันต่อๆ ไปในเชนได้ หากตั้งค่าเป็น null ซึ่งเป็นอาร์กิวเมนต์ที่ไม่ถูกต้อง เราจะบอกว่าไม่มีข้อผิดพลาด และการดำเนินการตามคำขอควรดำเนินการตามปกติ หากอาร์กิวเมนต์นี้เชื่อถือได้ (เช่น ออบเจ็กต์ข้อผิดพลาด) ระบบจะหยุดการประมวลผลคำขอ และระบบจะส่งคำขอไปยังเป้าหมาย

พารามิเตอร์ที่สองจะส่งข้อมูลคำขอไปยังฟังก์ชันถัดไปในเชน หากคุณไม่ประมวลผลเพิ่มเติม ระบบจะส่งข้อมูลคำขอไปยังเป้าหมายของ API โดยไม่มีการเปลี่ยนแปลง อย่างไรก็ตาม คุณจะมีโอกาสแก้ไขข้อมูลคำขอภายในเมธอดนี้และส่งคำขอที่แก้ไขแล้วไปยังเป้าหมายได้ เช่น หากข้อมูลคำขอคือ XML และเป้าหมายต้องการ JSON คุณก็เพิ่มโค้ดลงในเมธอด ondata_request() ที่ (ก) เปลี่ยน Content-Type ของส่วนหัวของคำขอเป็น application/json และแปลงข้อมูลคำขอเป็น JSON ด้วยวิธีการใดก็ได้ที่คุณต้องการ (เช่น คุณอาจใช้ตัวแปลง xml2json ของ Node.js ที่ได้รับจาก NPM ก็ได้)

มาดูกันว่าวิธีการเป็นอย่างไร

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  next(null, translated_data);
},

ในกรณีนี้ ข้อมูลคำขอ (ที่คาดว่าจะเป็น XML) จะถูกแปลงเป็น JSON และข้อมูลที่เปลี่ยนรูปแบบจะส่งผ่าน next() ไปยังฟังก์ชันถัดไปในห่วงโซ่คำขอ ก่อนที่จะส่งไปยังเป้าหมายแบ็กเอนด์

โปรดทราบว่าคุณเพิ่มคำสั่งการแก้ไขข้อบกพร่องอีกรายการเพื่อพิมพ์ข้อมูลที่เปลี่ยนรูปแบบเพื่อวัตถุประสงค์ในการแก้ไขข้อบกพร่องได้ เช่น

ondata_request: function(req, res, data, next) {
  debug('****** plugin ondata_request');
  var translated_data = parser.toJson(data);
  debug('****** plugin ondata_response: translated_json: ' + translated_json);
  next(null, translated_data);
},

เกี่ยวกับคำสั่งเรียกใช้ตัวแฮนเดิลปลั๊กอิน

หากเขียนปลั๊กอินสำหรับ Edge Microgateway คุณจะต้องทำความเข้าใจลำดับในการเรียกใช้เครื่องจัดการเหตุการณ์ของปลั๊กอิน

สิ่งสำคัญที่ต้องจำไว้คือเมื่อคุณระบุลำดับปลั๊กอินในไฟล์การกำหนดค่า Edge Microgateway ตัวแฮนเดิลคำขอจะดำเนินการตามลำดับจากน้อยไปมาก ในขณะที่เครื่องจัดการการตอบกลับจะดำเนินการตามลำดับมากไปน้อย

ตัวอย่างต่อไปนี้ได้รับการออกแบบมาเพื่อช่วยให้คุณเข้าใจลำดับการดำเนินการ

1. สร้างปลั๊กอินง่ายๆ 3 รายการ

ลองใช้ปลั๊กอินต่อไปนี้ สิ่งที่ทำได้ทั้งหมดคือเอาต์พุตของคอนโซลการพิมพ์เมื่อมีการเรียกใช้เครื่องจัดการเหตุการณ์

plugins/plugin-1/index.js

module.exports.init = function(config, logger, stats) {

  return {

    onrequest: function(req, res, next) {
      console.log('plugin-1: onrequest');
      next();
    },

    onend_request: function(req, res, data, next) {
      console.log('plugin-1: onend_request');
      next(null, data);
    },

    ondata_response: function(req, res, data, next) {
      console.log('plugin-1: ondata_response ' + data.length);
      next(null, data);
    },

    onend_response: function(req, res, data, next) {
      console.log('plugin-1: onend_response');
      next(null, data);
    }
  };
}

ตอนนี้ลองสร้างปลั๊กอินเพิ่มเติม 2 รายการ คือ plugin-2 และ plugin-3 ด้วยโค้ดเดียวกัน (ยกเว้นเปลี่ยนคำสั่ง console.log() เป็น plugin-2 และ plugin-3 ตามลำดับ)

2. ตรวจสอบโค้ดปลั๊กอิน

ฟังก์ชันปลั๊กอินที่ส่งออกใน <microgateway-root-dir>/plugins/plugin-1/index.js คือตัวแฮนเดิลเหตุการณ์ที่เรียกใช้ ณ เวลาใดเวลาหนึ่งระหว่างการประมวลผลคำขอและการตอบกลับ เช่น onrequest จะดำเนินการกับไบต์แรกของส่วนหัวของคำขอ ขณะที่ onend_response จะทำงานหลังจากได้รับข้อมูลการตอบกลับไบต์สุดท้าย

ลองดูเครื่องจัดการ ondata_Response ระบบจะเรียกใช้เครื่องจัดการเมื่อได้รับข้อมูลการตอบกลับเป็นกลุ่ม สิ่งสำคัญที่ควรทราบคือข้อมูลคำตอบไม่จำเป็นต้องได้รับพร้อมกันทั้งหมด แต่ข้อมูลอาจได้รับเป็นกลุ่มที่มีความยาวเท่าใดก็ได้ตามต้องการ

3. เพิ่มปลั๊กอินลงในลำดับปลั๊กอิน

เราจะเพิ่มปลั๊กอินไปยังลําดับปลั๊กอินในไฟล์การกําหนดค่า Edge Microgateway (~./edgemicro/config.yaml) ตามตัวอย่างนี้ ลำดับเป็นสิ่งสำคัญ โดยกำหนดลำดับการดำเนินการของเครื่องจัดการปลั๊กอิน

  plugins:
    dir: ../plugins
    sequence:
      - plugin-1
      - plugin-2
      - plugin-3
  

4. ตรวจสอบผลลัพธ์การแก้ไขข้อบกพร่อง

ต่อไปเรามาดูเอาต์พุตที่จะเกิดขึ้นเมื่อมีการเรียกปลั๊กอินเหล่านี้กัน โดยมีเรื่องสำคัญ 2-3 อย่างที่ควรทราบ ดังนี้

  • ลำดับปลั๊กอินที่ไฟล์การกำหนดค่า Edge Microgateway (~./edgemicro/config.yaml) ระบุลำดับในการเรียกใช้เครื่องจัดการเหตุการณ์
  • ระบบจะเรียกใช้เครื่องจัดการคำขอตามลำดับจากน้อยไปมาก (ลำดับที่ปรากฏในลำดับปลั๊กอิน ได้แก่ 1, 2, 3)
  • ระบบจะเรียกใช้เครื่องจัดการการตอบกลับตามลำดับจากมากไปน้อย นั่นคือ 3, 2, 1
  • ระบบจะเรียกใช้เครื่องจัดการ ondata_response 1 ครั้งสำหรับข้อมูลแต่ละกลุ่มที่เข้ามา ในตัวอย่างนี้ (เอาต์พุตที่แสดงด้านล่าง) ได้รับข้อมูล 2 ส่วน

ต่อไปนี้คือตัวอย่างเอาต์พุตของการแก้ไขข้อบกพร่องที่สร้างขึ้นเมื่อใช้งานปลั๊กอิน 3 ตัวนี้และมีการส่งคำขอผ่าน Edge Microgateway โดยให้สังเกตลำดับที่มีการเรียกเครื่องจัดการดังนี้

  plugin-1: onrequest
  plugin-2: onrequest
  plugin-3: onrequest

  plugin-1: onend_request
  plugin-2: onend_request
  plugin-3: onend_request

  plugin-3: ondata_response 931
  plugin-2: ondata_response 931
  plugin-1: ondata_response 931

  plugin-3: ondata_response 1808
  plugin-3: onend_response

  plugin-2: ondata_response 1808
  plugin-2: onend_response

  plugin-1: ondata_response 1808
  plugin-1: onend_response

สรุป

การทำความเข้าใจลำดับการเรียกใช้ตัวแฮนเดิลปลั๊กอินมีความสำคัญมากเมื่อพยายามใช้ฟังก์ชันของปลั๊กอินที่กำหนดเอง เช่น การสะสมและการเปลี่ยนรูปแบบข้อมูลคำขอหรือการตอบกลับ

โปรดทราบว่าตัวแฮนเดิลคำขอจะทำงานตามลำดับที่ระบุปลั๊กอินในไฟล์การกำหนดค่า Edge Microgateway และเรียกใช้งานเครื่องจัดการการตอบกลับตามลำดับที่ตรงข้ามกัน

เกี่ยวกับการใช้ตัวแปรร่วมในปลั๊กอิน

ทุกคำขอที่ส่งไปยัง Edge Microgateway จะส่งไปยังอินสแตนซ์เดียวกันของปลั๊กอิน ดังนั้นสถานะของคำขอที่ 2 จากไคลเอ็นต์อื่นจะเขียนทับคำขอแรก ที่ปลอดภัยเพียงแห่งเดียวในการบันทึกสถานะปลั๊กอินคือการจัดเก็บสถานะในพร็อพเพอร์ตี้ของออบเจ็กต์คำขอหรือออบเจ็กต์การตอบกลับ (ซึ่งจำกัดอายุการใช้งานตามอายุการใช้งานของคำขอนั้นๆ)

การเขียน URL เป้าหมายใหม่ในปลั๊กอิน

เพิ่มแล้วใน v2.3.3

คุณลบล้าง URL เป้าหมายเริ่มต้นในปลั๊กอินแบบไดนามิกได้โดยแก้ไขตัวแปรเหล่านี้ในโค้ดปลั๊กอิน: req.targetHostname และ req.targetPath

เพิ่มแล้วใน v2.4.x

นอกจากนี้ คุณยังลบล้างพอร์ตปลายทางเป้าหมายและเลือกระหว่าง HTTP กับ HTTPS ได้ด้วย แก้ไขตัวแปรเหล่านี้ในโค้ดปลั๊กอิน: req.targetPort และ req.targetSecure หากต้องการเลือก HTTPS ให้ตั้งค่า req.targetSecure เป็น true สำหรับ HTTP ให้ตั้งค่าเป็น false หากคุณตั้งค่า req.targetSecure เป็น "จริง" โปรดดูข้อมูลเพิ่มเติมที่ชุดข้อความการสนทนานี้

มีการเพิ่มปลั๊กอินตัวอย่าง eurekaclient ลงใน Edge Microgateway ปลั๊กอินนี้สาธิตวิธีใช้ตัวแปร req.targetPort และ req.targetSecure และสาธิตวิธีที่ Edge Microgateway สามารถค้นหาปลายทางแบบไดนามิกโดยใช้ Eureka เป็นแคตตาล็อกปลายทางบริการ


ปลั๊กอินตัวอย่าง

ปลั๊กอินต่อไปนี้จะมาพร้อมกับการติดตั้ง Edge Microgateway โดยคุณสามารถดูการติดตั้ง Edge Microgateway ได้ที่นี่

[prefix]/lib/node_modules/edgemicro/plugins

โดยที่ [prefix] คือไดเรกทอรีคำนำหน้า npm ตามที่อธิบายใน " Edge Microgateway ได้รับการติดตั้งไว้ไว้ที่ใด" ใน การติดตั้ง Edge Microgateway

คำขอสะสม

ปลั๊กอินนี้จะรวบรวมชิ้นส่วนข้อมูลจากไคลเอ็นต์ไปไว้ในพร็อพเพอร์ตี้อาร์เรย์ที่แนบอยู่กับออบเจ็กต์คำขอ เมื่อได้รับข้อมูลคำขอทั้งหมดแล้ว อาร์เรย์จะเชื่อมต่ออยู่ในบัฟเฟอร์ ซึ่งจะส่งไปยังปลั๊กอินถัดไปในลำดับ ปลั๊กอินนี้ควรเป็นปลั๊กอินแรกในลำดับเพื่อให้ปลั๊กอินต่อๆ มาได้รับข้อมูลคำขอที่รวบรวมไว้

module.exports.init = function(config, logger, stats) {

  function accumulate(req, data) {

    if (!req._chunks) req._chunks = [];
    req._chunks.push(data);

  }

  return {

    ondata_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      next(null, null);

    },


    onend_request: function(req, res, data, next) {

      if (data && data.length > 0) accumulate(req, data);

      var content = null;

      if (req._chunks && req._chunks.length) {

        content = Buffer.concat(req._chunks);

      }

      delete req._chunks;

      next(null, content);

    }

  };

}

คำตอบสะสม

ปลั๊กอินนี้จะรวบรวมชิ้นส่วนข้อมูลจากเป้าหมายลงในพร็อพเพอร์ตี้อาร์เรย์ที่แนบอยู่กับออบเจ็กต์ Response เมื่อได้รับข้อมูลคำตอบทั้งหมดแล้ว อาร์เรย์จะเชื่อมต่ออยู่ในบัฟเฟอร์ซึ่งจะส่งไปยังปลั๊กอินถัดไปในลำดับ เนื่องจากปลั๊กอินนี้ทำงานบนคำตอบ ซึ่งจะได้รับการประมวลผลแบบย้อนกลับ คุณจึงควรจัดตำแหน่งปลั๊กอินนี้เป็นปลั๊กอินสุดท้ายในลำดับ

module.exports.init = function(config, logger, stats) {

  function accumulate(res, data) {
    if (!res._chunks) res._chunks = [];
    res._chunks.push(data);
  }

  return {

    ondata_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      next(null, null);
    },

    onend_response: function(req, res, data, next) {
      if (data && data.length > 0) accumulate(res, data);
      var content = Buffer.concat(res._chunks);
      delete res._chunks;
      next(null, content);
    }

  };

}

ปลั๊กอินส่วนหัวตัวพิมพ์ใหญ่

การกระจาย Edge Microgateway มีตัวอย่างปลั๊กอินที่ชื่อว่า <microgateway-root-dir>/plugins/header-uppercase โดยตัวอย่างจะมีความคิดเห็นที่อธิบายเครื่องจัดการฟังก์ชันแต่ละตัว ตัวอย่างนี้แปลงข้อมูลอย่างง่ายของการตอบสนองเป้าหมายและเพิ่มส่วนหัวที่กำหนดเองไปยังคำขอของไคลเอ็นต์และการตอบสนองเป้าหมาย

นี่คือซอร์สโค้ดของ <microgateway-root-dir>/plugins/header-uppercase/index.js

'use strict';

var debug = require('debug')('plugin:header-uppercase');

// required
module.exports.init = function(config, logger, stats) {

  var counter = 0;

  return {

    // indicates start of client request
    // request headers, url, query params, method should be available at this time
    // request processing stops (and a target request is not initiated) if
    // next is called with a truthy first argument (an instance of Error, for example)
    onrequest: function(req, res, next) {
      debug('plugin onrequest');
      req.headers['x-foo-request-id'] = counter++;
      req.headers['x-foo-request-start'] = Date.now();
      next();
    },

    // indicates start of target response
    // response headers and status code should be available at this time
    onresponse: function(req, res, next) {
      debug('plugin onresponse');
      res.setHeader('x-foo-response-id', req.headers['x-foo-request-id']);
      res.setHeader('x-foo-response-time', Date.now() - req.headers['x-foo-request-start']);
      next();
    },

    // chunk of request body data received from client
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the target
    ondata_request: function(req, res, data, next) {
      debug('plugin ondata_request ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // chunk of response body data received from target
    // should return (potentially) transformed data for next plugin in chain
    // the returned value from the last plugin in the chain is written to the client
    ondata_response: function(req, res, data, next) {
      debug('plugin ondata_response ' + data.length);
      var transformed = data.toString().toUpperCase();
      next(null, transformed);
    },

    // indicates end of client request
    onend_request: function(req, res, data, next) {
      debug('plugin onend_request');
      next(null, data);
    },

    // indicates end of target response
    onend_response: function(req, res, data, next) {
      debug('plugin onend_response');
      next(null, data);
    },

    // error receiving client request
    onerror_request: function(req, res, err, next) {
      debug('plugin onerror_request ' + err);
      next();
    },

    // error receiving target response
    onerror_response: function(req, res, err, next) {
      debug('plugin onerror_response ' + err);
      next();
    },

    // indicates client connection closed
    onclose_request: function(req, res, next) {
      debug('plugin onclose_request');
      next();
    },

    // indicates target connection closed
    onclose_response: function(req, res, next) {
      debug('plugin onclose_response');
      next();
    }

  };

}


เปลี่ยนรูปแบบอักษรตัวพิมพ์ใหญ่

นี่คือปลั๊กอินการเปลี่ยนรูปแบบทั่วไปที่คุณแก้ไขเพื่อทำการเปลี่ยนรูปแบบใดก็ได้ที่ต้องการ ตัวอย่างนี้ เพียงแค่เปลี่ยนการตอบกลับและข้อมูลคำขอเป็นตัวพิมพ์ใหญ่

 */
module.exports.init = function(config, logger, stats) {

  // perform content transformation here
  // the result of the transformation must be another Buffer
  function transform(data) {
    return new Buffer(data.toString().toUpperCase());
  }

  return {

    ondata_response: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_response: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    },

    ondata_request: function(req, res, data, next) {
      // transform each chunk as it is received
      next(null, data ? transform(data) : null);
    },

    onend_request: function(req, res, data, next) {
      // transform accumulated data, if any
      next(null, data ? transform(data) : null);
    }

  };

}