Polish Sentinel dashboard frontend for cluster flow control enhancement
- Add cluster server list and assign page and client list page (for a specific app) Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
8d413e1645
commit
bf34f8b3be
|
|
@ -67,15 +67,15 @@ angular
|
|||
})
|
||||
|
||||
.state('dashboard.flowV1', {
|
||||
templateUrl: 'app/views/flow_old.html',
|
||||
url: '/v1/flow/:app',
|
||||
templateUrl: 'app/views/flow_v1.html',
|
||||
url: '/flow/:app',
|
||||
controller: 'FlowControllerV1',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/flow_old.js',
|
||||
'app/scripts/controllers/flow_v1.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
|
|
@ -83,15 +83,15 @@ angular
|
|||
})
|
||||
|
||||
.state('dashboard.flow', {
|
||||
templateUrl: 'app/views/flow.html',
|
||||
url: '/flow/:app',
|
||||
controller: 'FlowController',
|
||||
templateUrl: 'app/views/flow_v2.html',
|
||||
url: '/v2/flow/:app',
|
||||
controller: 'FlowControllerV2',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/flow.js',
|
||||
'app/scripts/controllers/flow_v2.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
|
|
@ -114,16 +114,64 @@ angular
|
|||
}
|
||||
})
|
||||
|
||||
.state('dashboard.clusterAll', {
|
||||
templateUrl: 'app/views/cluster.html',
|
||||
url: '/cluster/:app',
|
||||
controller: 'SentinelClusterController',
|
||||
.state('dashboard.clusterAppAssignManage', {
|
||||
templateUrl: 'app/views/cluster_app_assign_manage.html',
|
||||
url: '/cluster/assign_manage/:app',
|
||||
controller: 'SentinelClusterAppAssignManageController',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/cluster.js',
|
||||
'app/scripts/controllers/cluster_app_assign_manage.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
.state('dashboard.clusterAppServerList', {
|
||||
templateUrl: 'app/views/cluster_app_server_list.html',
|
||||
url: '/cluster/server/:app',
|
||||
controller: 'SentinelClusterAppServerListController',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/cluster_app_server_list.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
.state('dashboard.clusterAppClientList', {
|
||||
templateUrl: 'app/views/cluster_app_client_list.html',
|
||||
url: '/cluster/client/:app',
|
||||
controller: 'SentinelClusterAppTokenClientListController',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/cluster_app_token_client_list.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
.state('dashboard.clusterSingle', {
|
||||
templateUrl: 'app/views/cluster_single_config.html',
|
||||
url: '/cluster/single/:app',
|
||||
controller: 'SentinelClusterSingleController',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/cluster_single.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
|
|
@ -224,4 +272,4 @@ angular
|
|||
}]
|
||||
}
|
||||
});
|
||||
}]);
|
||||
}]);
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterAppAssignManageController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
const UNSUPPORTED_CODE = 4041;
|
||||
|
||||
const CLUSTER_MODE_CLIENT = 0;
|
||||
const CLUSTER_MODE_SERVER = 1;
|
||||
const DEFAULT_CLUSTER_SERVER_PORT = 18730;
|
||||
|
||||
$scope.tmp = {
|
||||
curClientChosen: [],
|
||||
curRemainingClientChosen: [],
|
||||
curChosenServer: {},
|
||||
};
|
||||
|
||||
function convertSetToString(set) {
|
||||
if (set === undefined) {
|
||||
return '';
|
||||
}
|
||||
let s = '';
|
||||
for (let i = 0; i < set.length; i++) {
|
||||
s = s + set[i];
|
||||
if (i < set.length - 1) {
|
||||
s = s + ',';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function convertStrToNamespaceSet(str) {
|
||||
if (str === undefined || str === '') {
|
||||
return [];
|
||||
}
|
||||
let arr = [];
|
||||
let spliced = str.split(',');
|
||||
spliced.forEach((v) => {
|
||||
arr.push(v.trim());
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
function processAppSingleData(data) {
|
||||
if (data.state.server && data.state.server.namespaceSet) {
|
||||
data.state.server.namespaceSetStr = convertSetToString(data.state.server.namespaceSet);
|
||||
data.mode = data.state.stateInfo.mode;
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromArr(arr, v) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i] === v) {
|
||||
arr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetChosen() {
|
||||
$scope.tmp.curClientChosen = [];
|
||||
$scope.tmp.curRemainingClientChosen = [];
|
||||
}
|
||||
|
||||
function generateMachineId(e) {
|
||||
return e.ip + '@' + e.commandPort;
|
||||
}
|
||||
|
||||
function applyClusterMap(appClusterMachineList) {
|
||||
if (!appClusterMachineList) {
|
||||
return;
|
||||
}
|
||||
let tmpMap = new Map();
|
||||
$scope.clusterMap = [];
|
||||
$scope.remainingClientAddressList = [];
|
||||
let tmpServerList = [];
|
||||
let tmpClientList = [];
|
||||
appClusterMachineList.forEach((e) => {
|
||||
if (e.mode === CLUSTER_MODE_CLIENT) {
|
||||
tmpClientList.push(e);
|
||||
} else if (e.mode === CLUSTER_MODE_SERVER) {
|
||||
tmpServerList.push(e);
|
||||
} else {
|
||||
$scope.remainingClientAddressList.push(generateMachineId(e));
|
||||
}
|
||||
});
|
||||
tmpServerList.forEach((e) => {
|
||||
let ip = e.ip;
|
||||
let machineId = ip + '@' + e.commandPort;
|
||||
let group = {
|
||||
ip: ip,
|
||||
machineId: machineId,
|
||||
port: e.state.server.port,
|
||||
clientSet: [],
|
||||
namespaceSetStr: e.state.server.namespaceSetStr,
|
||||
belongToApp: true,
|
||||
};
|
||||
if (!tmpMap.has(ip)) {
|
||||
tmpMap.set(ip, group);
|
||||
}
|
||||
});
|
||||
tmpClientList.forEach((e) => {
|
||||
let ip = e.ip;
|
||||
let machineId = ip + '@' + e.commandPort;
|
||||
|
||||
let targetServer = e.state.client.clientConfig.serverHost;
|
||||
let targetPort = e.state.client.clientConfig.serverPort;
|
||||
if (targetServer === undefined || targetServer === '' ||
|
||||
targetPort === undefined || targetPort <= 0) {
|
||||
$scope.remainingClientAddressList.push(generateMachineId(e));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tmpMap.has(targetServer)) {
|
||||
let group = {
|
||||
ip: targetServer,
|
||||
machineId: targetServer,
|
||||
port: targetPort,
|
||||
clientSet: [machineId],
|
||||
belongToApp: false,
|
||||
};
|
||||
tmpMap.set(targetServer, group);
|
||||
} else {
|
||||
let g = tmpMap.get(targetServer);
|
||||
g.clientSet.push(machineId);
|
||||
}
|
||||
});
|
||||
tmpMap.forEach((v) => {
|
||||
if (v !== undefined) {
|
||||
$scope.clusterMap.push(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.onCurrentServerChange = () => {
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
$scope.remainingClientAddressList = [];
|
||||
|
||||
$scope.moveToServerGroup = () => {
|
||||
let chosenServer = $scope.tmp.curChosenServer;
|
||||
if (!chosenServer || !chosenServer.machineId) {
|
||||
return;
|
||||
}
|
||||
$scope.tmp.curRemainingClientChosen.forEach(e => {
|
||||
chosenServer.clientSet.push(e);
|
||||
removeFromArr($scope.remainingClientAddressList, e);
|
||||
});
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
$scope.moveToRemainingSharePool = () => {
|
||||
$scope.tmp.curClientChosen.forEach(e => {
|
||||
$scope.remainingClientAddressList.push(e);
|
||||
removeFromArr($scope.tmp.curChosenServer.clientSet, e);
|
||||
});
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
function parseIpFromMachineId(machineId) {
|
||||
if (machineId.indexOf('@') === -1) {
|
||||
return machineId;
|
||||
}
|
||||
let arr = machineId.split('@');
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
$scope.addToServerList = () => {
|
||||
let group;
|
||||
$scope.tmp.curRemainingClientChosen.forEach(e => {
|
||||
group = {
|
||||
machineId: e,
|
||||
ip: parseIpFromMachineId(e),
|
||||
port: DEFAULT_CLUSTER_SERVER_PORT,
|
||||
clientSet: [],
|
||||
namespaceSetStr: 'default,' + $scope.app,
|
||||
belongToApp: true,
|
||||
};
|
||||
$scope.clusterMap.push(group);
|
||||
removeFromArr($scope.remainingClientAddressList, e);
|
||||
$scope.tmp.curChosenServer = group;
|
||||
});
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
$scope.removeFromServerList = () => {
|
||||
let chosenServer = $scope.tmp.curChosenServer;
|
||||
if (!chosenServer || !chosenServer.machineId) {
|
||||
return;
|
||||
}
|
||||
chosenServer.clientSet.forEach((e) => {
|
||||
if (e !== undefined) {
|
||||
$scope.remainingClientAddressList.push(e);
|
||||
}
|
||||
});
|
||||
|
||||
if (chosenServer.belongToApp || chosenServer.machineId.indexOf('@') !== -1) {
|
||||
$scope.remainingClientAddressList.push(chosenServer.machineId);
|
||||
} else {
|
||||
alert('提示:非本应用内机器将不会置回空闲列表中');
|
||||
}
|
||||
|
||||
removeFromArr($scope.clusterMap, chosenServer);
|
||||
|
||||
resetChosen();
|
||||
|
||||
if ($scope.clusterMap.length > 0) {
|
||||
$scope.tmp.curChosenServer = $scope.clusterMap[0];
|
||||
$scope.onCurrentServerChange();
|
||||
} else {
|
||||
$scope.tmp.curChosenServer = {};
|
||||
}
|
||||
};
|
||||
|
||||
function retrieveClusterAppInfo() {
|
||||
ClusterStateService.fetchClusterUniversalStateOfApp($scope.app).success(function (data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.appClusterMachineList = data.data;
|
||||
$scope.appClusterMachineList.forEach(processAppSingleData);
|
||||
applyClusterMap($scope.appClusterMachineList);
|
||||
if ($scope.clusterMap.length > 0) {
|
||||
$scope.tmp.curChosenServer = $scope.clusterMap[0];
|
||||
$scope.onCurrentServerChange();
|
||||
}
|
||||
} else {
|
||||
$scope.appClusterMachineList = {};
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
retrieveClusterAppInfo();
|
||||
|
||||
$scope.saveAndApplyAssign = () => {
|
||||
let ok = confirm('是否确认执行变更?');
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
let cm = $scope.clusterMap;
|
||||
if (!cm) {
|
||||
cm = [];
|
||||
}
|
||||
cm.forEach((e) => {
|
||||
e.namespaceSet = convertStrToNamespaceSet(e.namespaceSetStr);
|
||||
});
|
||||
cm.namespaceSet = convertStrToNamespaceSet(cm.namespaceSetStr);
|
||||
let request = {
|
||||
clusterMap: cm,
|
||||
remainingList: $scope.remainingClientAddressList,
|
||||
};
|
||||
ClusterStateService.applyClusterFullAssignOfApp($scope.app, request).success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
let failedServerSet = data.data.failedServerSet;
|
||||
let failedClientSet = data.data.failedClientSet;
|
||||
if (failedClientSet.length === 0 && failedServerSet.length === 0) {
|
||||
alert('全部推送成功');
|
||||
} else {
|
||||
alert('推送完毕。token server 失败列表:' + JSON.stringify(failedServerSet) +
|
||||
'; token client 失败列表:' + JSON.stringify(failedClientSet));
|
||||
}
|
||||
|
||||
retrieveClusterAppInfo();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('推送失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
alert('未知错误');
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
|
@ -0,0 +1,543 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterAppServerListController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
const UNSUPPORTED_CODE = 4041;
|
||||
|
||||
const CLUSTER_MODE_CLIENT = 0;
|
||||
const CLUSTER_MODE_SERVER = 1;
|
||||
const DEFAULT_CLUSTER_SERVER_PORT = 18730;
|
||||
const DEFAULT_NAMESPACE = 'default';
|
||||
const DEFAULT_MAX_ALLOWED_QPS = 20000;
|
||||
|
||||
// tmp for dialog temporary data.
|
||||
$scope.tmp = {
|
||||
curClientChosen: [],
|
||||
curRemainingClientChosen: [],
|
||||
curChosenServer: {},
|
||||
};
|
||||
|
||||
$scope.remainingMachineList = [];
|
||||
|
||||
function convertSetToString(set) {
|
||||
if (set === undefined) {
|
||||
return '';
|
||||
}
|
||||
if (set.length === 1 && set[0] === DEFAULT_NAMESPACE) {
|
||||
return DEFAULT_NAMESPACE;
|
||||
}
|
||||
let s = '';
|
||||
for (let i = 0; i < set.length; i++) {
|
||||
let ns = set[i];
|
||||
if (ns !== DEFAULT_NAMESPACE) {
|
||||
s = s + ns;
|
||||
if (i < set.length - 1) {
|
||||
s = s + ',';
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function convertStrToNamespaceSet(str) {
|
||||
if (str === undefined || str === '') {
|
||||
return [];
|
||||
}
|
||||
let arr = [];
|
||||
let spliced = str.split(',');
|
||||
spliced.forEach((v) => {
|
||||
arr.push(v.trim());
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
function processAppSingleData(data) {
|
||||
if (data.state.server && data.state.server.namespaceSet) {
|
||||
data.state.server.namespaceSetStr = convertSetToString(data.state.server.namespaceSet);
|
||||
data.mode = data.state.stateInfo.mode;
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromArr(arr, v) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i] === v) {
|
||||
arr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromArrIf(arr, f) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (f(arr[i]) === true) {
|
||||
arr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetAssignDialogChosen() {
|
||||
$scope.tmp.curClientChosen = [];
|
||||
$scope.tmp.curRemainingClientChosen = [];
|
||||
}
|
||||
|
||||
function generateMachineId(e) {
|
||||
return e.ip + '@' + e.commandPort;
|
||||
}
|
||||
|
||||
function applyClusterMap(appClusterMachineList) {
|
||||
if (!appClusterMachineList) {
|
||||
return;
|
||||
}
|
||||
let tmpMap = new Map();
|
||||
$scope.clusterMap = [];
|
||||
$scope.remainingMachineList = [];
|
||||
let tmpServerList = [];
|
||||
let tmpClientList = [];
|
||||
appClusterMachineList.forEach((e) => {
|
||||
if (e.mode === CLUSTER_MODE_CLIENT) {
|
||||
tmpClientList.push(e);
|
||||
} else if (e.mode === CLUSTER_MODE_SERVER) {
|
||||
tmpServerList.push(e);
|
||||
} else {
|
||||
$scope.remainingMachineList.push(generateMachineId(e));
|
||||
}
|
||||
});
|
||||
tmpServerList.forEach((e) => {
|
||||
let ip = e.ip;
|
||||
let machineId = ip + '@' + e.commandPort;
|
||||
let group = {
|
||||
ip: ip,
|
||||
machineId: machineId,
|
||||
port: e.state.server.port,
|
||||
clientSet: [],
|
||||
namespaceSetStr: e.state.server.namespaceSetStr,
|
||||
maxAllowedQps: e.state.server.flow.maxAllowedQps,
|
||||
belongToApp: true,
|
||||
};
|
||||
if (!tmpMap.has(ip)) {
|
||||
tmpMap.set(ip, group);
|
||||
}
|
||||
});
|
||||
tmpClientList.forEach((e) => {
|
||||
let ip = e.ip;
|
||||
let machineId = ip + '@' + e.commandPort;
|
||||
|
||||
let targetServer = e.state.client.clientConfig.serverHost;
|
||||
let targetPort = e.state.client.clientConfig.serverPort;
|
||||
if (targetServer === undefined || targetServer === '' ||
|
||||
targetPort === undefined || targetPort <= 0) {
|
||||
$scope.remainingMachineList.push(generateMachineId(e));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tmpMap.has(targetServer)) {
|
||||
let group = {
|
||||
ip: targetServer,
|
||||
machineId: targetServer,
|
||||
port: targetPort,
|
||||
clientSet: [machineId],
|
||||
belongToApp: false,
|
||||
};
|
||||
tmpMap.set(targetServer, group);
|
||||
} else {
|
||||
let g = tmpMap.get(targetServer);
|
||||
g.clientSet.push(machineId);
|
||||
}
|
||||
});
|
||||
tmpMap.forEach((v) => {
|
||||
if (v !== undefined) {
|
||||
$scope.clusterMap.push(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.notChosenServer = (id) => {
|
||||
return id !== $scope.serverAssignDialogData.serverData.currentServer;
|
||||
};
|
||||
|
||||
$scope.onCurrentServerChange = () => {
|
||||
resetAssignDialogChosen();
|
||||
};
|
||||
|
||||
$scope.moveToServerGroup = () => {
|
||||
$scope.tmp.curRemainingClientChosen.forEach(e => {
|
||||
$scope.serverAssignDialogData.serverData.clientSet.push(e);
|
||||
removeFromArr($scope.remainingMachineList, e);
|
||||
});
|
||||
resetAssignDialogChosen();
|
||||
};
|
||||
|
||||
$scope.moveToRemainingSharePool = () => {
|
||||
$scope.tmp.curClientChosen.forEach(e => {
|
||||
$scope.remainingMachineList.push(e);
|
||||
removeFromArr($scope.serverAssignDialogData.serverData.clientSet, e);
|
||||
});
|
||||
resetAssignDialogChosen();
|
||||
};
|
||||
|
||||
function parseIpFromMachineId(machineId) {
|
||||
if (machineId.indexOf('@') === -1) {
|
||||
return machineId;
|
||||
}
|
||||
let arr = machineId.split('@');
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
function retrieveClusterAssignInfoOfApp() {
|
||||
ClusterStateService.fetchClusterUniversalStateOfApp($scope.app).success(function (data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.appClusterMachineList = data.data;
|
||||
$scope.appClusterMachineList.forEach(processAppSingleData);
|
||||
applyClusterMap($scope.appClusterMachineList);
|
||||
} else {
|
||||
$scope.appClusterMachineList = {};
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$scope.newServerDialog = () => {
|
||||
retrieveClusterAssignInfoOfApp();
|
||||
$scope.serverAssignDialogData = {
|
||||
title: '新增 Token Server',
|
||||
type: 'add',
|
||||
confirmBtnText: '保存',
|
||||
serverData: {
|
||||
serverType: 0,
|
||||
clientSet: [],
|
||||
serverPort: DEFAULT_CLUSTER_SERVER_PORT,
|
||||
maxAllowedQps: DEFAULT_MAX_ALLOWED_QPS,
|
||||
}
|
||||
};
|
||||
$scope.serverAssignDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/cluster/cluster-server-assign-dialog.html',
|
||||
width: 1000,
|
||||
overlay: true,
|
||||
scope: $scope
|
||||
});
|
||||
};
|
||||
|
||||
$scope.modifyServerAssignConfig = (id) => {
|
||||
ClusterStateService.fetchClusterUniversalStateOfApp($scope.app).success(function (data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.appClusterMachineList = data.data;
|
||||
$scope.appClusterMachineList.forEach(processAppSingleData);
|
||||
applyClusterMap($scope.appClusterMachineList);
|
||||
let clusterMap = $scope.clusterMap;
|
||||
let d;
|
||||
for (let i = 0; i < clusterMap.length; i++) {
|
||||
if (clusterMap[i].machineId === id) {
|
||||
d = clusterMap[i];
|
||||
}
|
||||
}
|
||||
if (!d) {
|
||||
alert('状态错误');
|
||||
return;
|
||||
}
|
||||
$scope.serverAssignDialogData = {
|
||||
title: 'Token Server 分配编辑',
|
||||
type: 'edit',
|
||||
confirmBtnText: '保存',
|
||||
serverData: {
|
||||
currentServer: d.machineId,
|
||||
belongToApp: true,
|
||||
serverPort: d.port,
|
||||
clientSet: d.clientSet,
|
||||
}
|
||||
};
|
||||
if (d.maxAllowedQps !== undefined) {
|
||||
$scope.serverAssignDialogData.serverData.maxAllowedQps = d.maxAllowedQps;
|
||||
}
|
||||
$scope.serverAssignDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/cluster/cluster-server-assign-dialog.html',
|
||||
width: 1000,
|
||||
overlay: true,
|
||||
scope: $scope
|
||||
});
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
};
|
||||
|
||||
function getRemainingMachineList() {
|
||||
return $scope.remainingMachineList.filter((e) => $scope.notChosenServer(e));
|
||||
}
|
||||
|
||||
function doApplyNewSingleServerAssign() {
|
||||
let ok = confirm('是否确认执行变更?');
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
let serverData = $scope.serverAssignDialogData.serverData;
|
||||
let belongToApp = serverData.serverType == 0; // don't modify here!
|
||||
let machineId = serverData.currentServer;
|
||||
let request = {
|
||||
clusterMap: {
|
||||
machineId: machineId,
|
||||
ip: parseIpFromMachineId(machineId),
|
||||
port: serverData.serverPort,
|
||||
clientSet: serverData.clientSet,
|
||||
belongToApp: belongToApp,
|
||||
maxAllowedQps: serverData.maxAllowedQps,
|
||||
},
|
||||
remainingList: getRemainingMachineList(),
|
||||
};
|
||||
ClusterStateService.applyClusterSingleServerAssignOfApp($scope.app, request).success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
let failedServerSet = data.data.failedServerSet;
|
||||
let failedClientSet = data.data.failedClientSet;
|
||||
if (failedClientSet.length === 0 && failedServerSet.length === 0) {
|
||||
alert('全部推送成功');
|
||||
} else {
|
||||
let failedSet = [];
|
||||
if (failedServerSet) {
|
||||
failedServerSet.forEach((e) => {
|
||||
failedSet.push(e);
|
||||
});
|
||||
}
|
||||
if (failedClientSet) {
|
||||
failedClientSet.forEach((e) => {
|
||||
failedSet.push(e);
|
||||
});
|
||||
}
|
||||
|
||||
alert('推送完毕。失败机器列表:' + JSON.stringify(failedSet));
|
||||
}
|
||||
|
||||
location.reload();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('推送失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
alert('未知错误');
|
||||
});
|
||||
}
|
||||
|
||||
function doApplySingleServerAssignEdit() {
|
||||
let ok = confirm('是否确认执行变更?');
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
let serverData = $scope.serverAssignDialogData.serverData;
|
||||
let machineId = serverData.currentServer;
|
||||
let request = {
|
||||
clusterMap: {
|
||||
machineId: machineId,
|
||||
ip: parseIpFromMachineId(machineId),
|
||||
port: serverData.serverPort,
|
||||
clientSet: serverData.clientSet,
|
||||
belongToApp: serverData.belongToApp,
|
||||
},
|
||||
remainingList: $scope.remainingMachineList,
|
||||
};
|
||||
if (serverData.maxAllowedQps !== undefined) {
|
||||
request.clusterMap.maxAllowedQps = serverData.maxAllowedQps;
|
||||
}
|
||||
ClusterStateService.applyClusterSingleServerAssignOfApp($scope.app, request).success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
let failedServerSet = data.data.failedServerSet;
|
||||
let failedClientSet = data.data.failedClientSet;
|
||||
if (failedClientSet.length === 0 && failedServerSet.length === 0) {
|
||||
alert('全部推送成功');
|
||||
} else {
|
||||
let failedSet = [];
|
||||
failedServerSet.forEach(failedSet.push);
|
||||
failedClientSet.forEach(failedSet.push);
|
||||
alert('推送完毕。失败机器列表:' + JSON.stringify(failedSet));
|
||||
}
|
||||
|
||||
location.reload();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('推送失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
alert('未知错误');
|
||||
});
|
||||
}
|
||||
|
||||
$scope.saveAssignForDialog = () => {
|
||||
if (!checkAssignDialogValid()) {
|
||||
return;
|
||||
}
|
||||
if ($scope.serverAssignDialogData.type === 'add') {
|
||||
doApplyNewSingleServerAssign();
|
||||
} else if ($scope.serverAssignDialogData.type === 'edit') {
|
||||
doApplySingleServerAssignEdit();
|
||||
} else {
|
||||
alert('未知的操作');
|
||||
}
|
||||
};
|
||||
|
||||
function checkAssignDialogValid() {
|
||||
let serverData = $scope.serverAssignDialogData.serverData;
|
||||
if (serverData.currentServer === undefined || serverData.currentServer === '') {
|
||||
alert('请指定有效的 Token Server');
|
||||
return false;
|
||||
}
|
||||
if (serverData.serverPort === undefined || serverData.serverPort <= 0 || serverData.serverPort > 65535) {
|
||||
alert('请输入合法的端口值');
|
||||
return false;
|
||||
}
|
||||
if (serverData.maxAllowedQps !== undefined && serverData.maxAllowedQps < 0) {
|
||||
alert('请输入合法的最大允许 QPS');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$scope.viewConnectionDetail = (serverVO) => {
|
||||
$scope.connectionDetailDialogData = {
|
||||
serverData: serverVO
|
||||
};
|
||||
$scope.connectionDetailDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/cluster/cluster-server-connection-detail-dialog.html',
|
||||
width: 700,
|
||||
overlay: true,
|
||||
scope: $scope
|
||||
});
|
||||
};
|
||||
|
||||
function generateRequestLimitDataStr(limitData) {
|
||||
if (limitData.length === 1 && limitData[0].namespace === DEFAULT_NAMESPACE) {
|
||||
return 'default: ' + limitData[0].currentQps + ' / ' + limitData[0].maxAllowedQps;
|
||||
}
|
||||
for (let i = 0; i < limitData.length; i++) {
|
||||
let crl = limitData[i];
|
||||
if (crl.namespace === $scope.app) {
|
||||
return '' + crl.currentQps + ' / ' + crl.maxAllowedQps;
|
||||
}
|
||||
}
|
||||
return '0';
|
||||
}
|
||||
|
||||
function processServerListData(serverVO) {
|
||||
if (serverVO.state && serverVO.state.namespaceSet) {
|
||||
serverVO.state.namespaceSetStr = convertSetToString(serverVO.state.namespaceSet);
|
||||
}
|
||||
if (serverVO.state && serverVO.state.requestLimitData) {
|
||||
serverVO.state.requestLimitDataStr = generateRequestLimitDataStr(serverVO.state.requestLimitData);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.generateConnectionSet = (data) => {
|
||||
let connectionSet = data;
|
||||
let s = '';
|
||||
if (connectionSet) {
|
||||
s = s + '[';
|
||||
for (let i = 0; i < connectionSet.length; i++) {
|
||||
s = s + connectionSet[i].address;
|
||||
if (i < connectionSet.length - 1) {
|
||||
s = s + ', ';
|
||||
}
|
||||
}
|
||||
s = s + ']';
|
||||
} else {
|
||||
s = '[]';
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
function retrieveClusterServerInfo() {
|
||||
ClusterStateService.fetchClusterServerStateOfApp($scope.app).success(function (data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.serverVOList = data.data;
|
||||
$scope.serverVOList.forEach(processServerListData);
|
||||
|
||||
// if ($scope.serverVOList.length > 0) {
|
||||
// $scope.tmp.curChosenServer = $scope.serverVOList[0];
|
||||
// $scope.onChosenServerChange();
|
||||
// }
|
||||
} else {
|
||||
$scope.serverVOList = {};
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
retrieveClusterServerInfo();
|
||||
|
||||
let confirmUnbindServerDialog;
|
||||
$scope.unbindServer = (id) => {
|
||||
$scope.pendingUnbindIds = [id];
|
||||
$scope.confirmDialog = {
|
||||
title: '移除 Token Server',
|
||||
type: 'unbind_token_server',
|
||||
attentionTitle: '请确认是否移除以下 Token Server(该 server 下的 client 也会解除分配)',
|
||||
attention: id + '',
|
||||
confirmBtnText: '移除',
|
||||
};
|
||||
confirmUnbindServerDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/confirm-dialog.html',
|
||||
scope: $scope,
|
||||
overlay: true
|
||||
});
|
||||
};
|
||||
|
||||
function apiUnbindServerAssign(ids) {
|
||||
ClusterStateService.applyClusterServerBatchUnbind($scope.app, ids).success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
let failedServerSet = data.data.failedServerSet;
|
||||
let failedClientSet = data.data.failedClientSet;
|
||||
if (failedClientSet.length === 0 && failedServerSet.length === 0) {
|
||||
alert('成功');
|
||||
} else {
|
||||
alert('操作推送完毕,部分失败机器列表:' + JSON.stringify(failedClientSet));
|
||||
}
|
||||
|
||||
location.reload();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('推送失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
alert('未知错误');
|
||||
});
|
||||
// confirmUnbindServerDialog.close();
|
||||
}
|
||||
|
||||
// Confirm function for confirm dialog.
|
||||
$scope.confirm = () => {
|
||||
if ($scope.confirmDialog.type === 'unbind_token_server') {
|
||||
apiUnbindServerAssign($scope.pendingUnbindIds);
|
||||
} else {
|
||||
console.error('Error dialog when unbinding token server');
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterAppAssignManageController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
const UNSUPPORTED_CODE = 4041;
|
||||
|
||||
const CLUSTER_MODE_CLIENT = 0;
|
||||
const CLUSTER_MODE_SERVER = 1;
|
||||
const DEFAULT_CLUSTER_SERVER_PORT = 18730;
|
||||
|
||||
$scope.tmp = {
|
||||
curClientChosen: [],
|
||||
curRemainingClientChosen: [],
|
||||
curChosenServer: {},
|
||||
};
|
||||
|
||||
function convertSetToString(set) {
|
||||
if (set === undefined) {
|
||||
return '';
|
||||
}
|
||||
let s = '';
|
||||
for (let i = 0; i < set.length; i++) {
|
||||
s = s + set[i];
|
||||
if (i < set.length - 1) {
|
||||
s = s + ',';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function convertStrToNamespaceSet(str) {
|
||||
if (str === undefined || str === '') {
|
||||
return [];
|
||||
}
|
||||
let arr = [];
|
||||
let spliced = str.split(',');
|
||||
spliced.forEach((v) => {
|
||||
arr.push(v.trim());
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
function processAppSingleData(data) {
|
||||
if (data.state.server && data.state.server.namespaceSet) {
|
||||
data.state.server.namespaceSetStr = convertSetToString(data.state.server.namespaceSet);
|
||||
data.mode = data.state.stateInfo.mode;
|
||||
}
|
||||
}
|
||||
|
||||
function removeFromArr(arr, v) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i] === v) {
|
||||
arr.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resetChosen() {
|
||||
$scope.tmp.curClientChosen = [];
|
||||
$scope.tmp.curRemainingClientChosen = [];
|
||||
}
|
||||
|
||||
function generateMachineId(e) {
|
||||
return e.ip + '@' + e.commandPort;
|
||||
}
|
||||
|
||||
function applyClusterMap(appClusterMachineList) {
|
||||
if (!appClusterMachineList) {
|
||||
return;
|
||||
}
|
||||
let tmpMap = new Map();
|
||||
$scope.clusterMap = [];
|
||||
$scope.remainingClientAddressList = [];
|
||||
let tmpServerList = [];
|
||||
let tmpClientList = [];
|
||||
appClusterMachineList.forEach((e) => {
|
||||
if (e.mode === CLUSTER_MODE_CLIENT) {
|
||||
tmpClientList.push(e);
|
||||
} else if (e.mode === CLUSTER_MODE_SERVER) {
|
||||
tmpServerList.push(e);
|
||||
} else {
|
||||
$scope.remainingClientAddressList.push(generateMachineId(e));
|
||||
}
|
||||
});
|
||||
tmpServerList.forEach((e) => {
|
||||
let ip = e.ip;
|
||||
let machineId = ip + '@' + e.commandPort;
|
||||
let group = {
|
||||
ip: ip,
|
||||
machineId: machineId,
|
||||
port: e.state.server.port,
|
||||
clientSet: [],
|
||||
namespaceSetStr: e.state.server.namespaceSetStr,
|
||||
belongToApp: true,
|
||||
};
|
||||
if (!tmpMap.has(ip)) {
|
||||
tmpMap.set(ip, group);
|
||||
}
|
||||
});
|
||||
tmpClientList.forEach((e) => {
|
||||
let ip = e.ip;
|
||||
let machineId = ip + '@' + e.commandPort;
|
||||
|
||||
let targetServer = e.state.client.clientConfig.serverHost;
|
||||
let targetPort = e.state.client.clientConfig.serverPort;
|
||||
if (targetServer === undefined || targetServer === '' ||
|
||||
targetPort === undefined || targetPort <= 0) {
|
||||
$scope.remainingClientAddressList.push(generateMachineId(e));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tmpMap.has(targetServer)) {
|
||||
let group = {
|
||||
ip: targetServer,
|
||||
machineId: targetServer,
|
||||
port: targetPort,
|
||||
clientSet: [machineId],
|
||||
belongToApp: false,
|
||||
};
|
||||
tmpMap.set(targetServer, group);
|
||||
} else {
|
||||
let g = tmpMap.get(targetServer);
|
||||
g.clientSet.push(machineId);
|
||||
}
|
||||
});
|
||||
tmpMap.forEach((v) => {
|
||||
if (v !== undefined) {
|
||||
$scope.clusterMap.push(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.onCurrentServerChange = () => {
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
$scope.remainingClientAddressList = [];
|
||||
|
||||
$scope.moveToServerGroup = () => {
|
||||
let chosenServer = $scope.tmp.curChosenServer;
|
||||
if (!chosenServer || !chosenServer.machineId) {
|
||||
return;
|
||||
}
|
||||
$scope.tmp.curRemainingClientChosen.forEach(e => {
|
||||
chosenServer.clientSet.push(e);
|
||||
removeFromArr($scope.remainingClientAddressList, e);
|
||||
});
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
$scope.moveToRemainingSharePool = () => {
|
||||
$scope.tmp.curClientChosen.forEach(e => {
|
||||
$scope.remainingClientAddressList.push(e);
|
||||
removeFromArr($scope.tmp.curChosenServer.clientSet, e);
|
||||
});
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
function parseIpFromMachineId(machineId) {
|
||||
if (machineId.indexOf('@') === -1) {
|
||||
return machineId;
|
||||
}
|
||||
let arr = machineId.split('@');
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
$scope.addToServerList = () => {
|
||||
let group;
|
||||
$scope.tmp.curRemainingClientChosen.forEach(e => {
|
||||
group = {
|
||||
machineId: e,
|
||||
ip: parseIpFromMachineId(e),
|
||||
port: DEFAULT_CLUSTER_SERVER_PORT,
|
||||
clientSet: [],
|
||||
namespaceSetStr: 'default,' + $scope.app,
|
||||
belongToApp: true,
|
||||
};
|
||||
$scope.clusterMap.push(group);
|
||||
removeFromArr($scope.remainingClientAddressList, e);
|
||||
$scope.tmp.curChosenServer = group;
|
||||
});
|
||||
resetChosen();
|
||||
};
|
||||
|
||||
$scope.removeFromServerList = () => {
|
||||
let chosenServer = $scope.tmp.curChosenServer;
|
||||
if (!chosenServer || !chosenServer.machineId) {
|
||||
return;
|
||||
}
|
||||
chosenServer.clientSet.forEach((e) => {
|
||||
if (e !== undefined) {
|
||||
$scope.remainingClientAddressList.push(e);
|
||||
}
|
||||
});
|
||||
|
||||
if (chosenServer.belongToApp || chosenServer.machineId.indexOf('@') !== -1) {
|
||||
$scope.remainingClientAddressList.push(chosenServer.machineId);
|
||||
} else {
|
||||
alert('提示:非本应用内机器将不会置回空闲列表中');
|
||||
}
|
||||
|
||||
removeFromArr($scope.clusterMap, chosenServer);
|
||||
|
||||
resetChosen();
|
||||
|
||||
if ($scope.clusterMap.length > 0) {
|
||||
$scope.tmp.curChosenServer = $scope.clusterMap[0];
|
||||
$scope.onCurrentServerChange();
|
||||
} else {
|
||||
$scope.tmp.curChosenServer = {};
|
||||
}
|
||||
};
|
||||
|
||||
function retrieveClusterAppInfo() {
|
||||
ClusterStateService.fetchClusterUniversalStateOfApp($scope.app).success(function (data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.appClusterMachineList = data.data;
|
||||
$scope.appClusterMachineList.forEach(processAppSingleData);
|
||||
applyClusterMap($scope.appClusterMachineList);
|
||||
if ($scope.clusterMap.length > 0) {
|
||||
$scope.tmp.curChosenServer = $scope.clusterMap[0];
|
||||
$scope.onCurrentServerChange();
|
||||
}
|
||||
} else {
|
||||
$scope.appClusterMachineList = {};
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
retrieveClusterAppInfo();
|
||||
|
||||
$scope.saveAndApplyAssign = () => {
|
||||
let ok = confirm('是否确认执行变更?');
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
let cm = $scope.clusterMap;
|
||||
if (!cm) {
|
||||
cm = [];
|
||||
}
|
||||
cm.forEach((e) => {
|
||||
e.namespaceSet = convertStrToNamespaceSet(e.namespaceSetStr);
|
||||
});
|
||||
cm.namespaceSet = convertStrToNamespaceSet(cm.namespaceSetStr);
|
||||
let request = {
|
||||
clusterMap: cm,
|
||||
remainingList: $scope.remainingClientAddressList,
|
||||
};
|
||||
ClusterStateService.applyClusterFullAssignOfApp($scope.app, request).success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
let failedServerSet = data.data.failedServerSet;
|
||||
let failedClientSet = data.data.failedClientSet;
|
||||
if (failedClientSet.length === 0 && failedServerSet.length === 0) {
|
||||
alert('全部推送成功');
|
||||
} else {
|
||||
alert('推送完毕。token server 失败列表:' + JSON.stringify(failedServerSet) +
|
||||
'; token client 失败列表:' + JSON.stringify(failedClientSet));
|
||||
}
|
||||
|
||||
retrieveClusterAppInfo();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('推送失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
alert('未知错误');
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterAppServerMonitorController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
const UNSUPPORTED_CODE = 4041;
|
||||
|
||||
const CLUSTER_MODE_SERVER = 1;
|
||||
|
||||
$scope.tmp = {
|
||||
curChosenServer: {},
|
||||
};
|
||||
|
||||
function convertSetToString(set) {
|
||||
if (set === undefined) {
|
||||
return '';
|
||||
}
|
||||
let s = '';
|
||||
for (let i = 0; i < set.length; i++) {
|
||||
s = s + set[i];
|
||||
if (i < set.length - 1) {
|
||||
s = s + ',';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function processServerData(serverVO) {
|
||||
if (serverVO.state && serverVO.state.namespaceSet) {
|
||||
serverVO.state.namespaceSetStr = convertSetToString(serverVO.state.namespaceSet);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.generateConnectionSet = (data) => {
|
||||
let connectionSet = data;
|
||||
let s = '';
|
||||
if (connectionSet) {
|
||||
s = s + '[';
|
||||
for (let i = 0; i < connectionSet.length; i++) {
|
||||
s = s + connectionSet[i].address;
|
||||
if (i < connectionSet.length - 1) {
|
||||
s = s + ', ';
|
||||
}
|
||||
}
|
||||
s = s + ']';
|
||||
} else {
|
||||
s = '[]';
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
$scope.onChosenServerChange = () => {
|
||||
|
||||
};
|
||||
|
||||
function retrieveClusterServerInfo() {
|
||||
ClusterStateService.fetchClusterServerStateOfApp($scope.app).success(function (data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.serverVOList = data.data;
|
||||
$scope.serverVOList.forEach(processServerData);
|
||||
|
||||
if ($scope.serverVOList.length > 0) {
|
||||
$scope.tmp.curChosenServer = $scope.serverVOList[0];
|
||||
$scope.onChosenServerChange();
|
||||
}
|
||||
} else {
|
||||
$scope.serverVOList = {};
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
retrieveClusterServerInfo();
|
||||
|
||||
$scope.macsInputConfig = {
|
||||
searchField: ['text', 'value'],
|
||||
persist: true,
|
||||
create: false,
|
||||
maxItems: 1,
|
||||
render: {
|
||||
item: function (data, escape) {
|
||||
return '<div>' + escape(data.text) + '</div>';
|
||||
}
|
||||
},
|
||||
onChange: function (value, oldValue) {
|
||||
$scope.macInputModel = value;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterAppTokenClientListController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
|
||||
const UNSUPPORTED_CODE = 4041;
|
||||
const CLUSTER_MODE_CLIENT = 0;
|
||||
const CLUSTER_MODE_SERVER = 1;
|
||||
|
||||
function processClientData(clientVO) {
|
||||
|
||||
}
|
||||
|
||||
$scope.modifyClientConfigDialog = (clientVO) => {
|
||||
if (!clientVO) {
|
||||
return;
|
||||
}
|
||||
$scope.ccDialogData = {
|
||||
ip: clientVO.ip,
|
||||
commandPort: clientVO.commandPort,
|
||||
clientId: clientVO.id,
|
||||
serverHost: clientVO.state.clientConfig.serverHost,
|
||||
serverPort: clientVO.state.clientConfig.serverPort,
|
||||
requestTimeout: clientVO.state.clientConfig.requestTimeout,
|
||||
};
|
||||
$scope.ccDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/cluster/cluster-client-config-dialog.html',
|
||||
width: 700,
|
||||
overlay: true,
|
||||
scope: $scope
|
||||
});
|
||||
};
|
||||
|
||||
function checkValidClientConfig(config) {
|
||||
if (!config.serverHost || config.serverHost.trim() == '') {
|
||||
alert('请输入有效的 Token Server IP');
|
||||
return false;
|
||||
}
|
||||
if (config.serverPort === undefined || config.serverPort <= 0 || config.serverPort > 65535) {
|
||||
alert('请输入有效的 Token Server 端口');
|
||||
return false;
|
||||
}
|
||||
if (config.requestTimeout === undefined || config.requestTimeout <= 0) {
|
||||
alert('请输入有效的请求超时时长');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$scope.doModifyClientConfig = () => {
|
||||
if (!checkValidClientConfig($scope.ccDialogData)) {
|
||||
return;
|
||||
}
|
||||
let id = $scope.ccDialogData.id;
|
||||
let request = {
|
||||
app: $scope.app,
|
||||
ip: $scope.ccDialogData.ip,
|
||||
port: $scope.ccDialogData.commandPort,
|
||||
mode: CLUSTER_MODE_CLIENT,
|
||||
clientConfig: {
|
||||
serverHost: $scope.ccDialogData.serverHost,
|
||||
serverPort: $scope.ccDialogData.serverPort,
|
||||
requestTimeout: $scope.ccDialogData.requestTimeout,
|
||||
}
|
||||
};
|
||||
ClusterStateService.modifyClusterConfig(request).success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
alert('修改 Token Client 配置成功');
|
||||
window.location.reload();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('机器 ' + id + ' 的 Sentinel 没有引入集群限流客户端,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('修改失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error((data, header, config, status) => {
|
||||
alert('未知错误');
|
||||
});
|
||||
};
|
||||
|
||||
function retrieveClusterTokenClientInfo() {
|
||||
ClusterStateService.fetchClusterClientStateOfApp($scope.app)
|
||||
.success((data) => {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.clientVOList = data.data;
|
||||
$scope.clientVOList.forEach(processClientData);
|
||||
} else {
|
||||
$scope.clientVOList = [];
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
})
|
||||
.error(() => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
retrieveClusterTokenClientInfo();
|
||||
|
||||
$scope.macsInputConfig = {
|
||||
searchField: ['text', 'value'],
|
||||
persist: true,
|
||||
create: false,
|
||||
maxItems: 1,
|
||||
render: {
|
||||
item: function (data, escape) {
|
||||
return '<div>' + escape(data.text) + '</div>';
|
||||
}
|
||||
},
|
||||
onChange: function (value, oldValue) {
|
||||
$scope.macInputModel = value;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog',
|
||||
app.controller('SentinelClusterSingleController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
|
|
@ -39,7 +39,7 @@ app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog
|
|||
}
|
||||
|
||||
function convertStrToNamespaceSet(str) {
|
||||
if (str === undefined || str == '') {
|
||||
if (str === undefined || str === '') {
|
||||
return [];
|
||||
}
|
||||
let arr = [];
|
||||
|
|
@ -51,11 +51,11 @@ app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog
|
|||
}
|
||||
|
||||
function fetchMachineClusterState() {
|
||||
if (!$scope.macInputModel) {
|
||||
if (!$scope.macInputModel || $scope.macInputModel === '') {
|
||||
return;
|
||||
}
|
||||
let mac = $scope.macInputModel.split(':');
|
||||
ClusterStateService.fetchClusterUniversalState($scope.app, mac[0], mac[1]).success(function (data) {
|
||||
ClusterStateService.fetchClusterUniversalStateSingle($scope.app, mac[0], mac[1]).success(function (data) {
|
||||
if (data.code == 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.stateVO = data.data;
|
||||
|
|
@ -144,6 +144,11 @@ app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog
|
|||
alert('请输入有效的 Token Server 端口');
|
||||
return false;
|
||||
}
|
||||
let flowConfig = stateVO.server.flow;
|
||||
if (flowConfig.maxAllowedQps === undefined || flowConfig.maxAllowedQps < 0) {
|
||||
alert('请输入有效的最大允许 QPS');
|
||||
return false;
|
||||
}
|
||||
// if (transportConfig.idleSeconds === undefined || transportConfig.idleSeconds <= 0) {
|
||||
// alert('请输入有效的连接清理时长 (idleSeconds)');
|
||||
// return false;
|
||||
|
|
@ -205,19 +210,21 @@ app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog
|
|||
function queryAppMachines() {
|
||||
MachineService.getAppMachines($scope.app).success(
|
||||
function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
// $scope.machines = data.data;
|
||||
if (data.data) {
|
||||
$scope.machines = [];
|
||||
$scope.macsInputOptionsOrigin = [];
|
||||
$scope.macsInputOptions = [];
|
||||
data.data.forEach(function (item) {
|
||||
if (item.health) {
|
||||
$scope.macsInputOptions.push({
|
||||
$scope.macsInputOptionsOrigin.push({
|
||||
text: item.ip + ':' + item.port,
|
||||
value: item.ip + ':' + item.port
|
||||
});
|
||||
}
|
||||
});
|
||||
$scope.macsInputOptions = $scope.macsInputOptionsOrigin;
|
||||
}
|
||||
if ($scope.macsInputOptions.length > 0) {
|
||||
$scope.macInputModel = $scope.macsInputOptions[0].value;
|
||||
|
|
@ -227,11 +234,29 @@ app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog
|
|||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
queryAppMachines();
|
||||
|
||||
$scope.$watch('searchKey', function () {
|
||||
if (!$scope.macsInputOptions) {
|
||||
return;
|
||||
}
|
||||
if ($scope.searchKey) {
|
||||
$scope.macsInputOptions = $scope.macsInputOptionsOrigin
|
||||
.filter((e) => e.value.indexOf($scope.searchKey) !== -1);
|
||||
} else {
|
||||
$scope.macsInputOptions = $scope.macsInputOptionsOrigin;
|
||||
}
|
||||
if ($scope.macsInputOptions.length > 0) {
|
||||
$scope.macInputModel = $scope.macsInputOptions[0].value;
|
||||
} else {
|
||||
$scope.macInputModel = '';
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('macInputModel', function () {
|
||||
if ($scope.macInputModel) {
|
||||
fetchMachineClusterState();
|
||||
}
|
||||
});
|
||||
queryAppMachines();
|
||||
}]);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('FlowController', ['$scope', '$stateParams', 'FlowServiceV2', 'ngDialog',
|
||||
app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', 'ngDialog',
|
||||
'MachineService',
|
||||
function ($scope, $stateParams, FlowService, ngDialog,
|
||||
MachineService) {
|
||||
|
|
@ -27,6 +27,19 @@ app.controller('FlowController', ['$scope', '$stateParams', 'FlowServiceV2', 'ng
|
|||
}
|
||||
};
|
||||
|
||||
$scope.generateThresholdTypeShow = (rule) => {
|
||||
if (!rule.clusterMode) {
|
||||
return '单机';
|
||||
}
|
||||
if (rule.clusterConfig.thresholdType === 0) {
|
||||
return '集群均摊';
|
||||
} else if (rule.clusterConfig.thresholdType === 1) {
|
||||
return '集群总体';
|
||||
} else {
|
||||
return '集群';
|
||||
}
|
||||
};
|
||||
|
||||
getMachineRules();
|
||||
function getMachineRules() {
|
||||
if (!$scope.macInputModel) {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', 'ngDialog',
|
||||
app.controller('FlowControllerV2', ['$scope', '$stateParams', 'FlowServiceV2', 'ngDialog',
|
||||
'MachineService',
|
||||
function ($scope, $stateParams, FlowService, ngDialog,
|
||||
MachineService) {
|
||||
|
|
@ -27,6 +27,19 @@ app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', '
|
|||
}
|
||||
};
|
||||
|
||||
$scope.generateThresholdTypeShow = (rule) => {
|
||||
if (!rule.clusterMode) {
|
||||
return '单机';
|
||||
}
|
||||
if (rule.clusterConfig.thresholdType === 0) {
|
||||
return '集群均摊';
|
||||
} else if (rule.clusterConfig.thresholdType === 1) {
|
||||
return '集群总体';
|
||||
} else {
|
||||
return '集群';
|
||||
}
|
||||
};
|
||||
|
||||
getMachineRules();
|
||||
function getMachineRules() {
|
||||
if (!$scope.macInputModel) {
|
||||
|
|
@ -72,7 +85,11 @@ app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', '
|
|||
app: $scope.app,
|
||||
ip: mac[0],
|
||||
port: mac[1],
|
||||
limitApp: 'default'
|
||||
limitApp: 'default',
|
||||
clusterMode: false,
|
||||
clusterConfig: {
|
||||
thresholdType: 0
|
||||
}
|
||||
};
|
||||
$scope.flowRuleDialog = {
|
||||
title: '新增流控规则',
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
||||
'ngDialog', 'FlowServiceV2', 'DegradeService', 'AuthorityRuleService', 'ParamFlowService', 'MachineService',
|
||||
'ngDialog', 'FlowServiceV1', 'DegradeService', 'AuthorityRuleService', 'ParamFlowService', 'MachineService',
|
||||
'$interval', '$location', '$timeout',
|
||||
function ($scope, $stateParams, IdentityService, ngDialog,
|
||||
FlowService, DegradeService, AuthorityRuleService, ParamFlowService, MachineService, $interval, $location, $timeout) {
|
||||
|
|
@ -52,6 +52,10 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
|||
controlBehavior: 0,
|
||||
resource: resource,
|
||||
limitApp: 'default',
|
||||
clusterMode: false,
|
||||
clusterConfig: {
|
||||
thresholdType: 0
|
||||
},
|
||||
app: $scope.app,
|
||||
ip: mac[0],
|
||||
port: mac[1]
|
||||
|
|
@ -89,13 +93,15 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
|||
return;
|
||||
}
|
||||
FlowService.newRule(flowRuleDialogScope.currentRule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
if (data.code === 0) {
|
||||
flowRuleDialog.close();
|
||||
let url = '/dashboard/flow/' + $scope.app;
|
||||
$location.path(url);
|
||||
} else {
|
||||
alert('失败!');
|
||||
}
|
||||
}).error((data, header, config, status) => {
|
||||
alert('未知错误');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop
|
|||
let mac = $scope.macInputModel.split(':');
|
||||
ParamFlowService.queryMachineRules($scope.app, mac[0], mac[1])
|
||||
.success(function (data) {
|
||||
if (data.code == 0 && data.data) {
|
||||
if (data.code === 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.rules = data.data;
|
||||
$scope.rulesPageConfig.totalCount = $scope.rules.length;
|
||||
|
|
@ -157,6 +157,10 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop
|
|||
paramFlowItemList: [],
|
||||
count: 0,
|
||||
limitApp: 'default',
|
||||
clusterMode: false,
|
||||
clusterConfig: {
|
||||
thresholdType: 0
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.paramFlowRuleDialog = {
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@
|
|||
<i class="glyphicon glyphicon-check"></i> 授权规则</a>
|
||||
</li>
|
||||
<li ui-sref-active="active">
|
||||
<a ui-sref="dashboard.clusterAll({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-cloud"></i> 集群限流</a>
|
||||
<a ui-sref="dashboard.clusterAppServerList({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-cloud"></i> 集群流控</a>
|
||||
</li>
|
||||
<li ui-sref-active="active">
|
||||
<a ui-sref="dashboard.machine({app: entry.app})">
|
||||
|
|
|
|||
|
|
@ -1,28 +1,73 @@
|
|||
/**
|
||||
* Parameter flow control service.
|
||||
* Cluster state control service.
|
||||
*
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
angular.module('sentinelDashboardApp').service('ClusterStateService', ['$http', function ($http) {
|
||||
|
||||
this.fetchClusterUniversalState = function(app, ip, port) {
|
||||
this.fetchClusterUniversalStateSingle = function(app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: '/cluster/state',
|
||||
url: '/cluster/state_single',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.fetchClusterUniversalStateOfApp = function(app) {
|
||||
return $http({
|
||||
url: '/cluster/state/' + app,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.fetchClusterServerStateOfApp = function(app) {
|
||||
return $http({
|
||||
url: '/cluster/server_state/' + app,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.fetchClusterClientStateOfApp = function(app) {
|
||||
return $http({
|
||||
url: '/cluster/client_state/' + app,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.modifyClusterConfig = function(config) {
|
||||
return $http({
|
||||
url: '/cluster/config/modify',
|
||||
url: '/cluster/config/modify_single',
|
||||
data: config,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
this.applyClusterFullAssignOfApp = function(app, clusterMap) {
|
||||
return $http({
|
||||
url: '/cluster/assign/all_server/' + app,
|
||||
data: clusterMap,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
this.applyClusterSingleServerAssignOfApp = function(app, request) {
|
||||
return $http({
|
||||
url: '/cluster/assign/single_server/' + app,
|
||||
data: request,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
this.applyClusterServerBatchUnbind = function(app, machineSet) {
|
||||
return $http({
|
||||
url: '/cluster/assign/unbind_server/' + app,
|
||||
data: machineSet,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
|
|
|||
|
|
@ -1,75 +1,75 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.service('FlowServiceV1', ['$http', function ($http) {
|
||||
this.queryMachineRules = function (app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: '/v1/flow/rules',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.newRule = function (rule) {
|
||||
var param = {
|
||||
resource: rule.resource,
|
||||
limitApp: rule.limitApp,
|
||||
grade: rule.grade,
|
||||
count: rule.count,
|
||||
strategy: rule.strategy,
|
||||
refResource: rule.refResource,
|
||||
controlBehavior: rule.controlBehavior,
|
||||
warmUpPeriodSec: rule.warmUpPeriodSec,
|
||||
maxQueueingTimeMs: rule.maxQueueingTimeMs,
|
||||
app: rule.app,
|
||||
ip: rule.ip,
|
||||
port: rule.port
|
||||
this.queryMachineRules = function (app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: '/v1/flow/rules',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
return $http({
|
||||
url: '/v1/flow/rule',
|
||||
data: rule,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
this.newRule = function (rule) {
|
||||
var param = {
|
||||
resource: rule.resource,
|
||||
limitApp: rule.limitApp,
|
||||
grade: rule.grade,
|
||||
count: rule.count,
|
||||
strategy: rule.strategy,
|
||||
refResource: rule.refResource,
|
||||
controlBehavior: rule.controlBehavior,
|
||||
warmUpPeriodSec: rule.warmUpPeriodSec,
|
||||
maxQueueingTimeMs: rule.maxQueueingTimeMs,
|
||||
app: rule.app,
|
||||
ip: rule.ip,
|
||||
port: rule.port
|
||||
};
|
||||
|
||||
this.saveRule = function (rule) {
|
||||
var param = {
|
||||
id: rule.id,
|
||||
resource: rule.resource,
|
||||
limitApp: rule.limitApp,
|
||||
grade: rule.grade,
|
||||
count: rule.count,
|
||||
strategy: rule.strategy,
|
||||
refResource: rule.refResource,
|
||||
controlBehavior: rule.controlBehavior,
|
||||
warmUpPeriodSec: rule.warmUpPeriodSec,
|
||||
maxQueueingTimeMs: rule.maxQueueingTimeMs,
|
||||
return $http({
|
||||
url: '/v1/flow/rule',
|
||||
data: rule,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
return $http({
|
||||
url: '/v1/flow/save.json',
|
||||
params: param,
|
||||
method: 'PUT'
|
||||
});
|
||||
};
|
||||
this.saveRule = function (rule) {
|
||||
var param = {
|
||||
id: rule.id,
|
||||
resource: rule.resource,
|
||||
limitApp: rule.limitApp,
|
||||
grade: rule.grade,
|
||||
count: rule.count,
|
||||
strategy: rule.strategy,
|
||||
refResource: rule.refResource,
|
||||
controlBehavior: rule.controlBehavior,
|
||||
warmUpPeriodSec: rule.warmUpPeriodSec,
|
||||
maxQueueingTimeMs: rule.maxQueueingTimeMs,
|
||||
};
|
||||
|
||||
this.deleteRule = function (rule) {
|
||||
var param = {
|
||||
id: rule.id,
|
||||
app: rule.app
|
||||
return $http({
|
||||
url: '/v1/flow/save.json',
|
||||
params: param,
|
||||
method: 'PUT'
|
||||
});
|
||||
};
|
||||
|
||||
return $http({
|
||||
url: '/v1/flow/delete.json',
|
||||
params: param,
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
this.deleteRule = function (rule) {
|
||||
var param = {
|
||||
id: rule.id,
|
||||
app: rule.app
|
||||
};
|
||||
|
||||
return $http({
|
||||
url: '/v1/flow/delete.json',
|
||||
params: param,
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
|
||||
function notNumberAtLeastZero(num) {
|
||||
return num === undefined || num === '' || isNaN(num) || num < 0;
|
||||
|
|
@ -79,7 +79,7 @@ app.service('FlowServiceV1', ['$http', function ($http) {
|
|||
return num === undefined || num === '' || isNaN(num) || num <= 0;
|
||||
}
|
||||
|
||||
this.checkRuleValid = function (rule) {
|
||||
this.checkRuleValid = function (rule) {
|
||||
if (rule.resource === undefined || rule.resource === '') {
|
||||
alert('资源名称不能为空');
|
||||
return false;
|
||||
|
|
@ -110,6 +110,10 @@ app.service('FlowServiceV1', ['$http', function ($http) {
|
|||
alert('排队超时时间必须大于 0');
|
||||
return false;
|
||||
}
|
||||
if (rule.clusterMode && (rule.clusterConfig === undefined || rule.clusterConfig.thresholdType === undefined)) {
|
||||
alert('集群限流配置不正确');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}]);
|
||||
|
|
|
|||
|
|
@ -1,41 +1,41 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.service('FlowServiceV2', ['$http', function ($http) {
|
||||
this.queryMachineRules = function (app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
this.queryMachineRules = function (app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: '/v2/flow/rules',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
return $http({
|
||||
url: '/v2/flow/rules',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.newRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule',
|
||||
data: rule,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
this.newRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule',
|
||||
data: rule,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
this.saveRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule/' + rule.id,
|
||||
data: rule,
|
||||
method: 'PUT'
|
||||
});
|
||||
};
|
||||
this.saveRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule/' + rule.id,
|
||||
data: rule,
|
||||
method: 'PUT'
|
||||
});
|
||||
};
|
||||
|
||||
this.deleteRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule/' + rule.id,
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
this.deleteRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule/' + rule.id,
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
|
||||
function notNumberAtLeastZero(num) {
|
||||
return num === undefined || num === '' || isNaN(num) || num < 0;
|
||||
|
|
@ -45,7 +45,7 @@ app.service('FlowServiceV2', ['$http', function ($http) {
|
|||
return num === undefined || num === '' || isNaN(num) || num <= 0;
|
||||
}
|
||||
|
||||
this.checkRuleValid = function (rule) {
|
||||
this.checkRuleValid = function (rule) {
|
||||
if (rule.resource === undefined || rule.resource === '') {
|
||||
alert('资源名称不能为空');
|
||||
return false;
|
||||
|
|
@ -76,10 +76,10 @@ app.service('FlowServiceV2', ['$http', function ($http) {
|
|||
alert('排队超时时间必须大于 0');
|
||||
return false;
|
||||
}
|
||||
if (rule.clusterMode && (rule.clusterConfig === undefined || rule.clusterConfig.thresholdType === undefined)) {
|
||||
alert('集群限流配置不正确');
|
||||
return false;
|
||||
}
|
||||
if (rule.clusterMode && (rule.clusterConfig === undefined || rule.clusterConfig.thresholdType === undefined)) {
|
||||
alert('集群限流配置不正确');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}]);
|
||||
|
|
|
|||
|
|
@ -525,6 +525,10 @@ body {
|
|||
max-width: 200px;
|
||||
}
|
||||
|
||||
.width-200 {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.witdh-300 {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
<div class="row clearfix">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group" ng-if="stateVO.currentMode == 0">
|
||||
<label class="col-sm-2 control-label">连接状态</label>
|
||||
<div class="col-sm-4">
|
||||
<p class="form-control-static text-danger" ng-if="stateVO.client.clientConfig.clientState === 0">未连接</p>
|
||||
<p class="form-control-static" ng-if="stateVO.client.clientConfig.clientState === 1">连接中</p>
|
||||
<p class="form-control-static text-success" ng-if="stateVO.client.clientConfig.clientState === 2">已连接</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server IP</label>
|
||||
<div class="col-sm-4">
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
<div class="row clearfix">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group" ng-if="stateVO.currentMode == 1">
|
||||
<label class="col-sm-2 control-label">Token Server 模式</label>
|
||||
<div class="col-sm-4">
|
||||
<p class="form-control-static" ng-if="!stateVO.server.embedded">独立模式 (Alone)</p>
|
||||
<p class="form-control-static" ng-if="stateVO.server.embedded">嵌入模式 (Embedded)</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server 端口</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" max="65535" required class="form-control highlight-border" ng-model='stateVO.server.transport.port' placeholder='请指定 Token Server 端口' />
|
||||
<input type="number" min="1" max="65535" required class="form-control highlight-border" ng-model='stateVO.server.transport.port' placeholder='请指定 Token Server 端口' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
@ -12,5 +19,11 @@
|
|||
<input type="text" required class="form-control highlight-border" ng-model='stateVO.server.namespaceSetStr' placeholder='请指定服务端服务的命名空间集合(以,分隔)' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">最大全局 QPS</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" max="100000" required class="form-control highlight-border" ng-model='stateVO.server.flow.maxAllowedQps' placeholder='请指定服务端最大全局 QPS' />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">集群限流 - 机器分配/管控</span>
|
||||
</div>
|
||||
|
||||
<!-- error panel -->
|
||||
<div class="row clearfix" ng-if="loadError">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<center>
|
||||
<p>{{loadError.message}}</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;" ng-if="!loadError">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Server 列表</label>
|
||||
<div class="col-sm-4">
|
||||
<select ng-model="tmp.curChosenServer" ng-change="onCurrentServerChange()" size="8"
|
||||
ng-options="serverGroup.machineId for serverGroup in clusterMap"
|
||||
class="form-control"></select>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-warning" ng-click="removeFromServerList()">移除
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server 端口</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" class="form-control highlight-border"
|
||||
ng-disabled="!tmp.curChosenServer.belongToApp"
|
||||
ng-model='tmp.curChosenServer.port' placeholder='port' min="1" max="65535"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">命名空间集合</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" required class="form-control highlight-border"
|
||||
ng-disabled="!tmp.curChosenServer.belongToApp"
|
||||
ng-model='tmp.curChosenServer.namespaceSetStr'
|
||||
placeholder='请指定服务端服务的命名空间集合(以,分隔)'/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form role="form" class="form-inline" style="margin-top: 30px; margin-left: 20px;">
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label" style="width: 200px; text-align: center;">当前对应客户端列表</label>
|
||||
<select size="8" multiple="multiple" ng-model="tmp.curClientChosen"
|
||||
ng-options="ip for ip in tmp.curChosenServer.clientSet"
|
||||
class="form-control" style="width: 100%;"></select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
ng-disabled="!tmp.curChosenServer || !tmp.curChosenServer.machineId"
|
||||
ng-click="moveToServerGroup()">←
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
ng-click="moveToRemainingSharePool()">→
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label" style="width: 220px; text-align: center;">未分配机器列表</label>
|
||||
<div>
|
||||
<select size="8" multiple="multiple" ng-model="tmp.curRemainingClientChosen"
|
||||
ng-options="ip for ip in remainingClientAddressList"
|
||||
class="form-control" style="width: 100%;">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-6">
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
ng-click="addToServerList()">添加为 server
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="separator"></div>
|
||||
<div style="margin-top: 20px;">
|
||||
<button type="button" style="margin: 0 10px 10px 10px;" class="btn btn-outline-success"
|
||||
ng-click="saveAndApplyAssign()">保存并执行分配
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
</div>
|
||||
<!-- .card -->
|
||||
</div>
|
||||
<!-- .col-md-12 -->
|
||||
</div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<!-- .container-fluid -->
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ui-sref="dashboard.clusterAppServerList({app: app})">
|
||||
Token Server 列表
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">集群限流 - Token Client 列表</span>
|
||||
</div>
|
||||
|
||||
<!-- error panel -->
|
||||
<div class="row clearfix" ng-if="loadError">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<center>
|
||||
<p>{{loadError.message}}</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;" ng-if="!loadError">
|
||||
<!-- table start -->
|
||||
<table class="table" style="border-left: none; border-right:none;margin-top: 10px;">
|
||||
<thead>
|
||||
<tr style="background: #F3F5F7;">
|
||||
<td style="min-width: 12%;">Client ID</td>
|
||||
<td>Server IP</td>
|
||||
<td>Server 端口</td>
|
||||
<td>连接状态</td>
|
||||
<td style="min-width: 15%;">操作</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="clientVO in clientVOList">
|
||||
<td style="word-wrap:break-word;word-break:break-all;">{{clientVO.id}}</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">{{clientVO.state.clientConfig.serverHost}}</td>
|
||||
<td>{{clientVO.state.clientConfig.serverPort}}</td>
|
||||
<td>
|
||||
<span class="form-control-static text-danger" ng-if="clientVO.state.clientConfig.clientState === 0">未连接</span>
|
||||
<span class="form-control-static" ng-if="clientVO.state.clientConfig.clientState === 1">连接中</span>
|
||||
<span class="form-control-static text-success" ng-if="clientVO.state.clientConfig.clientState === 2">已连接</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-xs btn-outline-primary" type="button"
|
||||
ng-click="modifyClientConfigDialog(clientVO)" style="font-size: 12px; height:25px;">编辑配置</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
</div>
|
||||
<!-- .card -->
|
||||
</div>
|
||||
<!-- .col-md-12 -->
|
||||
</div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<!-- .container-fluid -->
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ng-if="!loadError" ng-click="newServerDialog()">
|
||||
<i class="fa fa-plus"></i> 新增 Token Server</button>
|
||||
<a class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ui-sref="dashboard.clusterAppClientList({app: app})">
|
||||
Token Client 列表
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">集群限流 - Token Server 列表</span>
|
||||
<input class="form-control width-200" placeholder="搜索 server..." ng-model="searchKey">
|
||||
</div>
|
||||
|
||||
<!-- error panel -->
|
||||
<div class="row clearfix" ng-if="loadError">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<center>
|
||||
<p>{{loadError.message}}</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;" ng-if="!loadError">
|
||||
<!-- table start -->
|
||||
<table class="table" style="border-left: none; border-right:none;margin-top: 10px;">
|
||||
<thead>
|
||||
<tr style="background: #F3F5F7;">
|
||||
<td style="width: 15%;">Server ID</td>
|
||||
<td style="width: 10%;">Port</td>
|
||||
<td style="width: 15%;">命名空间集合</td>
|
||||
<td>总连接数</td>
|
||||
<td>QPS 总览</td>
|
||||
<td style="width: 20%;">操作</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="serverVO in serverVOList | filter: {id: searchKey}">
|
||||
<td style="word-wrap:break-word;word-break:break-all;">{{serverVO.id}}</td>
|
||||
<td>{{serverVO.port}}</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{serverVO.state.namespaceSetStr}}
|
||||
</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{serverVO.connectedCount}}
|
||||
</td>
|
||||
<td>
|
||||
{{serverVO.state.requestLimitDataStr}}
|
||||
<!--<p ng-repeat="crl in serverVO.state.requestLimitData">-->
|
||||
<!--<span ng-if="crl.namespace === app">{{crl.namespace}}:{{crl.currentQps}} / {{crl.maxAllowedQps}}</span>-->
|
||||
<!--</p>-->
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-xs btn-outline-primary" type="button"
|
||||
ng-click="viewConnectionDetail(serverVO)" style="font-size: 12px; height:25px;">连接详情</button>
|
||||
<button class="btn btn-xs btn-outline-primary" type="button"
|
||||
ng-click="modifyServerAssignConfig(serverVO.id)" style="font-size: 12px; height:25px;">管理</button>
|
||||
<button class="btn btn-xs btn-outline-danger" type="button"
|
||||
ng-click="unbindServer(serverVO.id)" style="font-size: 12px; height:25px;">移除</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
</div>
|
||||
<!-- .card -->
|
||||
</div>
|
||||
<!-- .col-md-12 -->
|
||||
</div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<!-- .container-fluid -->
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">集群限流 - Token Server 总览</span>
|
||||
</div>
|
||||
|
||||
<!-- error panel -->
|
||||
<div class="row clearfix" ng-if="loadError">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<center>
|
||||
<p>{{loadError.message}}</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;" ng-if="!loadError">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group" hidden>
|
||||
<label class="col-sm-2 control-label">Token Server 列表</label>
|
||||
<div class="col-sm-4">
|
||||
<select ng-model="tmp.curChosenServer" ng-change="onChosenServerChange()"
|
||||
ng-options="serverEntity.id for serverEntity in serverVOList"
|
||||
class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- table start -->
|
||||
<table class="table" style="border-left: none; border-right:none;margin-top: 10px;">
|
||||
<thead>
|
||||
<tr style="background: #F3F5F7;">
|
||||
<td style="width: 12%;">Server ID</td>
|
||||
<td style="width: 5%;">Port</td>
|
||||
<td style="width: 10%;">命名空间集合</td>
|
||||
<td>总连接数</td>
|
||||
<td>连接情况</td>
|
||||
<td>QPS 总览</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="serverVO in clientVOList">
|
||||
<td style="word-wrap:break-word;word-break:break-all;">{{serverVO.id}}</td>
|
||||
<td>{{serverVO.port}}</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{serverVO.state.namespaceSetStr}}
|
||||
</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{serverVO.connectedCount}}
|
||||
</td>
|
||||
<td>
|
||||
<p ng-repeat="cg in serverVO.state.connection">
|
||||
namespace: {{cg.namespace}}, 连接数: {{cg.connectedCount}}, clients:
|
||||
{{generateConnectionSet(cg.connectionSet)}}
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<p ng-repeat="crl in serverVO.state.requestLimitData">
|
||||
namespace: {{crl.namespace}}, 当前 QPS: {{crl.currentQps}}, 最大允许 QPS:
|
||||
{{crl.maxAllowedQps}}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
</div>
|
||||
<!-- .card -->
|
||||
</div>
|
||||
<!-- .col-md-12 -->
|
||||
</div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<!-- .container-fluid -->
|
||||
|
|
@ -12,8 +12,7 @@
|
|||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">集群限流</span>
|
||||
<button class="btn btn-primary" style="float: right; margin-right: 10px; height: 30px;font-size: 12px;" ng-click="getMachineRules()">刷新</button>
|
||||
<input class="form-control witdh-200" placeholder="关键字" ng-model="searchKey">
|
||||
<input class="form-control witdh-200" placeholder="机器搜索" ng-model="searchKey">
|
||||
<div class="control-group" style="float:right;margin-right: 10px;margin-bottom: -10px;">
|
||||
<selectize id="gsInput" class="selectize-input-200" config="macsInputConfig" options="macsInputOptions" ng-model="macInputModel"
|
||||
placeholder="机器"></selectize>
|
||||
|
|
@ -34,8 +33,7 @@
|
|||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;">
|
||||
<!--<span class="brand" style="font-weight:bold;">集群限流状态</span>-->
|
||||
<div class="card-body" style="padding: 0px 0px;" ng-if="!loadError">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">当前模式</label>
|
||||
|
|
@ -80,7 +78,8 @@
|
|||
|
||||
<div class="separator"></div>
|
||||
<div clss="row" style="margin-top: 20px;">
|
||||
<button style="margin: 0 10px 10px 10px;" class="btn btn-outline-success" ng-click="saveConfig()">保存配置</button>
|
||||
<button style="margin: 0 10px 10px 10px;" class="btn btn-outline-success"
|
||||
ng-click="saveConfig()">保存配置</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<div>
|
||||
<span class="brand" style="font-weight:bold;">修改 Token Client 配置</span>
|
||||
<div class="card" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Client ID</label>
|
||||
<div class="col-sm-4">
|
||||
<p class="form-control-static">{{ccDialogData.clientId}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Token Server IP</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control highlight-border" ng-model='ccDialogData.serverHost' placeholder='请指定 Token Server IP' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Token Server 端口</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" max="65535" required class="form-control highlight-border" ng-model='ccDialogData.serverPort' placeholder='请指定 Token Server 端口' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">请求超时时间(ms)</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" required class="form-control highlight-border" ng-model='ccDialogData.requestTimeout' placeholder='请指定请求超时时间(ms)' />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div clss="row" style="margin-top: 20px;">
|
||||
<button class="btn btn-outline-danger" style="float:right; height: 30px;font-size: 12px;margin-left: 10px;" ng-click="ccDialog.close()">取消</button>
|
||||
<button class="btn btn-outline-success" style="float:right; height: 30px;font-size: 12px;margin-left: 10px;" ng-click="doModifyClientConfig()">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
<div>
|
||||
<span class="brand" style="font-weight:bold;">{{serverAssignDialogData.title}}</span>
|
||||
<div class="card" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div ng-if="serverAssignDialogData.type == 'edit'">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server</label>
|
||||
<div class="col-sm-4">
|
||||
<p class="form-control-static">{{serverAssignDialogData.serverData.currentServer}}</p>
|
||||
</div>
|
||||
|
||||
<label class="col-sm-2 control-label">Server 端口</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" min="1" max="65535" class="form-control highlight-border"
|
||||
ng-disabled="!serverAssignDialogData.serverData.belongToApp"
|
||||
ng-model='serverAssignDialogData.serverData.serverPort' placeholder='请输入 Token Server 端口'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="serverAssignDialogData.serverData.belongToApp">
|
||||
<label class="col-sm-2 control-label"
|
||||
title="server 最大允许的总 QPS,注意 embedded 模式下不要设的太大">最大允许 QPS</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" min="0" max="200000" class="form-control highlight-border"
|
||||
ng-model='serverAssignDialogData.serverData.maxAllowedQps' placeholder='请输入 server 最大允许 QPS'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="serverAssignDialogData.type == 'add'">
|
||||
<div class="form-group" >
|
||||
<label class="col-sm-2 control-label">机器类型</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="form-control highlight-border" align="center">
|
||||
<input type="radio" name="strategy" value="0" checked ng-model='serverAssignDialogData.serverData.serverType' /> 应用内机器
|
||||
<input type="radio" name="strategy" value="1" ng-model='serverAssignDialogData.serverData.serverType' /> 外部指定机器
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="serverAssignDialogData.serverData.serverType == 1">
|
||||
<div class="col-sm-6">
|
||||
<p class="form-control-static text-primary" style="font-size: x-small;">若指定外部 server,请先在相应页面对外部 server 进行配置,然后在此页面指定。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="serverAssignDialogData.serverData.serverType == 0">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">选择机器</label>
|
||||
<div class="col-sm-4">
|
||||
<select ng-model="serverAssignDialogData.serverData.currentServer" ng-change="onCurrentServerChange()"
|
||||
ng-options="machineId for machineId in remainingMachineList"
|
||||
class="form-control"></select>
|
||||
</div>
|
||||
|
||||
<label class="col-sm-2 control-label">Server 端口</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" min="1" max="65535" class="form-control highlight-border"
|
||||
ng-model='serverAssignDialogData.serverData.serverPort' placeholder='请输入 Token Server 端口号'/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label"
|
||||
title="server 最大允许的总 QPS,注意 embedded 模式下不要设的太大">最大允许 QPS</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" min="0" max="200000" class="form-control highlight-border"
|
||||
ng-model='serverAssignDialogData.serverData.maxAllowedQps' placeholder='请输入 server 最大允许 QPS'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-if="serverAssignDialogData.serverData.serverType == 1">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Server IP</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control highlight-border"
|
||||
ng-model='serverAssignDialogData.serverData.currentServer' placeholder='请输入独立的 Token Server IP'/>
|
||||
</div>
|
||||
|
||||
<label class="col-sm-2 control-label">Server 端口</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="number" min="1" max="65535" class="form-control highlight-border"
|
||||
ng-model='serverAssignDialogData.serverData.serverPort' placeholder='请输入 Token Server 端口号'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- assign form start -->
|
||||
<form role="form" class="form-inline" ng-if="serverAssignDialogData.serverData.currentServer"
|
||||
style="margin-top: 30px; margin-left: 20px; text-align: center;">
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label" style="width: 220px; text-align: center;">请从中选取 client:</label>
|
||||
<div>
|
||||
<select size="8" multiple="multiple" ng-model="tmp.curRemainingClientChosen"
|
||||
ng-options="ip for ip in remainingMachineList | filter: notChosenServer"
|
||||
class="form-control" style="width: 100%;">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
ng-click="moveToRemainingSharePool()">←
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
ng-click="moveToServerGroup()">→
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label" style="width: 200px; text-align: center;">已选取的 client 列表</label>
|
||||
<div>
|
||||
<select size="8" multiple="multiple" ng-model="tmp.curClientChosen"
|
||||
ng-options="ip for ip in serverAssignDialogData.serverData.clientSet"
|
||||
class="form-control" style="width: 100%;"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div clss="row" style="margin-top: 20px;">
|
||||
<button class="btn btn-outline-danger" style="float:right; height: 30px;font-size: 12px;margin-left: 10px;" ng-click="serverAssignDialog.close()">取消</button>
|
||||
<button class="btn btn-outline-success" style="float:right; height: 30px;font-size: 12px;margin-left: 10px;" ng-click="saveAssignForDialog()">{{serverAssignDialogData.confirmBtnText}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<div>
|
||||
<span class="brand" style="font-weight:bold;">连接详情</span>
|
||||
<div class="card" style="margin-top: 20px;margin-bottom: 10px;">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Token Server</label>
|
||||
<div class="col-sm-4">
|
||||
<p class="form-control-static">{{connectionDetailDialogData.serverData.id}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="col-md-12">
|
||||
<!-- table start -->
|
||||
<table class="table" style="border-left: none; border-right:none;margin-top: 10px;">
|
||||
<thead>
|
||||
<tr style="background: #F3F5F7;">
|
||||
<td style="min-width: 15%;" class="text-center">命名空间</td>
|
||||
<td class="text-center">连接数</td>
|
||||
<td class="text-center">连接详情</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="cg in connectionDetailDialogData.serverData.state.connection">
|
||||
<td style="word-wrap:break-word;word-break:break-all;" class="text-center">{{cg.namespace}}</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;" class="text-center">{{cg.connectedCount}}</td>
|
||||
<td class="text-center">{{generateConnectionSet(cg.connectionSet)}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" title="流控针对应用,即流量入口的调用来源(origin)">流控应用</label>
|
||||
<label class="col-sm-2 control-label" data-toggle="tooltip" title="流控针对应用,即流量入口的调用来源(origin)">来源应用</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control highlight-border" ng-model='currentRule.limitApp' placeholder='指调用方,"default"表示所有应用。'
|
||||
/>
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
<div class="col-sm-4">
|
||||
<div class="form-control highlight-border" align="center">
|
||||
<input type="radio" name="clusterThresholdType" value="0" ng-model='currentRule.clusterConfig.thresholdType' /> 单机均摊
|
||||
<input type="radio" name="clusterThresholdType" value="1" ng-model='currentRule.clusterConfig.thresholdType' /> Global
|
||||
<input type="radio" name="clusterThresholdType" value="1" ng-model='currentRule.clusterConfig.thresholdType' /> 总体阈值
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -25,12 +25,42 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">限流阈值</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" class="form-control highlight-border" ng-model='currentRule.rule.count' placeholder='请填入限流阈值' />
|
||||
<div ng-if="!currentRule.rule.clusterMode">
|
||||
<label class="col-sm-2 control-label">单机阈值</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" class="form-control highlight-border" ng-model='currentRule.rule.count' placeholder='单机阈值' />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="currentRule.rule.clusterMode && currentRule.rule.clusterConfig.thresholdType == 0">
|
||||
<label class="col-sm-2 control-label">均摊阈值</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" class="form-control highlight-border" ng-model='currentRule.rule.count' placeholder='集群均摊阈值' />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="currentRule.rule.clusterMode && currentRule.rule.clusterConfig.thresholdType == 1">
|
||||
<label class="col-sm-2 control-label">集群阈值</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" class="form-control highlight-border" ng-model='currentRule.rule.count' placeholder='集群总体阈值' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">是否集群</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="checkbox" name="clusterMode" ng-model="currentRule.rule.clusterMode">
|
||||
</div>
|
||||
<div ng-if="currentRule.rule.clusterMode">
|
||||
<label class="col-sm-3 control-label">集群阈值模式</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="form-control highlight-border" align="center">
|
||||
<input type="radio" name="clusterThresholdType" value="0" ng-model='currentRule.rule.clusterConfig.thresholdType' /> 单机均摊
|
||||
<input type="radio" name="clusterThresholdType" value="1" ng-model='currentRule.rule.clusterConfig.thresholdType' /> 总体阈值
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- exclusion item part start -->
|
||||
<div ng-if="!paramFlowRuleDialog.showAdvanceButton">
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<input type="radio" name="grade" value="2" ng-model='currentRule.grade' ng-disabled="systemRuleDialog.type == 'edit'" /> 线程数
|
||||
<!--qps -->
|
||||
<input type="radio" name="grade" value="3" checked ng-model='currentRule.grade' ng-disabled="systemRuleDialog.type == 'edit'"
|
||||
/> QPS
|
||||
/> 入口 QPS
|
||||
</div>
|
||||
<div class="form-control highlight-border" ng-if="systemRuleDialog.type == 'add'" align="center">
|
||||
<!--avgLoad -->
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
<input type="radio" name="grade" value="2" ng-model='currentRule.grade' ng-disabled="systemRuleDialog.type == 'edit'" /> 线程数
|
||||
<!--qps -->
|
||||
<input type="radio" name="grade" value="3" checked ng-model='currentRule.grade' ng-disabled="systemRuleDialog.type == 'edit'"
|
||||
/> QPS
|
||||
/> 入口 QPS
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
<div class="col-md-6">
|
||||
<button class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ng-disabled="!macInputModel" ng-click="addNewRule()">
|
||||
<i class="fa fa-plus"></i> 新增流控规则</button>
|
||||
<a class="btn btn-outline-success" style="float: right; margin-right: 10px;" ui-sref="dashboard.flow({app: app})">
|
||||
回到新版</a>
|
||||
<!--<a class="btn btn-outline-success" style="float: right; margin-right: 10px;" ui-sref="dashboard.flow({app: app})">-->
|
||||
<!--回到集群页面</a>-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -35,24 +35,24 @@
|
|||
<td style="width: 40%">
|
||||
资源名
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
流控应用
|
||||
<td style="width: 8%;">
|
||||
来源应用
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<td style="width: 8%;">
|
||||
流控模式
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<td style="width: 8%;">
|
||||
阈值类型
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
单机阈值
|
||||
<td style="width: 6%;">
|
||||
阈值
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
阈值模式
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
流控效果
|
||||
</td>
|
||||
<!--<td style="width: 8%;">-->
|
||||
<!--状态-->
|
||||
<!--</td>-->
|
||||
<td style="width: 12%;">
|
||||
操作
|
||||
</td>
|
||||
|
|
@ -74,10 +74,14 @@
|
|||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{rule.count}}
|
||||
</td>
|
||||
<td>
|
||||
<span>{{generateThresholdTypeShow(rule)}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="rule.controlBehavior == 0">快速失败</span>
|
||||
<span ng-if="rule.controlBehavior == 1">Warm Up</span>
|
||||
<span ng-if="rule.controlBehavior == 2">排队等待</span>
|
||||
<span ng-if="rule.controlBehavior == 3">预热排队</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-xs btn-default" type="button" ng-click="editRule(rule)" style="font-size: 12px; height:25px;">编辑</button>
|
||||
|
|
@ -7,7 +7,8 @@
|
|||
<i class="fa fa-plus"></i> 新增流控规则
|
||||
</button>
|
||||
<a class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ui-sref="dashboard.flowV1({app: app})">
|
||||
回到旧版(单机)</a>
|
||||
回到单机页面
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -31,7 +32,7 @@
|
|||
资源名
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
流控应用
|
||||
来源应用
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
流控模式
|
||||
|
|
@ -40,10 +41,10 @@
|
|||
阈值类型
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
单机阈值
|
||||
阈值
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
是否集群
|
||||
阈值模式
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
流控效果
|
||||
|
|
@ -70,8 +71,7 @@
|
|||
{{rule.count}}
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="rule.clusterMode">是</span>
|
||||
<span ng-if="!rule.clusterMode">否</span>
|
||||
<span>{{generateThresholdTypeShow(rule)}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="rule.controlBehavior == 0">快速失败</span>
|
||||
|
|
@ -53,7 +53,10 @@
|
|||
流控模式
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
单机阈值
|
||||
阈值
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
是否集群
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
例外项数目
|
||||
|
|
@ -74,6 +77,10 @@
|
|||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{ruleEntity.rule.count}}
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="ruleEntity.rule.clusterMode">是</span>
|
||||
<span ng-if="!ruleEntity.rule.clusterMode">否</span>
|
||||
</td>
|
||||
<td>
|
||||
{{ruleEntity.rule.paramFlowItemList == undefined ? 0 : ruleEntity.rule.paramFlowItemList.length}}
|
||||
</td>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue