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

คุณกําลังดูเอกสาร Apigee Edge
ดูเอกสารประกอบเกี่ยวกับ Apigee X

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

ผู้ชม

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

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

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

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

ตําแหน่งที่จะวางโค้ดปลั๊กอินที่กําหนดเอง

โฟลเดอร์สําหรับปลั๊กอินที่กําหนดเองจะรวมอยู่ในการติดตั้ง 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

เขียนปลั๊กอินที่เรียบง่าย

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

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

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

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

  3. สร้างโปรเจ็กต์ปลั๊กอินใหม่ที่ชื่อว่า response-override และ cd ให้กับโปรเจ็กต์ดังกล่าว
    mkdir response-override && cd response-override
    
  4. สร้างโปรเจ็กต์ Node.js ใหม่โดยดําเนินการดังนี้
    npm init
    
    Hit หลายๆ ครั้งเพื่อยอมรับค่าเริ่มต้น
  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 ฟังก์ชัน

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

ตัวอย่าง:

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

ondata_request ฟังก์ชัน

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

ตัวอย่าง:

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

onend_request ฟังก์ชัน

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

ตัวอย่าง:

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

ตัวบันทึก

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

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

สถิติ

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

  • 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 เป็นอาร์กิวเมนต์ที่ผิดพลาด กล่าวคือไม่มีข้อผิดพลาด และจะดําเนินการตามคําขอตามปกติ หากอาร์กิวเมนต์นี้เป็นจริง (เช่น ออบเจ็กต์ข้อผิดพลาด) ให้หยุดคําขอและส่งคําขอไปยังเป้าหมาย

พารามิเตอร์ที่ 2 จะส่งข้อมูลคําขอไปยังฟังก์ชันถัดไปในเชน หากคุณไม่ประมวลผลเพิ่มเติม ระบบจะส่งข้อมูลคําขอไปยังเป้าหมายของ API อย่างไรก็ตาม คุณมีโอกาสแก้ไขข้อมูลคําขอภายในวิธีนี้ แล้วส่งต่อคําขอที่แก้ไขแล้วไปยังเป้าหมาย ตัวอย่างเช่น หากข้อมูลคําขอคือ XML และเป้าหมายคาดหวังให้ JSON คุณอาจเพิ่มโค้ดลงในเมธอด ondata_request() ที่ (ก) เปลี่ยนประเภทเนื้อหาของส่วนหัวคําขอเป็น 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() ไปยังฟังก์ชันถัดไปในห่วงโซ่คําขอ ก่อนที่จะส่งไปยังเป้าหมายแบ็กเอนด์

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

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. ตรวจสอบเอาต์พุตของการแก้ไขข้อบกพร่อง

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

  • ลําดับปลั๊กอินที่ไฟล์การกําหนดค่า 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);

    }

  };

}

การตอบกลับสะสม

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

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);
    }

  };

}