mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
1.3.0
This commit is contained in:
@@ -675,4 +675,6 @@ table th, table td {
|
||||
color: #393D49;
|
||||
}
|
||||
|
||||
.x-win {display: none;padding: 20px;}
|
||||
.x-win {display: none;padding: 20px;}
|
||||
|
||||
.layui-this{font-weight: bold;}
|
@@ -49,7 +49,7 @@
|
||||
<cite>首页</cite>
|
||||
</a>
|
||||
</li>
|
||||
<li class="open">
|
||||
<!--<li class="open">
|
||||
<a>
|
||||
<i class="layui-icon layui-icon-template-1"></i>
|
||||
<cite>配置管理</cite>
|
||||
@@ -62,7 +62,7 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</li>-->
|
||||
<li class="open">
|
||||
<a>
|
||||
<i class="layui-icon layui-icon-app"></i>
|
||||
@@ -81,6 +81,12 @@
|
||||
<cite>路由管理</cite>
|
||||
</a>
|
||||
</li>
|
||||
<li date-refresh="1">
|
||||
<a href="../service/limitManager.html">
|
||||
<i class="layui-icon layui-icon-chart"></i>
|
||||
<cite>限流管理</cite>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="open">
|
||||
|
101
sop-admin/sop-admin-front/pages/service/limitManager.html
Normal file
101
sop-admin/sop-admin-front/pages/service/limitManager.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="x-admin-sm">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>SOP Admin</title>
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport"
|
||||
content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8"/>
|
||||
<link rel="stylesheet" href="../../assets/css/font.css">
|
||||
<link rel="stylesheet" href="../../assets/css/xadmin.css">
|
||||
<style>
|
||||
.layui-form-label{width: 100px;}
|
||||
.layui-input-block{margin-left: 130px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="x-nav">
|
||||
<span class="layui-breadcrumb">
|
||||
<a href="../dashboard/welcome.html">首页</a>
|
||||
<a><cite>服务管理</cite></a>
|
||||
<a><cite>限流管理</cite></a>
|
||||
</span>
|
||||
<a class="layui-btn layui-btn-small layui-btn-normal" style="line-height:1.6em;margin-top:4px;float:right"
|
||||
href="javascript:location.replace(location.href);" title="刷新">
|
||||
<i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a>
|
||||
</div>
|
||||
<div class="x-body" style="padding-top:5px;">
|
||||
<div class="layui-row">
|
||||
<div class="layui-tab" lay-filter="serviceTabFilter" style="margin-top: 0;">
|
||||
<ul id="serviceTab" class="layui-tab-title">
|
||||
</ul>
|
||||
</div>
|
||||
<div class="layui-row">
|
||||
<form class="layui-form layui-col-md12 x-so" action="" lay-filter="searchFrm">
|
||||
路由名称:
|
||||
<input name="id" class="layui-input" style="width: 200px;" placeholder="输入接口名或版本号">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="searchFilter">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<table class="layui-hide" id="limitTable" lay-filter="limitTableFilter"></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="updateWin" class="x-win">
|
||||
<form id="updateForm" class="layui-form" action="" lay-filter="updateWinFilter">
|
||||
<input type="hidden" name="serviceId" />
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">id</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="id" readonly="readonly" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">限流策略</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="type" value="1" title="漏桶策略" lay-filter="limitTypeFilter">
|
||||
<input type="radio" name="type" value="2" title="令牌桶策略" lay-filter="limitTypeFilter">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item limit-type type1">
|
||||
<label class="layui-form-label">每秒可处理请求数</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="execCountPerSecond" lay-verify="required" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item limit-type type1">
|
||||
<label class="layui-form-label">错误码</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="limitCode" lay-verify="required" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item limit-type type1">
|
||||
<label class="layui-form-label">错误信息</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="limitMsg" lay-verify="required" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item limit-type type2">
|
||||
<label class="layui-form-label">令牌桶容量</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="tokenBucketCount" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-input-block">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="updateWinSubmitFilter">保存</button>
|
||||
<button type="button" class="layui-btn layui-btn-primary" onclick="layer.closeAll()">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="../../assets/js/lib.js"></script>
|
||||
<script type="text/javascript" src="limitManager.js"></script>
|
||||
</body>
|
||||
</html>
|
165
sop-admin/sop-admin-front/pages/service/limitManager.js
Normal file
165
sop-admin/sop-admin-front/pages/service/limitManager.js
Normal file
@@ -0,0 +1,165 @@
|
||||
lib.importJs('../../assets/js/routerole.js')
|
||||
.use(['element', 'table', 'tree', 'form'], function () {
|
||||
var LIMIT_STATUS = {
|
||||
'1': '<span class="x-green">已开启</span>'
|
||||
,'0': '<span class="x-red">已关闭</span>'
|
||||
}
|
||||
// 限流策略,1:漏桶策略,2:令牌桶策略
|
||||
var LIMIT_TYPE = {
|
||||
'1': '漏桶策略'
|
||||
,'2': '令牌桶策略'
|
||||
}
|
||||
var element = layui.element;
|
||||
var form = layui.form;
|
||||
var updateForm = layui.Form('updateForm');
|
||||
var addForm = layui.Form('addForm');
|
||||
var authForm = layui.Form('authForm');
|
||||
var table = layui.table;
|
||||
|
||||
var currentServiceId;
|
||||
var limitTable;
|
||||
var smTitle;
|
||||
|
||||
|
||||
form.on('submit(searchFilter)', function (data) {
|
||||
var param = data.field;
|
||||
param.serviceId = currentServiceId;
|
||||
searchTable(param)
|
||||
return false;
|
||||
});
|
||||
|
||||
// 监听修改提交
|
||||
form.on('submit(updateWinSubmitFilter)', function(data) {
|
||||
ApiUtil.post('route.update', data.field, function (resp) {
|
||||
layer.closeAll();
|
||||
limitTable.reload();
|
||||
})
|
||||
return false;
|
||||
});
|
||||
|
||||
form.on('radio(limitTypeFilter)', function(data){
|
||||
$('.limit-type').hide();
|
||||
$('.type' + data.value).show();
|
||||
});
|
||||
|
||||
element.on('tab(serviceTabFilter)', function(data){
|
||||
loadLimitTable(this.innerHTML);
|
||||
});
|
||||
|
||||
|
||||
function initServiceTab() {
|
||||
ApiUtil.post('service.list', {}, function (resp) {
|
||||
var serviceList = resp.data;
|
||||
var html = [];
|
||||
for (var i = 0; i < serviceList.length; i++) {
|
||||
var serviceInfo = serviceList[i];
|
||||
var clazz = i === 0 ? 'class="layui-this"' : '';
|
||||
html.push('<li ' + clazz + '>' + serviceInfo.serviceId + '</li>');
|
||||
}
|
||||
$('#serviceTab').html(html.join(''));
|
||||
|
||||
if (serviceList.length > 0) {
|
||||
loadLimitTable(serviceList[0].serviceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function loadLimitTable(serviceId) {
|
||||
currentServiceId = serviceId;
|
||||
searchTable({
|
||||
serviceId: serviceId
|
||||
});
|
||||
smTitle = '[ <strong>serviceId:</strong>' + currentServiceId + ' ]';
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询表格
|
||||
* @param params
|
||||
*/
|
||||
function searchTable(params) {
|
||||
var postData = {
|
||||
data: JSON.stringify(params)
|
||||
};
|
||||
if (!limitTable) {
|
||||
limitTable = renderTable(postData);
|
||||
} else {
|
||||
limitTable.reload({
|
||||
where: postData
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function renderTable(postData) {
|
||||
var limitTable = table.render({
|
||||
elem: '#limitTable'
|
||||
, url: ApiUtil.createUrl('route.limit.list')
|
||||
, where: postData
|
||||
, headers: {access_token: ApiUtil.getAccessToken()}
|
||||
, cellMinWidth: 80 //全局定义常规单元格的最小宽度,layui 2.2.1 新增
|
||||
, cols: [[
|
||||
{field: 'id', title: 'id(接口名+版本号)', width: 200}
|
||||
, {
|
||||
field: 'type', title: '限流策略', width: 80, templet: function (row) {
|
||||
return LIMIT_TYPE[row.type + ''];
|
||||
}
|
||||
}
|
||||
, {
|
||||
field: 'info', title: '限流信息', width: 500, templet: function (row) {
|
||||
if (row.limitStatus == 0) {
|
||||
return '--'
|
||||
}
|
||||
var html = [];
|
||||
if (row.type == 1) {
|
||||
html.push('每秒可处理请求数:' + row.execCountPerSecond);
|
||||
html.push('错误码:' + row.limitCode);
|
||||
html.push('错误信息:' + row.limitMsg);
|
||||
} else if(row.type == 2) {
|
||||
html.push('令牌桶容量:' + row.tokenBucketCount);
|
||||
}
|
||||
return html.join(',');
|
||||
}
|
||||
}
|
||||
, {
|
||||
field: 'limitStatus', title: '状态', width: 80, templet: function (row) {
|
||||
return LIMIT_STATUS[row.limitStatus + ''];
|
||||
}
|
||||
}
|
||||
, {
|
||||
fixed: 'right', title: '操作', width: 100, templet: function (row) {
|
||||
var html = ['<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="edit">修改</a>'];
|
||||
return html.join('');
|
||||
}
|
||||
}
|
||||
]]
|
||||
});
|
||||
|
||||
//监听单元格事件
|
||||
table.on('tool(limitTableFilter)', function(obj) {
|
||||
var data = obj.data;
|
||||
var event = obj.event;
|
||||
if(event === 'edit'){
|
||||
//表单初始赋值
|
||||
data.serviceId = currentServiceId;
|
||||
|
||||
updateForm.setData(data);
|
||||
$('.limit-type').hide();
|
||||
$('.type' + data.type).show();
|
||||
|
||||
layer.open({
|
||||
type: 1
|
||||
,title: '修改限流' + smTitle
|
||||
,area: ['600px', '380px']
|
||||
,content: $('#updateWin') //这里content是一个DOM,注意:最好该元素要存放在body最外层,否则可能被其它的相对元素所影响
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return limitTable;
|
||||
}
|
||||
|
||||
initServiceTab();
|
||||
|
||||
RouteRole.loadAllRole(form, 'roleArea');
|
||||
|
||||
});
|
@@ -21,37 +21,31 @@
|
||||
href="javascript:location.replace(location.href);" title="刷新">
|
||||
<i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a>
|
||||
</div>
|
||||
<div class="x-body">
|
||||
<div class="x-body" style="padding-top:5px;">
|
||||
<div class="layui-row">
|
||||
<div class="layui-col-md2">
|
||||
<ul id="leftTree"></ul>
|
||||
<div class="layui-tab" lay-filter="serviceTabFilter" style="margin-top: 0;">
|
||||
<ul id="serviceTab" class="layui-tab-title">
|
||||
</ul>
|
||||
</div>
|
||||
<div id="optTip" class="layui-col-md2" style="margin-top: 20px;">
|
||||
<i class="layui-icon layui-icon-return"></i>点击树节点查看
|
||||
<div class="layui-row">
|
||||
<form class="layui-form layui-col-md12 x-so" action="" lay-filter="searchFrm">
|
||||
路由名称:
|
||||
<input name="id" class="layui-input" style="width: 200px;" placeholder="输入接口名或版本号">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="searchFilter">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="rightPart" class="layui-col-md10" style="display: none;">
|
||||
<div class="layui-row">
|
||||
<form class="layui-form layui-col-md12 x-so" action="" lay-filter="searchFrm">
|
||||
路由名称:
|
||||
<input name="id" class="layui-input" style="width: 200px;" placeholder="输入接口名或版本号">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="searchFilter">
|
||||
<i class="layui-icon layui-icon-search"></i>搜索
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<table class="layui-hide" id="routeTable" lay-filter="routeTableFilter"></table>
|
||||
<script type="text/html" id="toolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-ms layui-btn-normal" lay-event="add">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加路由
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table class="layui-hide" id="routeTable" lay-filter="routeTableFilter"></table>
|
||||
<script type="text/html" id="toolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-ms layui-btn-normal" lay-event="add">
|
||||
<i class="layui-icon layui-icon-add-1"></i>添加路由
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
</div>
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div id="addWin" class="x-win">
|
||||
@@ -75,20 +69,6 @@
|
||||
<input type="text" name="path" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">合并结果</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="mergeResult" value="1" title="合并">
|
||||
<input type="radio" name="mergeResult" value="0" title="不合并">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">忽略验证</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="ignoreValidate" value="1" title="是">
|
||||
<input type="radio" name="ignoreValidate" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
@@ -126,20 +106,6 @@
|
||||
<input type="text" name="path" class="layui-input"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">合并结果</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="mergeResult" value="1" title="合并">
|
||||
<input type="radio" name="mergeResult" value="0" title="不合并">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">忽略验证</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="radio" name="ignoreValidate" value="1" title="是">
|
||||
<input type="radio" name="ignoreValidate" value="0" title="否">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">状态</label>
|
||||
<div class="layui-input-block">
|
||||
|
@@ -5,6 +5,7 @@ lib.importJs('../../assets/js/routerole.js')
|
||||
,'1': '<span class="x-green">已启用</span>'
|
||||
,'2': '<span class="x-red">已禁用</span>'
|
||||
}
|
||||
var element = layui.element;
|
||||
var form = layui.form;
|
||||
var updateForm = layui.Form('updateForm');
|
||||
var addForm = layui.Form('addForm');
|
||||
@@ -50,43 +51,30 @@ lib.importJs('../../assets/js/routerole.js')
|
||||
return false;
|
||||
});
|
||||
|
||||
element.on('tab(serviceTabFilter)', function(data){
|
||||
loadRouteTable(this.innerHTML);
|
||||
});
|
||||
|
||||
function initTree() {
|
||||
|
||||
function initServiceTab() {
|
||||
ApiUtil.post('service.list', {}, function (resp) {
|
||||
var serviceList = resp.data;
|
||||
var children = [];
|
||||
var html = [];
|
||||
for (var i = 0; i < serviceList.length; i++) {
|
||||
var serviceInfo = serviceList[i];
|
||||
children.push({
|
||||
id: i + 1,
|
||||
name: serviceInfo.serviceId
|
||||
})
|
||||
var clazz = i === 0 ? 'class="layui-this"' : '';
|
||||
html.push('<li ' + clazz + '>' + serviceInfo.serviceId + '</li>');
|
||||
}
|
||||
$('#serviceTab').html(html.join(''));
|
||||
|
||||
layui.tree({
|
||||
elem: '#leftTree' //传入元素选择器
|
||||
, nodes: [{ //节点
|
||||
name: '服务列表'
|
||||
, spread: true // 展开
|
||||
, children: children
|
||||
}]
|
||||
, click: function (node) {
|
||||
if (node.id) {
|
||||
reloadRightPart(node)
|
||||
}
|
||||
}
|
||||
});
|
||||
if (serviceList.length > 0) {
|
||||
loadRouteTable(serviceList[0].serviceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新右边部分
|
||||
* @param node 树节点
|
||||
*/
|
||||
function reloadRightPart(node) {
|
||||
$('#optTip').hide();
|
||||
$('#rightPart').show();
|
||||
var serviceId = node.name;
|
||||
|
||||
function loadRouteTable(serviceId) {
|
||||
currentServiceId = serviceId;
|
||||
searchTable({
|
||||
serviceId: serviceId
|
||||
@@ -174,7 +162,7 @@ lib.importJs('../../assets/js/routerole.js')
|
||||
layer.open({
|
||||
type: 1
|
||||
,title: '修改路由' + smTitle
|
||||
,area: ['500px', '460px']
|
||||
,area: ['500px', '350px']
|
||||
,content: $('#updateWin') //这里content是一个DOM,注意:最好该元素要存放在body最外层,否则可能被其它的相对元素所影响
|
||||
});
|
||||
} else if (event === 'auth') {
|
||||
@@ -210,7 +198,7 @@ lib.importJs('../../assets/js/routerole.js')
|
||||
layer.open({
|
||||
type: 1
|
||||
,title: '添加路由' + smTitle
|
||||
,area: ['500px', '460px']
|
||||
,area: ['500px', '350px']
|
||||
,content: $('#addWin')
|
||||
});
|
||||
}
|
||||
@@ -218,7 +206,7 @@ lib.importJs('../../assets/js/routerole.js')
|
||||
return routeTable;
|
||||
}
|
||||
|
||||
initTree();
|
||||
initServiceTab();
|
||||
|
||||
RouteRole.loadAllRole(form, 'roleArea');
|
||||
|
||||
|
@@ -37,7 +37,7 @@
|
||||
<dependency>
|
||||
<groupId>net.oschina.durcframework</groupId>
|
||||
<artifactId>easyopen-spring-boot-starter</artifactId>
|
||||
<version>1.16.0</version>
|
||||
<version>1.16.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@@ -8,10 +8,10 @@ import lombok.Data;
|
||||
*/
|
||||
@Data
|
||||
public class IsvFormVO {
|
||||
@ApiDocField(description = "appKey")
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
private String appKey;
|
||||
|
||||
@ApiDocField(description = "secret")
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
@ApiDocField(description = "pubKey")
|
||||
|
@@ -12,15 +12,15 @@ import java.util.List;
|
||||
@Data
|
||||
public class IsvVO {
|
||||
/** 数据库字段:id */
|
||||
@ApiDocField(description = "id")
|
||||
@ApiDocField(description = "id", example = "1")
|
||||
private Long id;
|
||||
|
||||
/** appKey, 数据库字段:app_key */
|
||||
@ApiDocField(description = "appKey")
|
||||
@ApiDocField(description = "appKey", example = "aaaa")
|
||||
private String appKey;
|
||||
|
||||
/** secret, 数据库字段:secret */
|
||||
@ApiDocField(description = "appKey")
|
||||
@ApiDocField(description = "secret", example = "bbbb")
|
||||
private String secret;
|
||||
|
||||
/** 公钥, 数据库字段:pub_key */
|
||||
|
@@ -0,0 +1,115 @@
|
||||
package com.gitee.sop.adminserver.api.service;
|
||||
|
||||
import com.gitee.easyopen.annotation.Api;
|
||||
import com.gitee.easyopen.annotation.ApiService;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDoc;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
||||
import com.gitee.easyopen.exception.ApiException;
|
||||
import com.gitee.easyopen.util.CopyUtil;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminserver.api.service.param.LimitParam;
|
||||
import com.gitee.sop.adminserver.api.service.param.RouteSearchParam;
|
||||
import com.gitee.sop.adminserver.api.service.result.LimitVO;
|
||||
import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
|
||||
import com.gitee.sop.adminserver.bean.RouteConfigDto;
|
||||
import com.gitee.sop.adminserver.common.LimitEnum;
|
||||
import com.gitee.sop.adminserver.entity.ConfigRouteLimit;
|
||||
import com.gitee.sop.adminserver.mapper.ConfigRouteLimitMapper;
|
||||
import com.gitee.sop.adminserver.service.RouteConfigService;
|
||||
import com.gitee.sop.adminserver.service.RouteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 限流
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@ApiService
|
||||
@ApiDoc("服务管理")
|
||||
@Slf4j
|
||||
public class LimitApi {
|
||||
|
||||
@Autowired
|
||||
RouteService routeService;
|
||||
|
||||
@Autowired
|
||||
RouteConfigService routeConfigService;
|
||||
|
||||
@Autowired
|
||||
ConfigRouteLimitMapper configRouteLimitMapper;
|
||||
|
||||
@Api(name = "route.limit.list")
|
||||
@ApiDocMethod(description = "限流列表", elementClass = LimitVO.class)
|
||||
List<LimitVO> listLimit(RouteSearchParam param) throws Exception {
|
||||
List<GatewayRouteDefinition> routeDefinitionList = routeService.getRouteDefinitionList(param);
|
||||
List<String> routeIdList = getRouteIdList(routeDefinitionList);
|
||||
// key:routeId
|
||||
Map<String, ConfigRouteLimit> routeLimitMap = getStoreConfigRouteLimit(routeIdList);
|
||||
List<LimitVO> gatewayRouteDefinitions = routeDefinitionList
|
||||
.stream()
|
||||
.map(gatewayRouteDefinition -> {
|
||||
LimitVO vo = new LimitVO();
|
||||
CopyUtil.copyProperties(gatewayRouteDefinition, vo);
|
||||
ConfigRouteLimit configRouteLimit = routeLimitMap.getOrDefault(gatewayRouteDefinition.getId(), getDefaultLimit());
|
||||
CopyUtil.copyPropertiesIgnoreNull(configRouteLimit, vo);
|
||||
return vo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
return gatewayRouteDefinitions;
|
||||
}
|
||||
|
||||
private List<String> getRouteIdList(List<GatewayRouteDefinition> routeDefinitionList) {
|
||||
return routeDefinitionList
|
||||
.stream()
|
||||
.map(GatewayRouteDefinition::getId)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Map<String, ConfigRouteLimit> getStoreConfigRouteLimit(List<String> routeIdList) {
|
||||
Query query = new Query();
|
||||
query.in("route_id", routeIdList);
|
||||
// key:routeId
|
||||
Map<String, ConfigRouteLimit> routeLimitMap = configRouteLimitMapper.list(query)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ConfigRouteLimit::getRouteId, Function.identity()));
|
||||
return routeLimitMap;
|
||||
}
|
||||
|
||||
private ConfigRouteLimit getDefaultLimit() {
|
||||
ConfigRouteLimit configRouteLimit = new ConfigRouteLimit();
|
||||
configRouteLimit.setType(LimitEnum.TYPE_LEAKY_BUCKET.getVal());
|
||||
configRouteLimit.setLimitStatus(LimitEnum.STATUS_CLOSE.getVal());
|
||||
return configRouteLimit;
|
||||
}
|
||||
|
||||
@Api(name = "route.limit.update")
|
||||
@ApiDocMethod(description = "修改限流")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateLimtit(LimitParam param) {
|
||||
String routeId = param.getRouteId();
|
||||
ConfigRouteLimit configRouteLimit = configRouteLimitMapper.getByColumn("route_id", routeId);
|
||||
if (configRouteLimit == null) {
|
||||
configRouteLimit = new ConfigRouteLimit();
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, configRouteLimit);
|
||||
configRouteLimitMapper.save(configRouteLimit);
|
||||
} else {
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, configRouteLimit);
|
||||
configRouteLimitMapper.updateIgnoreNull(configRouteLimit);
|
||||
}
|
||||
RouteConfigDto routeConfigDto = new RouteConfigDto();
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, routeConfigDto);
|
||||
try {
|
||||
routeConfigService.sendRouteConfigMsg(routeConfigDto);
|
||||
} catch (Exception e) {
|
||||
log.error("推送限流消息错误, param:{}", param, e);
|
||||
throw new ApiException("修改失败,请查看日志");
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,6 +6,7 @@ import com.gitee.easyopen.annotation.ApiService;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDoc;
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
||||
import com.gitee.easyopen.exception.ApiException;
|
||||
import com.gitee.easyopen.util.CopyUtil;
|
||||
import com.gitee.fastmybatis.core.query.Query;
|
||||
import com.gitee.sop.adminserver.api.isv.result.RoleVO;
|
||||
import com.gitee.sop.adminserver.api.service.param.RouteParam;
|
||||
@@ -14,23 +15,26 @@ import com.gitee.sop.adminserver.api.service.param.RouteSearchParam;
|
||||
import com.gitee.sop.adminserver.api.service.result.RouteVO;
|
||||
import com.gitee.sop.adminserver.api.service.result.ServiceInfo;
|
||||
import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
|
||||
import com.gitee.sop.adminserver.bean.RouteConfigDto;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import com.gitee.sop.adminserver.entity.ConfigRouteBase;
|
||||
import com.gitee.sop.adminserver.entity.PermRole;
|
||||
import com.gitee.sop.adminserver.entity.PermRolePermission;
|
||||
import com.gitee.sop.adminserver.mapper.ConfigRouteBaseMapper;
|
||||
import com.gitee.sop.adminserver.mapper.PermRoleMapper;
|
||||
import com.gitee.sop.adminserver.mapper.PermRolePermissionMapper;
|
||||
import com.gitee.sop.adminserver.service.RouteConfigService;
|
||||
import com.gitee.sop.adminserver.service.RoutePermissionService;
|
||||
import com.gitee.sop.adminserver.service.RouteService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -49,36 +53,24 @@ public class RouteApi {
|
||||
@Autowired
|
||||
PermRoleMapper permRoleMapper;
|
||||
|
||||
@Autowired
|
||||
ConfigRouteBaseMapper configRouteBaseMapper;
|
||||
|
||||
@Autowired
|
||||
RoutePermissionService routePermissionService;
|
||||
|
||||
@Autowired
|
||||
RouteConfigService routeConfigService;
|
||||
|
||||
@Autowired
|
||||
RouteService routeService;
|
||||
|
||||
@Api(name = "route.list")
|
||||
@ApiDocMethod(description = "路由列表")
|
||||
List<RouteVO> listRoute(RouteSearchParam param) throws Exception {
|
||||
if (StringUtils.isBlank(param.getServiceId())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String searchPath = ZookeeperContext.getSopRouteRootPath() + "/" + param.getServiceId();
|
||||
|
||||
List<ChildData> childDataList = ZookeeperContext.getChildrenData(searchPath);
|
||||
|
||||
List<RouteVO> routeDefinitionList = childDataList.stream()
|
||||
.map(childData -> {
|
||||
String serviceNodeData = new String(childData.getData());
|
||||
GatewayRouteDefinition routeDefinition = JSON.parseObject(serviceNodeData, GatewayRouteDefinition.class);
|
||||
return routeDefinition;
|
||||
})
|
||||
.filter(gatewayRouteDefinition -> {
|
||||
boolean isRoute = gatewayRouteDefinition.getOrder() != Integer.MIN_VALUE;
|
||||
String id = param.getId();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
return isRoute;
|
||||
} else {
|
||||
return isRoute && gatewayRouteDefinition.getId().contains(id);
|
||||
}
|
||||
})
|
||||
.map(gatewayRouteDefinition->{
|
||||
List<RouteVO> routeDefinitionList = routeService.getRouteDefinitionList(param)
|
||||
.stream()
|
||||
.map(gatewayRouteDefinition -> {
|
||||
RouteVO vo = new RouteVO();
|
||||
BeanUtils.copyProperties(gatewayRouteDefinition, vo);
|
||||
vo.setRoles(this.getRouteRole(gatewayRouteDefinition.getId()));
|
||||
@@ -96,8 +88,10 @@ public class RouteApi {
|
||||
String zookeeperRoutePath = serviceIdPath + "/" + param.getId();
|
||||
String data = ZookeeperContext.getData(zookeeperRoutePath);
|
||||
GatewayRouteDefinition routeDefinition = JSON.parseObject(data, GatewayRouteDefinition.class);
|
||||
BeanUtils.copyProperties(param, routeDefinition);
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition);
|
||||
ZookeeperContext.updatePathData(zookeeperRoutePath, JSON.toJSONString(routeDefinition));
|
||||
|
||||
this.updateRouteConfig(param);
|
||||
}
|
||||
|
||||
@Api(name = "route.add")
|
||||
@@ -109,7 +103,7 @@ public class RouteApi {
|
||||
throw new ApiException("id已存在");
|
||||
}
|
||||
GatewayRouteDefinition routeDefinition = new GatewayRouteDefinition();
|
||||
BeanUtils.copyProperties(param, routeDefinition);
|
||||
CopyUtil.copyPropertiesIgnoreNull(param, routeDefinition);
|
||||
ZookeeperContext.createNewData(zookeeperRoutePath, JSON.toJSONString(routeDefinition));
|
||||
ServiceInfo serviceInfo = new ServiceInfo();
|
||||
serviceInfo.setServiceId(param.getServiceId());
|
||||
@@ -118,6 +112,37 @@ public class RouteApi {
|
||||
serviceInfo.setCreateTime(now);
|
||||
serviceInfo.setUpdateTime(now);
|
||||
ZookeeperContext.updatePathData(serviceIdPath, JSON.toJSONString(serviceInfo));
|
||||
|
||||
this.updateRouteConfig(param);
|
||||
}
|
||||
|
||||
private void updateRouteConfig(RouteParam param) {
|
||||
try {
|
||||
String routeId = param.getId();
|
||||
ConfigRouteBase configRouteBase = configRouteBaseMapper.getByColumn("route_id", routeId);
|
||||
boolean doSave = configRouteBase == null;
|
||||
if (doSave) {
|
||||
configRouteBase = new ConfigRouteBase();
|
||||
configRouteBase.setRouteId(param.getId());
|
||||
}
|
||||
configRouteBase.setStatus(param.getStatus().byteValue());
|
||||
|
||||
int i = doSave ? configRouteBaseMapper.save(configRouteBase)
|
||||
: configRouteBaseMapper.update(configRouteBase);
|
||||
|
||||
if (i > 0) {
|
||||
this.sendMsg(param);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("发送msg失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMsg(RouteParam param) throws Exception {
|
||||
RouteConfigDto routeConfigDto = new RouteConfigDto();
|
||||
routeConfigDto.setRouteId(param.getId());
|
||||
routeConfigDto.setStatus(param.getStatus());
|
||||
routeConfigService.sendRouteConfigMsg(routeConfigDto);
|
||||
}
|
||||
|
||||
@Api(name = "route.role.get")
|
||||
@@ -166,9 +191,10 @@ public class RouteApi {
|
||||
}
|
||||
|
||||
try {
|
||||
routePermissionService.sendRoutePermissionReloadToZookeeper();
|
||||
routePermissionService.sendRoutePermissionReloadMsg();
|
||||
} catch (Exception e) {
|
||||
log.info("消息推送--路由权限(reload)失败",e);
|
||||
log.info("消息推送--路由权限(reload)失败", e);
|
||||
throw new ApiException("修改失败,请查看日志");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,45 @@
|
||||
package com.gitee.sop.adminserver.api.service.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 限流
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class LimitParam {
|
||||
@ApiDocField(description = "routeId")
|
||||
@NotBlank
|
||||
private String routeId;
|
||||
|
||||
/** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
|
||||
@ApiDocField(description = "限流策略,1:漏桶策略,2:令牌桶策略")
|
||||
@NotNull
|
||||
private Byte type;
|
||||
|
||||
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
|
||||
@ApiDocField(description = "每秒可处理请求数")
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
@ApiDocField(description = "返回的错误码")
|
||||
private String limitCode;
|
||||
|
||||
/** 返回的错误信息, 数据库字段:limit_msg */
|
||||
@ApiDocField(description = "返回的错误信息")
|
||||
private String limitMsg;
|
||||
|
||||
/** 令牌桶容量, 数据库字段:token_bucket_count */
|
||||
@ApiDocField(description = "令牌桶容量")
|
||||
private Integer tokenBucketCount;
|
||||
|
||||
/** 1:开启,0关闭, 数据库字段:limit_status */
|
||||
@ApiDocField(description = "1:开启,0关闭")
|
||||
@NotNull
|
||||
private Byte limitStatus;
|
||||
}
|
@@ -38,14 +38,6 @@ public class RouteParam {
|
||||
@ApiDocField(description = "路由path")
|
||||
private String path;
|
||||
|
||||
|
||||
/**
|
||||
* 是否忽略验证,业务参数验证除外
|
||||
*/
|
||||
@NotNull
|
||||
@ApiDocField(description = "是否忽略验证,1:是,0:否")
|
||||
private Integer ignoreValidate;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@@ -53,10 +45,4 @@ public class RouteParam {
|
||||
@ApiDocField(description = "状态,0:审核,1:启用,2:禁用")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@NotNull
|
||||
@ApiDocField(description = "是否合并结果,1:是,0:否")
|
||||
private Integer mergeResult;
|
||||
}
|
||||
|
@@ -4,12 +4,18 @@ import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class RouteSearchParam extends ServiceSearchParam {
|
||||
@ApiDocField(description = "id")
|
||||
public class RouteSearchParam {
|
||||
@ApiDocField(description = "服务名serviceId")
|
||||
@NotBlank(message = "serviceId不能为空")
|
||||
private String serviceId;
|
||||
|
||||
@ApiDocField(description = "路由id")
|
||||
private String id;
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@ import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@@ -11,6 +13,6 @@ import lombok.Setter;
|
||||
@Setter
|
||||
public class ServiceSearchParam {
|
||||
|
||||
@ApiDocField(description = "serviceId")
|
||||
@ApiDocField(description = "服务名serviceId")
|
||||
private String serviceId;
|
||||
}
|
||||
|
@@ -0,0 +1,54 @@
|
||||
package com.gitee.sop.adminserver.api.service.result;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 限流
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class LimitVO {
|
||||
@ApiDocField(description = "路由id")
|
||||
private String id;
|
||||
|
||||
@ApiDocField(description = "serviceId")
|
||||
private String serviceId;
|
||||
|
||||
/**
|
||||
* 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type
|
||||
*/
|
||||
@ApiDocField(description = "限流策略,1:漏桶策略,2:令牌桶策略")
|
||||
private Byte type;
|
||||
|
||||
/**
|
||||
* 每秒可处理请求数, 数据库字段:exec_count_per_second
|
||||
*/
|
||||
@ApiDocField(description = "每秒可处理请求数")
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/**
|
||||
* 返回的错误码, 数据库字段:limit_code
|
||||
*/
|
||||
@ApiDocField(description = "返回的错误码")
|
||||
private String limitCode;
|
||||
|
||||
/**
|
||||
* 返回的错误信息, 数据库字段:limit_msg
|
||||
*/
|
||||
@ApiDocField(description = "返回的错误信息")
|
||||
private String limitMsg;
|
||||
|
||||
/**
|
||||
* 令牌桶容量, 数据库字段:token_bucket_count
|
||||
*/
|
||||
@ApiDocField(description = "令牌桶容量")
|
||||
private Integer tokenBucketCount;
|
||||
|
||||
/**
|
||||
* 1:开启,0关闭, 数据库字段:limit_status
|
||||
*/
|
||||
@ApiDocField(description = "1:开启,0关闭")
|
||||
private Byte limitStatus;
|
||||
}
|
@@ -1,9 +1,17 @@
|
||||
package com.gitee.sop.adminserver.api.system.param;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
public class LoginForm {
|
||||
@NotBlank(message = "用户名不能为空")
|
||||
@ApiDocField(description = "用户名", required = true)
|
||||
private String username;
|
||||
|
||||
@NotBlank(message = "密码不能为空")
|
||||
@ApiDocField(description = "密码", required = true)
|
||||
private String password;
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
|
||||
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -13,6 +14,7 @@ public class GatewayRouteDefinition {
|
||||
/**
|
||||
* 路由的Id
|
||||
*/
|
||||
@ApiDocField(description = "路由id")
|
||||
private String id = "";
|
||||
|
||||
/**
|
||||
@@ -28,11 +30,13 @@ public class GatewayRouteDefinition {
|
||||
/**
|
||||
* 路由规则转发的目标uri
|
||||
*/
|
||||
@ApiDocField(description = "uri")
|
||||
private String uri;
|
||||
|
||||
/**
|
||||
* uri后面跟的path
|
||||
*/
|
||||
@ApiDocField(description = "path")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
@@ -43,20 +47,24 @@ public class GatewayRouteDefinition {
|
||||
/**
|
||||
* 是否忽略验证,业务参数验证除外
|
||||
*/
|
||||
@ApiDocField(description = "是否忽略验证,业务参数验证除外,1:忽略,0:不忽略")
|
||||
private int ignoreValidate;
|
||||
|
||||
/**
|
||||
* 状态,0:待审核,1:启用,2:禁用
|
||||
*/
|
||||
@ApiDocField(description = "状态,0:待审核,1:启用,2:禁用")
|
||||
private int status = 1;
|
||||
|
||||
/**
|
||||
* 合并结果
|
||||
*/
|
||||
@ApiDocField(description = "合并结果,1:合并,2:不合并")
|
||||
private int mergeResult = 1;
|
||||
|
||||
/**
|
||||
* 是否需要授权才能访问
|
||||
*/
|
||||
@ApiDocField(description = "是否需要授权才能访问,1:是,2:否")
|
||||
private int permission;
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package com.gitee.sop.adminserver.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Data
|
||||
public class RouteConfigDto {
|
||||
|
||||
private String routeId;
|
||||
|
||||
/** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
|
||||
private Byte type;
|
||||
|
||||
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
private String limitCode;
|
||||
|
||||
/** 返回的错误信息, 数据库字段:limit_msg */
|
||||
private String limitMsg;
|
||||
|
||||
/** 令牌桶容量, 数据库字段:token_bucket_count */
|
||||
private Integer tokenBucketCount;
|
||||
|
||||
/** 限流开启状态,1:开启,0关闭, 数据库字段:limit_status */
|
||||
private Byte limitStatus;
|
||||
|
||||
/**
|
||||
* 状态,0:待审核,1:启用,2:禁用
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
|
||||
}
|
@@ -67,6 +67,10 @@ public class ZookeeperContext {
|
||||
return SOP_MSG_CHANNEL_PATH + "/isv-route-permission";
|
||||
}
|
||||
|
||||
public static String getRouteConfigChannelPath() {
|
||||
return SOP_MSG_CHANNEL_PATH + "/route-conf";
|
||||
}
|
||||
|
||||
public static CuratorFramework getClient() {
|
||||
return client;
|
||||
}
|
||||
|
@@ -0,0 +1,36 @@
|
||||
package com.gitee.sop.adminserver.common;
|
||||
|
||||
/**
|
||||
* 限流
|
||||
* @author tanghc
|
||||
*/
|
||||
public enum LimitEnum {
|
||||
/**
|
||||
* 限流策略,1:漏桶策略
|
||||
*/
|
||||
TYPE_LEAKY_BUCKET((byte) 1),
|
||||
/**
|
||||
* 限流策略,2:令牌桶策略
|
||||
*/
|
||||
TYPE_TOKEN_BUCKET((byte) 2),
|
||||
/**
|
||||
* 1:开启
|
||||
*/
|
||||
STATUS_OPEN((byte) 1),
|
||||
/**
|
||||
* 0关闭
|
||||
*/
|
||||
STATUS_CLOSE((byte) 0),
|
||||
|
||||
;
|
||||
|
||||
LimitEnum(byte val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
private byte val;
|
||||
|
||||
public byte getVal() {
|
||||
return val;
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_route_base
|
||||
* 备注:路由配置表
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "config_route_base")
|
||||
@Data
|
||||
public class ConfigRouteBase {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Long id;
|
||||
|
||||
/** 路由id, 数据库字段:route_id */
|
||||
private String routeId;
|
||||
|
||||
/** 状态,1:启用,2:禁用, 数据库字段:status */
|
||||
private Byte status;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
package com.gitee.sop.adminserver.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
|
||||
/**
|
||||
* 表名:config_route_limit
|
||||
* 备注:路由限流配置
|
||||
*
|
||||
* @author tanghc
|
||||
*/
|
||||
@Table(name = "config_route_limit")
|
||||
@Data
|
||||
public class ConfigRouteLimit {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
/** 数据库字段:id */
|
||||
private Integer id;
|
||||
|
||||
/** 路由id, 数据库字段:route_id */
|
||||
private String routeId;
|
||||
|
||||
/** 限流策略,1:漏桶策略,2:令牌桶策略, 数据库字段:type */
|
||||
private Byte type;
|
||||
|
||||
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
private String limitCode;
|
||||
|
||||
/** 返回的错误信息, 数据库字段:limit_msg */
|
||||
private String limitMsg;
|
||||
|
||||
/** 令牌桶容量, 数据库字段:token_bucket_count */
|
||||
private Integer tokenBucketCount;
|
||||
|
||||
/** 1:开启,0关闭, 数据库字段:limit_status */
|
||||
private Byte limitStatus;
|
||||
|
||||
/** 数据库字段:gmt_create */
|
||||
private Date gmtCreate;
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
|
||||
import com.gitee.sop.adminserver.entity.ConfigRouteBase;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ConfigRouteBaseMapper extends CrudMapper<ConfigRouteBase, Long> {
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.gitee.sop.adminserver.mapper;
|
||||
|
||||
import com.gitee.fastmybatis.core.mapper.CrudMapper;
|
||||
|
||||
import com.gitee.sop.adminserver.entity.ConfigRouteLimit;
|
||||
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
public interface ConfigRouteLimitMapper extends CrudMapper<ConfigRouteLimit, Integer> {
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package com.gitee.sop.adminserver.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Service
|
||||
public class ConfigRouteBaseService {
|
||||
|
||||
public void updateConfigRouteBase() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package com.gitee.sop.adminserver.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.sop.adminserver.bean.ChannelMsg;
|
||||
import com.gitee.sop.adminserver.bean.RouteConfigDto;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class RouteConfigService {
|
||||
|
||||
/**
|
||||
* 发送路由配置消息
|
||||
* @param routeConfigDto
|
||||
* @throws Exception
|
||||
*/
|
||||
public void sendRouteConfigMsg(RouteConfigDto routeConfigDto) throws Exception {
|
||||
String configData = JSON.toJSONString(routeConfigDto);
|
||||
ChannelMsg channelMsg = new ChannelMsg("update", configData);
|
||||
String jsonData = JSON.toJSONString(channelMsg);
|
||||
String path = ZookeeperContext.getRouteConfigChannelPath();
|
||||
log.info("消息推送--路由配置(update), path:{}, data:{}", path, jsonData);
|
||||
ZookeeperContext.createOrUpdateData(path, jsonData);
|
||||
}
|
||||
}
|
@@ -93,7 +93,7 @@ public class RoutePermissionService {
|
||||
/**
|
||||
* 推送所有路由权限到zookeeper
|
||||
*/
|
||||
public void sendRoutePermissionReloadToZookeeper() throws Exception {
|
||||
public void sendRoutePermissionReloadMsg() throws Exception {
|
||||
ChannelMsg channelMsg = new ChannelMsg("reload", null);
|
||||
String jsonData = JSON.toJSONString(channelMsg);
|
||||
String path = ZookeeperContext.getIsvRoutePermissionChannelPath();
|
||||
|
@@ -0,0 +1,53 @@
|
||||
package com.gitee.sop.adminserver.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.sop.adminserver.api.service.param.RouteSearchParam;
|
||||
import com.gitee.sop.adminserver.bean.GatewayRouteDefinition;
|
||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* @author tanghc
|
||||
*/
|
||||
@Service
|
||||
public class RouteService {
|
||||
|
||||
public List<GatewayRouteDefinition> getRouteDefinitionList(RouteSearchParam param) throws Exception {
|
||||
if (StringUtils.isBlank(param.getServiceId())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String searchPath = ZookeeperContext.getSopRouteRootPath() + "/" + param.getServiceId();
|
||||
|
||||
List<ChildData> childDataList = ZookeeperContext.getChildrenData(searchPath);
|
||||
|
||||
List<GatewayRouteDefinition> routeDefinitionStream = childDataList.stream()
|
||||
.map(childData -> {
|
||||
String serviceNodeData = new String(childData.getData());
|
||||
GatewayRouteDefinition routeDefinition = JSON.parseObject(serviceNodeData, GatewayRouteDefinition.class);
|
||||
return routeDefinition;
|
||||
})
|
||||
.filter(gatewayRouteDefinition -> {
|
||||
boolean isRoute = gatewayRouteDefinition.getOrder() != Integer.MIN_VALUE;
|
||||
String id = param.getId();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
return isRoute;
|
||||
} else {
|
||||
return isRoute && gatewayRouteDefinition.getId().contains(id);
|
||||
}
|
||||
})
|
||||
.collect(toList())
|
||||
;
|
||||
|
||||
return routeDefinitionStream;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user