# System structure

  • Overall architecture diagram

  • Service orchestration architecture diagram

# Service list

Module Project name Port
gateway node fizz-gateway-node 8600
Management backend fizz-manager-professional 8000

# Middleware list

Resource Type Database
Redis 10
MySQL fizz-manager

# Database Design

# Mysql

# E-R diagram

  • Service orchestration

FizzGate management background-aggregate[service orchestration]

  • Routing

FizzGate management background-api[routing]

  • Flow Control

FizzGate management background-flow_control[flow control]

  • Open documentation

FizzGate Management Backend-open_doc[Open Document]

# Middleware

# Redis

key key Chinese name value type description
fizz_api_config_route api configuration hash api configuration key to store Hash
fizz_api_config_app_set_size api configures the number of app sets hash api configures the number of app sets and stores the Hash Key
fizz_aggregate_config Aggregation configuration hash Aggregation configuration stores the key of Hash
fizz_rpc_service RPC service information hash RPC service information stores the Hash Key
fizz_app Application permissions hash RPC service information storage Hash Key
fizz_gateway_group Gateway group hash Gateway group stores the key of Hash
fizz_plugin_config Plug-in hash Plug-in stores the key of Hash
fizz_api_pairing_doc Document set pairing configuration hash Document set pairing configuration stores the key of Hash
fizz_rate_limit Flow control configuration hash Flow control configuration stores the key of Hash
fizz_api_config_app:%s_%s api configuration app set api configuration app stores the Key mode of Set {fizz_api_config_app:apiId_index}
fizz_manager_url Management backend address string Management backend address
fizz_api_pairing_info Pairing information hash Pairing information stores the Hash Key
fizz_global_resource Public parameters hash Public parameters store the key of Hash

# MQ Design

Message type TAG GID BODY field description Description
Redis fizz_api_config_channel_route api configuration Channel
Redis fizz_api_config_app_channel api configuration app associated Channel
Redis fizz_plugin_config_channel Plug-in fixed configuration Channel
Redis fizz_aggregate_channel Aggregation configuration Channel
Redis fizz_rpc_service_channel RPC service information Channel
Redis fizz_app_channel Application permissionChannel
Redis fizz_gateway_group_channel Gateway group Channel
Redis fizz_api_pairing_doc_channel Document set pairing configuration Channel
Redis fizz_rate_limit_channel Flow control configuration Channel
Redis fizz_global_resource_channel Public parameter Channel
Redis fizz_api_pairing_info_channel Pairing information Channel

【Illustrate】

  • Message type: kafka, rocketMq, activeMq, Redis
  • TAG*: refers to Topic*
  • GID*: refers to the consumer group*
  • BODY*: The specific format of the message. To facilitate expansion, it is usually in JSON format. Consumers need to consider compatibility with possible extensions of the JSON message body*
  • Description: Describe the message

# Service orchestration design

# Configuration file design

