# 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
- Routing
- Flow Control
- Open documentation
# 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: {}
}]
}
}