//Interface configuration
export const aggrAPIConfig = {
   name: "input name", // Customized aggregate interface name
   debug: false, // Whether it is debug mode, the default is false (has been abandoned after v1.1.4, set debugMode uniformly in the list)
   type: "REQUEST", // type, REQUEST/MYSQL
   method: "GET", // HTTP method, GET/POST, etc.
   path: "/aggr/aggr-hotel/hotel/rates", // Format: /aggr/+group name+path, the group name starts with aggr-, indicating the aggregation interface
   headersDef: { // Optional, define some parameters of the header of the aggregation interface, using JSON Schema specification (see: http://json-schema.org/specification.html) for parameter verification and interface document generation
     "type": [
       "object",
       "null"
     ],
     "properties": {
       appId: {
         type: "string",
         title: "Application ID",
         description: "Description"
       }
     },
     "required": ["appId"]
   },
   paramsDef: { // Optional, define some parameters of the aggregate interface parameter, using JSON Schema specification (see: http://json-schema.org/specification.html for details), for parameter verification and interface document generation
     "type": [
       "object",
       "null"
     ],
     "properties": {
       lang: {
         type: "string",
         title: "Language",
         description: "Description"
       }
     },
     "required": []
   },
   bodyDef: { // Optional, define some parameters of the body of the aggregate interface, using JSON Schema specification (see: http://json-schema.org/specification.html) for parameter verification and interface document generation
     "type": [
       "object",
       "null"
     ],
     "properties": {
       userId: {
         type: "string",
         title: "username",
         description: "Description"
       }
     },
     "required": ["userId"]
   },
   // TODO (all script related are processed in the same way) The script content is stored separately, and the passed parameters are replaced with the script id.
   scriptValidate: { // Optional, used for parameter verification scenarios that cannot be covered by headersDef, paramsDef, and bodyDef.
     "aggregate_config_script_id": 12
     //The following is the specific content of the script
     // type: "", // groovy
     // source: "", // The script returns a List<String> object, null: verification passed, List: error message list
     // consts: { // constants
     // },
     // variables: { // environment variables
     // }
   },
   validateResponse: {// Input parameter verification failure response, the processing method is the same as dataMapping.response
     fixedBody: { // fixed body
       "code": -411
     },
     fixedHeaders: {// Fixed headers
       "a": "b"
     },
     headers: { // Referenced headers
     },
     body: { // Referenced header
       "errorMsg": "string validateMsg", //Default value
     },
     script: {
       "aggregate_config_script_id": 2
     }
   },
   langDef: {
     "langParam": "input.request.body.languageCode",
     "langMapping": {
       "zh": "0",
       "en": "1"
     }
   },
   dataMapping: {//Aggregation interface data conversion rules
     response: {
       fixedBody: { // fixed body
         "code": "b"
       },
       fixedHeaders: {// Fixed headers
         "a": "b"
       },
       headers: { // The referenced header defaults to the source data type. If you want to convert the type, it starts with the target type + space, such as: "int "
         "abc": "int step1.requests.request1.headers.xyz"
       },
       body: { // The referenced header defaults to the source data type. If you want to convert the type, it starts with the target type + space, such as: "int "
         "abc": "int step1.requests.request1.response.id",
         "inn.innName": "step1.requests.request2.response.hotelName",
       },
       script: { // Script calculates the value of body
         "aggregate_config_script_id": 1
         // The script content is stored separately and replaced with the script id.
         // type: "", // groovy
         // source: ""
       }
     }
   },
   stepConfigs: [{ // step configuration
     name: "step1", // step name
     stop: false, // Whether to return after executing the current step
     dataMapping: {// step response data conversion rules configuration results
       response: {
         fixedBody: { // fixed body
           "a": "b"
         },
         body: { // step result
           "abc": "step1.requests.request1.response.id",
           "inn.innName": "step1.requests.request2.response.hotelName"
         },
         script: {// Script calculates the value of body
           "aggregate_config_script_id": 1
           // The script content is stored separately and replaced with the script id.
           // type: "", // groovy
           // source: ""
         }
       }
     },
 
     //Add component
     components: [
       {
         "type": "condition",
         "desc": "For example: determine whether a member is a member",
         "value1": {
           "type": "fixed/ref",
           "fixedDataType": "", // Fixed value data type: number/string/boolean
           "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
           "value": null
         },
         // Comparison operator: eq gt ge lt le ne contains notContain containsAny isNull isNotNull isBlank isNotBlank isEmpty isNotEmpty
         "operator": "",
         "value2": {
           "type": "", // Fixed value: fixed Reference value: ref
           "fixedDataType": "", // Fixed value data type: number/string/boolean
           "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
           "value": null
         }
       },
       {
         "type": "circle",
         "desc": "", // Description For example: loop call 10 times
         "dataSourceType": "", // Fixed value: fixed Reference value: ref
         "dataSource": "", // int or string
         // Loop condition
         "execConditions": [
           {
             "type": "condition",
             "desc": "", // Description: For example: Determine whether a member is a member
             "value1": {
               "type": "fixed/ref",
               "fixedDataType": "", // Fixed value data type: number/string/boolean
               "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
               "value": null
             },
             // Comparison operator: eq gt ge lt le ne contains notContain containsAny isNull isNotNull isBlank isNotBlank isEmpty isNotEmpty
             "operator": "",
             "value2": {
               "type": "fixed/ref",
               "fixedDataType": "", // Fixed value data type: number/string/boolean
               "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
               "value": null
             }
           }
         ],
         //Exit condition
         "breakConditions": [
           {
             "type": "condition",
             "desc": "For example: determine whether a member is a member",
             "value1": {
               "type": "fixed/ref",
               "fixedDataType": "", // Fixed value data type: number/string/boolean
               "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
               "value": null
             },
             //Comparison symbols: eq gt ge lt le ne contains notContain containsAny isNull isNotNull isBlank isNotBlank isEmpty isNotEmpty
             "operator": "",
             "value2": {
               "type": "fixed/ref",
               "fixedDataType": "", // Fixed value data type: number/string/boolean
               "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
               "value": null
             }
           }
         ]
       }
     ],
 
     requests: [ //Each step can call multiple interfaces
       {
         name: "request1", //Interface name, format request+N
         type: "REQUEST", // Type, RESTful interface-REQUEST | Dubbo interface-DUBBO | gRPC interface-GRPC
         serviceName: 'com.abc.UserService', // [Dobbo/gRPC interface]
         version: '1.2', // Dubbo only
         group: '', // Dubbo only
         paramTypes: 'int,java.lang.String,com.abc.entity.Depart', // Dubbo only
         method: "GET", // [RESTful interface] HTTP method, GET/POST, etc.
         // 'method': 'getUserInfo', // [Dobbo/gRPC interface] Custom methods: such as 'getUserInfo' already has reusable fields
         url: "", // [RESTful interface only] Default url, used when the environment url is null
         devUrl: "http://baidu.com", // RESTful interface only
         testUrl: "http://baidu.com", // RESTful interface only
         preUrl: "http://baidu.com", // RESTful interface only
         prodUrl: "http://baidu.com", // RESTful interface only
         timeout: 3000, // The timeout unit is milliseconds, allowing a value between 1-10000 seconds. If left blank or less than 1 millisecond, the default value is 3 seconds. If it is greater than 10 seconds, the default value is 10 seconds.
         condition: { // Preprocessing script configuration
           "aggregate_config_script_id": 1
         },
         fallback: {
           mode: "stop", // stop|continue whether to continue execution when the request fails
           defaultResult: "" // When mode=continue, you can set the default response message (json string)
         },
         dataMapping: { // Data conversion rules
           request: {
             fixedBody: {},
             fixedHeaders: {},
             fixedParams: {},
             headers: {//The default is the source data type. If you want to convert the type, start with the target type + space, such as: "int "
               "abc": "step1.requests.request1.headers.xyz"
             },
             body: {
               "*": "input.request.body", // * Used to transparently transmit a json object
               "inn.innId": "step1.requests.request1.response.id" // The default is the source data type. If you want to convert the type, start with the target type + space, such as: "int "
             },
             params: {//The default is the source data type. If you want to convert the type, start with the target type + space, such as: "int "
               "userId": "input.requestBody.userId"
             },
             script: {// Script calculates the value of body
               "aggregate_config_script_id": 1
               // The script content is stored separately and replaced with the script id.
               // type: "", // groovy
               // source: "",
             }
           },
           response: {
             fixedBody: {},
             fixedHeaders: {},
             headers: {
               "abc": "step1.requests.request1.headers.xyz"
             },
             body: {
               "inn.innId": "step1.requests.request1.response.id"
             },
             script: {// Script calculates the value of body
               "aggregate_config_script_id": 1
               // The script content is stored separately and replaced with the script id.
               // type: "", // groovy
               // source: ""
             }
           },
           //Add component (in request)
           components: [
             {
               "type": "condition",
               "desc": "For example: determine whether a member is a member",
               "value1": {
                 "type": "fixed/ref",
                 "fixedDataType": "", // Fixed value data type: number/string/boolean
                 "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
                 "value": null
               },
               // Comparison operator: eq gt ge lt le ne contains notContain containsAny isNull isNotNull isBlank isNotBlank isEmpty isNotEmpty
               "operator": "",
               "value2": {
                 "type": "", // Fixed value: fixed Reference value: ref
                 "fixedDataType": "", // Fixed value data type: number/string/boolean
                 "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
                 "value": null
               }
             },
             {
               "type": "circle",
               "desc": "", // Description For example: loop call 10 times
               "dataSourceType": "", // Fixed value: fixed Reference value: ref
               "dataSource": "", // int or string
               // Loop condition
               "execConditions": [
                 {
                   "type": "condition",
                   "desc": "", // Description: For example: Determine whether a member is a member
                   "value1": {
                     "type": "fixed/ref",
                     "fixedDataType": "", // Fixed value data type: number/string/boolean
                     "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
                     "value": null
                   },
                   // Comparison operator: eq gt ge lt le ne contains notContain containsAny isNull isNotNull isBlank isNotBlank isEmpty isNotEmpty
                   "operator": "",
                   "value2": {
                     "type": "fixed/ref",
                     "fixedDataType": "", // Fixed value data type: number/string/boolean
                     "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
                     "value": null
                   }
                 }
               ],
               //Exit condition
               "breakConditions": [
                 {
                   "type": "condition",
                   "desc": "For example: determine whether a member is a member",
                   "value1": {
                     "type": "fixed/ref",
                     "fixedDataType": "", // Fixed value data type: number/string/boolean
                     "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
                     "value": null
                   },
                   //Comparison symbols: eq gt ge lt le ne contains notContain containsAny isNull isNotNull isBlank isNotBlank isEmpty isNotEmpty
                   "operator": "",
                   "value2": {
                     "type": "fixed/ref",
                     "fixedDataType": "", // Fixed value data type: number/string/boolean
                     "refDataType": "", // Data type of reference value: int/long/float/double/string/boolean/array
                     "value": null
                   }
                 }
               ]
             }
           ]
         }
         }
     ]
   }]
};

# Contextual design

//Context data structure design
//Context, used to save customer input and output and the input and output results of each step
var context = {
     //Whether DEBUG mode
     debug: false,
     // The time taken for each operation
     elapsedTimes: [{
         [actionName]: 123, // Operation name: Time-consuming
     }],
 
     // exception info
     exceptionMessage: "",
     exceptionStacks: "",
     exceptionData: "",
 
     //Customer input and interface return results
     input: {
         request: {
             path: "",
             method: "GET/POST",
             headers: {},
             body: {},
             params: {}
         },
         response: { // Response of aggregate interface
             headers: {},
             body: {}
         }
     },
     // steps
     step1: {
         requests: { //Interface 1
             request1: { // Request related parameters
                 request: {
                     url: "",
                     method: "GET/POST",
                     headers: {},
                     body: {}
                 },
                 //Interface response converted according to conversion rules
                 response: {
                     headers: {},
                     body: {}
                 },
                 // Request the current loop object of the loop component
                 item: null,
                 // Request the subscript of the current loop object of the loop component
                 index: null,
                 //Request the result of the loop
                 circle: [{
                     // loop object
                     item: null,
                     //The subscript of the loop object
                     index: null,
                     //Request related parameters
                     request: {
                         url: "",
                         method: "GET/POST",
                         headers: {},
                         body: {}
                     },
                     //Interface response converted according to conversion rules
                     response: {
                         headers: {},
                         body: {}
                     }
                 }],
                 //Execution result of conditional component
                 conditionResults: [
                     {
                         'My condition 1': true
                     }
                 ]
             },
             //Interface 2
             request2: {
                 // ... field gateway interface 1
             }
             //...Other interfaces, fields are the same as above
         },
         // step result
         result: {},
         //The current loop object of the step loop component
         item: null,
         //The subscript of the current loop object of the step loop component
         index: null,
         // Result of step loop
         circle: [{
             // loop object
             item: null,
             //The subscript of the loop object
             index: null,
             // step result
             result: {}
         }]
     }
}