Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
springcloud-sentinel
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
senthink-project-origin
springcloud-sentinel
Commits
6d512971
Commit
6d512971
authored
Apr 18, 2020
by
李根
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1 添加网关规则持久化至nacos 2 修改网关限流 列表页 只调用一个接口,获取api分组数据和网关流控规则数据
parent
a3289421
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1543 additions
and
45 deletions
+1543
-45
Test/src/main/java/com/demo/senthinel/Test.java
+3
-3
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/DashboardApplication.java
+3
-1
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/NacosConfig.java
+22
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/NacosProperties.java
+22
-4
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiControllerV2.java
+260
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleControllerV2.java
+0
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/dao/MetricEntityDao.java
+10
-9
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/dao/ResourcesListMongoDao.java
+8
-6
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricEntity.java
+2
-2
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/metric/MetricFetcher.java
+1
-1
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/repository/rule/InMemoryRuleRepositoryAdapter.java
+2
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayApiGroupNacosProvider.java
+56
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayApiGroupNacosPublisher.java
+53
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayFlowRuleNacosProvider.java
+54
-0
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayFlowRuleNacosPublisher.java
+53
-0
sentinel-dashboard/src/main/resources/application.yml
+6
-6
sentinel-dashboard/src/main/webapp/resources/app/scripts/app.js
+33
-0
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/gateway/api_v2.js
+245
-0
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/gateway/flow_v2.js
+270
-0
sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html
+12
-3
sentinel-dashboard/src/main/webapp/resources/app/scripts/services/gateway/api_service_v2.js
+73
-0
sentinel-dashboard/src/main/webapp/resources/app/scripts/services/gateway/flow_service_v2.js
+76
-0
sentinel-dashboard/src/main/webapp/resources/app/views/gateway/api_v2.html
+91
-0
sentinel-dashboard/src/main/webapp/resources/app/views/gateway/flow_v2.html
+110
-0
sentinel-dashboard/src/main/webapp/resources/app/views/metric.html
+4
-4
sentinel-dashboard/src/main/webapp/resources/gulpfile.js
+2
-0
sentinel-dashboard/src/main/webapp/resources/index.htm
+3
-1
sentinel-demo-springboot-nacos/pom.xml
+68
-4
sentinel-demo-springboot-nacos/sentinel-demo-springboot-nacos.iml
+1
-1
No files found.
Test/src/main/java/com/demo/senthinel/Test.java
View file @
6d512971
...
@@ -17,9 +17,9 @@ public class Test {
...
@@ -17,9 +17,9 @@ public class Test {
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
// 测试限流
// 测试限流
test
(
25
,
"
/test2"
);
test
(
5
,
"/test
/test2"
);
// 测试降级
// 测试降级
test
(
5
,
"/test3"
);
//
test(5, "/test3");
}
}
...
@@ -37,7 +37,7 @@ public class Test {
...
@@ -37,7 +37,7 @@ public class Test {
Thread
thread
=
new
Thread
(
Thread
thread
=
new
Thread
(
()
->
{
()
->
{
while
(
true
)
{
while
(
true
)
{
ListenableFuture
<
Response
>
execute
=
asyncHttpClient
.
prepareGet
(
"http://localhost:
19966
"
+
resource
).
execute
();
ListenableFuture
<
Response
>
execute
=
asyncHttpClient
.
prepareGet
(
"http://localhost:
7051/columbia
"
+
resource
).
execute
();
System
.
out
.
println
(
"resources:"
+
resource
+
"-----"
+
Thread
.
currentThread
().
getName
());
System
.
out
.
println
(
"resources:"
+
resource
+
"-----"
+
Thread
.
currentThread
().
getName
());
try
{
try
{
Thread
.
sleep
(
random
.
nextInt
(
1000
));
Thread
.
sleep
(
random
.
nextInt
(
1000
));
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/DashboardApplication.java
View file @
6d512971
...
@@ -20,13 +20,15 @@ import com.alibaba.csp.sentinel.init.InitExecutor;
...
@@ -20,13 +20,15 @@ import com.alibaba.csp.sentinel.init.InitExecutor;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
;
import
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration
;
/**
/**
* Sentinel dashboard application.
* Sentinel dashboard application.
*
*
* @author Carpenter Lee
* @author Carpenter Lee
*/
*/
@SpringBootApplication
@SpringBootApplication
(
exclude
=
{
MongoAutoConfiguration
.
class
,
MongoDataAutoConfiguration
.
class
}
)
public
class
DashboardApplication
{
public
class
DashboardApplication
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/NacosConfig.java
View file @
6d512971
...
@@ -15,6 +15,8 @@
...
@@ -15,6 +15,8 @@
*/
*/
package
com
.
alibaba
.
csp
.
sentinel
.
dashboard
.
config
;
package
com
.
alibaba
.
csp
.
sentinel
.
dashboard
.
config
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity
;
import
com.alibaba.csp.sentinel.datasource.Converter
;
import
com.alibaba.csp.sentinel.datasource.Converter
;
...
@@ -58,6 +60,26 @@ public class NacosConfig {
...
@@ -58,6 +60,26 @@ public class NacosConfig {
return
s
->
JSON
.
parseArray
(
s
,
DegradeRuleEntity
.
class
);
return
s
->
JSON
.
parseArray
(
s
,
DegradeRuleEntity
.
class
);
}
}
@Bean
public
Converter
<
List
<
ApiDefinitionEntity
>,
String
>
apiDefinitionEntryEncoder
()
{
return
JSON:
:
toJSONString
;
}
@Bean
public
Converter
<
String
,
List
<
ApiDefinitionEntity
>>
apiDefinitionEntryDecoder
()
{
return
s
->
JSON
.
parseArray
(
s
,
ApiDefinitionEntity
.
class
);
}
@Bean
public
Converter
<
List
<
GatewayFlowRuleEntity
>,
String
>
gatewayFlowRuleEntityEncoder
()
{
return
JSON:
:
toJSONString
;
}
@Bean
public
Converter
<
String
,
List
<
GatewayFlowRuleEntity
>>
gatewayFlowRuleEntityDecoder
()
{
return
s
->
JSON
.
parseArray
(
s
,
GatewayFlowRuleEntity
.
class
);
}
@Bean
@Bean
public
ConfigService
nacosConfigService
()
throws
Exception
{
public
ConfigService
nacosConfigService
()
throws
Exception
{
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/config/NacosProperties.java
View file @
6d512971
...
@@ -32,11 +32,15 @@ public class NacosProperties {
...
@@ -32,11 +32,15 @@ public class NacosProperties {
private
String
groupId
=
"DEFAULT_GROUP"
;
private
String
groupId
=
"DEFAULT_GROUP"
;
private
String
flowDataIdPrefix
=
"
-
flow-rules"
;
private
String
flowDataIdPrefix
=
"flow-rules"
;
private
String
degradeDataIdPrefix
=
"
-
degrade-rules"
;
private
String
degradeDataIdPrefix
=
"degrade-rules"
;
private
String
paramFlowDataIdPrefix
=
"-param-rules"
;
private
String
paramFlowDataIdPrefix
=
"param-rules"
;
private
String
gatewayFlowRuleDataIdPrefix
=
"gateway-flow-rules"
;
private
String
gatewayApiDefineDataIdPrefix
=
"gateway-api-define-rules"
;
public
String
getServerAddr
()
{
public
String
getServerAddr
()
{
return
serverAddr
;
return
serverAddr
;
...
@@ -86,9 +90,23 @@ public class NacosProperties {
...
@@ -86,9 +90,23 @@ public class NacosProperties {
this
.
paramFlowDataIdPrefix
=
paramFlowDataIdPrefix
;
this
.
paramFlowDataIdPrefix
=
paramFlowDataIdPrefix
;
}
}
public
String
getGatewayFlowRuleDataIdPrefix
()
{
return
gatewayFlowRuleDataIdPrefix
;
}
public
void
setGatewayFlowRuleDataIdPrefix
(
String
gatewayFlowRuleDataIdPrefix
)
{
this
.
gatewayFlowRuleDataIdPrefix
=
gatewayFlowRuleDataIdPrefix
;
}
public
String
getGatewayApiDefineDataIdPrefix
()
{
return
gatewayApiDefineDataIdPrefix
;
}
public
void
setGatewayApiDefineDataIdPrefix
(
String
gatewayApiDefineDataIdPrefix
)
{
this
.
gatewayApiDefineDataIdPrefix
=
gatewayApiDefineDataIdPrefix
;
}
// public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";
// public static final String CLUSTER_MAP_DATA_ID_POSTFIX = "-cluster-map";
//
//
// /**
// /**
// * cc for `cluster-client`
// * cc for `cluster-client`
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayApiControllerV2.java
0 → 100644
View file @
6d512971
This diff is collapsed.
Click to expand it.
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/gateway/GatewayFlowRuleControllerV2.java
0 → 100644
View file @
6d512971
This diff is collapsed.
Click to expand it.
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/dao/MetricEntityDao.java
View file @
6d512971
...
@@ -20,17 +20,17 @@ import java.util.List;
...
@@ -20,17 +20,17 @@ import java.util.List;
@Component
@Component
public
class
MetricEntityDao
{
public
class
MetricEntityDao
{
@Autowired
//
@Autowired
private
MongoTemplate
mongoTemplate
;
//
private MongoTemplate mongoTemplate;
public
void
save
(
MetricEntity
metric
)
{
public
void
save
(
MetricEntity
metric
)
{
mongoTemplate
.
insert
(
metric
);
//
mongoTemplate.insert(metric);
}
}
//
public
void
savaAll
(
List
<
MetricEntity
>
metricEntities
)
{
//
public void savaAll(List<MetricEntity> metricEntities) {
metricEntities
.
forEach
(
m
->
mongoTemplate
.
save
(
m
));
//
metricEntities.forEach(m -> mongoTemplate.save(m));
}
//
}
//
public
List
<
MetricEntity
>
queryByAppAndResourceBetween
(
String
app
,
String
resource
,
public
List
<
MetricEntity
>
queryByAppAndResourceBetween
(
String
app
,
String
resource
,
long
startTime
,
long
endTime
)
{
long
startTime
,
long
endTime
)
{
Criteria
criteria
=
new
Criteria
();
Criteria
criteria
=
new
Criteria
();
...
@@ -39,7 +39,8 @@ public class MetricEntityDao {
...
@@ -39,7 +39,8 @@ public class MetricEntityDao {
.
and
(
"timestamp"
).
gt
(
new
Date
(
startTime
)).
lt
(
new
Date
(
endTime
));
.
and
(
"timestamp"
).
gt
(
new
Date
(
startTime
)).
lt
(
new
Date
(
endTime
));
Query
query
=
new
Query
(
criteria
);
Query
query
=
new
Query
(
criteria
);
return
mongoTemplate
.
find
(
query
,
MetricEntity
.
class
);
// return mongoTemplate.find(query, MetricEntity.class);
return
null
;
}
}
}
}
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/dao/ResourcesListMongoDao.java
View file @
6d512971
...
@@ -22,22 +22,24 @@ import java.util.stream.Collectors;
...
@@ -22,22 +22,24 @@ import java.util.stream.Collectors;
@Component
@Component
public
class
ResourcesListMongoDao
{
public
class
ResourcesListMongoDao
{
@Autowired
//
@Autowired
private
MongoTemplate
mongoTemplate
;
//
private MongoTemplate mongoTemplate;
public
void
save
(
ResourceListMongo
resource
)
{
public
void
save
(
ResourceListMongo
resource
)
{
mongoTemplate
.
save
(
resource
);
//
mongoTemplate.save(resource);
}
}
public
List
<
ResourceListMongo
>
getByApp
(
String
app
)
{
public
List
<
ResourceListMongo
>
getByApp
(
String
app
)
{
Query
query
=
new
Query
(
Criteria
.
where
(
"app"
).
is
(
app
));
Query
query
=
new
Query
(
Criteria
.
where
(
"app"
).
is
(
app
));
return
mongoTemplate
.
find
(
query
,
ResourceListMongo
.
class
);
// return mongoTemplate.find(query, ResourceListMongo.class);
return
null
;
}
}
public
List
<
String
>
getResourceNameListByApp
(
String
app
)
{
public
List
<
String
>
getResourceNameListByApp
(
String
app
)
{
Query
query
=
new
Query
(
Criteria
.
where
(
"app"
).
is
(
app
));
Query
query
=
new
Query
(
Criteria
.
where
(
"app"
).
is
(
app
));
List
<
ResourceListMongo
>
resourceListMongos
=
mongoTemplate
.
find
(
query
,
ResourceListMongo
.
class
);
// List<ResourceListMongo> resourceListMongos = mongoTemplate.find(query, ResourceListMongo.class);
return
resourceListMongos
.
stream
().
map
(
a
->
a
.
getResources
()).
collect
(
Collectors
.
toList
());
// return resourceListMongos.stream().map(a -> a.getResources()).collect(Collectors.toList());
return
null
;
}
}
}
}
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/datasource/entity/MetricEntity.java
View file @
6d512971
...
@@ -23,9 +23,9 @@ import java.util.Date;
...
@@ -23,9 +23,9 @@ import java.util.Date;
/**
/**
* @author leyou
* @author leyou
*/
*/
@Document
(
collection
=
"MetricEntity"
)
//
@Document(collection = "MetricEntity")
public
class
MetricEntity
{
public
class
MetricEntity
{
@Field
(
"idd"
)
//
@Field("idd")
private
Long
id
;
private
Long
id
;
private
Date
gmtCreate
;
private
Date
gmtCreate
;
private
Date
gmtModified
;
private
Date
gmtModified
;
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/metric/MetricFetcher.java
View file @
6d512971
...
@@ -83,7 +83,7 @@ public class MetricFetcher {
...
@@ -83,7 +83,7 @@ public class MetricFetcher {
@Autowired
@Autowired
// @Qualifier("mongoMetricsRepository")
// @Qualifier("mongoMetricsRepository")
@Qualifier
(
"
mongo
MetricsRepository"
)
@Qualifier
(
"
inMemory
MetricsRepository"
)
private
MetricsRepository
<
MetricEntity
>
metricStore
;
private
MetricsRepository
<
MetricEntity
>
metricStore
;
@Autowired
@Autowired
private
AppManagement
appManagement
;
private
AppManagement
appManagement
;
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/repository/rule/InMemoryRuleRepositoryAdapter.java
View file @
6d512971
...
@@ -56,6 +56,7 @@ public abstract class InMemoryRuleRepositoryAdapter<T extends RuleEntity> implem
...
@@ -56,6 +56,7 @@ public abstract class InMemoryRuleRepositoryAdapter<T extends RuleEntity> implem
nextId
();
nextId
();
MAX_ID
=
entity
.
getId
();
MAX_ID
=
entity
.
getId
();
}
}
// System.out.println(MAX_ID);
T
processedEntity
=
preProcess
(
entity
);
T
processedEntity
=
preProcess
(
entity
);
if
(
processedEntity
!=
null
)
{
if
(
processedEntity
!=
null
)
{
allRules
.
put
(
processedEntity
.
getId
(),
processedEntity
);
allRules
.
put
(
processedEntity
.
getId
(),
processedEntity
);
...
@@ -88,6 +89,7 @@ public abstract class InMemoryRuleRepositoryAdapter<T extends RuleEntity> implem
...
@@ -88,6 +89,7 @@ public abstract class InMemoryRuleRepositoryAdapter<T extends RuleEntity> implem
for
(
T
rule
:
rules
)
{
for
(
T
rule
:
rules
)
{
savedRules
.
add
(
save
(
rule
));
savedRules
.
add
(
save
(
rule
));
}
}
System
.
out
.
println
(
"--MAXNUM"
+
MAX_ID
);
return
savedRules
;
return
savedRules
;
}
}
...
...
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayApiGroupNacosProvider.java
0 → 100644
View file @
6d512971
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
alibaba
.
csp
.
sentinel
.
dashboard
.
rule
.
gateway
;
import
com.alibaba.csp.sentinel.dashboard.config.NacosProperties
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider
;
import
com.alibaba.csp.sentinel.datasource.Converter
;
import
com.alibaba.csp.sentinel.util.StringUtil
;
import
com.alibaba.nacos.api.config.ConfigService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author Eric Zhao
* @since 1.4.0
*/
@Component
(
"gatewayApiNacosProvider"
)
public
class
GatewayApiGroupNacosProvider
implements
DynamicRuleProvider
<
List
<
ApiDefinitionEntity
>>
{
@Autowired
private
NacosProperties
nacosProperties
;
@Autowired
private
ConfigService
configService
;
@Autowired
private
Converter
<
String
,
List
<
ApiDefinitionEntity
>>
converter
;
@Override
public
List
<
ApiDefinitionEntity
>
getRules
(
String
appName
)
throws
Exception
{
String
rules
=
configService
.
getConfig
(
appName
+
'-'
+
nacosProperties
.
getGatewayApiDefineDataIdPrefix
(),
nacosProperties
.
getGroupId
(),
3000
);
if
(
StringUtil
.
isEmpty
(
rules
))
{
return
new
ArrayList
<>();
}
return
converter
.
convert
(
rules
);
}
}
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayApiGroupNacosPublisher.java
0 → 100644
View file @
6d512971
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
alibaba
.
csp
.
sentinel
.
dashboard
.
rule
.
gateway
;
import
com.alibaba.csp.sentinel.dashboard.config.NacosProperties
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher
;
import
com.alibaba.csp.sentinel.datasource.Converter
;
import
com.alibaba.csp.sentinel.util.AssertUtil
;
import
com.alibaba.nacos.api.config.ConfigService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.List
;
/**
* @author Eric Zhao
* @since 1.4.0
*/
@Component
(
"gatewayApiNacosPublisher"
)
public
class
GatewayApiGroupNacosPublisher
implements
DynamicRulePublisher
<
List
<
ApiDefinitionEntity
>>
{
@Autowired
private
NacosProperties
nacosProperties
;
@Autowired
private
ConfigService
configService
;
@Autowired
private
Converter
<
List
<
ApiDefinitionEntity
>,
String
>
converter
;
@Override
public
void
publish
(
String
app
,
List
<
ApiDefinitionEntity
>
rules
)
throws
Exception
{
AssertUtil
.
notEmpty
(
app
,
"app name cannot be empty"
);
if
(
rules
==
null
)
{
return
;
}
configService
.
publishConfig
(
app
+
'-'
+
nacosProperties
.
getGatewayApiDefineDataIdPrefix
(),
nacosProperties
.
getGroupId
(),
converter
.
convert
(
rules
));
}
}
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayFlowRuleNacosProvider.java
0 → 100644
View file @
6d512971
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
alibaba
.
csp
.
sentinel
.
dashboard
.
rule
.
gateway
;
import
com.alibaba.csp.sentinel.dashboard.config.NacosProperties
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider
;
import
com.alibaba.csp.sentinel.datasource.Converter
;
import
com.alibaba.csp.sentinel.util.StringUtil
;
import
com.alibaba.nacos.api.config.ConfigService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author Eric Zhao
* @since 1.4.0
*/
@Component
(
"gatewayFlowRuleNacosProvider"
)
public
class
GatewayFlowRuleNacosProvider
implements
DynamicRuleProvider
<
List
<
GatewayFlowRuleEntity
>>
{
@Autowired
private
NacosProperties
nacosProperties
;
@Autowired
private
ConfigService
configService
;
@Autowired
private
Converter
<
String
,
List
<
GatewayFlowRuleEntity
>>
converter
;
@Override
public
List
<
GatewayFlowRuleEntity
>
getRules
(
String
appName
)
throws
Exception
{
String
rules
=
configService
.
getConfig
(
appName
+
'-'
+
nacosProperties
.
getGatewayFlowRuleDataIdPrefix
(),
nacosProperties
.
getGroupId
(),
3000
);
if
(
StringUtil
.
isEmpty
(
rules
))
{
return
new
ArrayList
<>();
}
return
converter
.
convert
(
rules
);
}
}
sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/gateway/GatewayFlowRuleNacosPublisher.java
0 → 100644
View file @
6d512971
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
alibaba
.
csp
.
sentinel
.
dashboard
.
rule
.
gateway
;
import
com.alibaba.csp.sentinel.dashboard.config.NacosProperties
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity
;
import
com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher
;
import
com.alibaba.csp.sentinel.datasource.Converter
;
import
com.alibaba.csp.sentinel.util.AssertUtil
;
import
com.alibaba.nacos.api.config.ConfigService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
java.util.List
;
/**
* @author Eric Zhao
* @since 1.4.0
*/
@Component
(
"gatewayFlowRuleNacosPublisher"
)
public
class
GatewayFlowRuleNacosPublisher
implements
DynamicRulePublisher
<
List
<
GatewayFlowRuleEntity
>>
{
@Autowired
private
NacosProperties
nacosProperties
;
@Autowired
private
ConfigService
configService
;
@Autowired
private
Converter
<
List
<
GatewayFlowRuleEntity
>,
String
>
converter
;
@Override
public
void
publish
(
String
app
,
List
<
GatewayFlowRuleEntity
>
rules
)
throws
Exception
{
AssertUtil
.
notEmpty
(
app
,
"app name cannot be empty"
);
if
(
rules
==
null
)
{
return
;
}
configService
.
publishConfig
(
app
+
'-'
+
nacosProperties
.
getGatewayFlowRuleDataIdPrefix
(),
nacosProperties
.
getGroupId
(),
converter
.
convert
(
rules
));
}
}
sentinel-dashboard/src/main/resources/application.yml
View file @
6d512971
spring
:
spring
:
application
:
application
:
name
:
sentinel-dashboard-plus
name
:
sentinel-dashboard-plus
#
data:
data
:
#
mongodb:
mongodb
:
#
port: 27017
port
:
27017
#
database: db1
database
:
db1
#
uri: mongodb://lg:123456@xx.xx.xx.xx
uri
:
mongodb://lg:123456@xx.xx.xx.xx
#
authentication-database: admin
authentication-database
:
admin
http
:
http
:
encoding
:
encoding
:
charset
:
utf-8
charset
:
utf-8
...
...
sentinel-dashboard/src/main/webapp/resources/app/scripts/app.js
View file @
6d512971
...
@@ -379,6 +379,22 @@ angular
...
@@ -379,6 +379,22 @@ angular
}
}
})
})
.
state
(
'dashboard.gatewayApiV2'
,
{
templateUrl
:
'app/views/gateway/api_v2.html'
,
url
:
'/v2/gateway/api/:app'
,
controller
:
'GatewayApiCtlV2'
,
resolve
:
{
loadMyFiles
:
[
'$ocLazyLoad'
,
function
(
$ocLazyLoad
)
{
return
$ocLazyLoad
.
load
({
name
:
'sentinelDashboardApp'
,
files
:
[
'app/scripts/controllers/gateway/api_v2.js'
,
]
});
}]
}
})
.
state
(
'dashboard.gatewayFlow'
,
{
.
state
(
'dashboard.gatewayFlow'
,
{
templateUrl
:
'app/views/gateway/flow.html'
,
templateUrl
:
'app/views/gateway/flow.html'
,
url
:
'/gateway/flow/:app'
,
url
:
'/gateway/flow/:app'
,
...
@@ -393,5 +409,21 @@ angular
...
@@ -393,5 +409,21 @@ angular
});
});
}]
}]
}
}
})
.
state
(
'dashboard.gatewayFlowV2'
,
{
templateUrl
:
'app/views/gateway/flow_v2.html'
,
url
:
'/v2/gateway/flow/:app'
,
controller
:
'GatewayFlowCtlV2'
,
resolve
:
{
loadMyFiles
:
[
'$ocLazyLoad'
,
function
(
$ocLazyLoad
)
{
return
$ocLazyLoad
.
load
({
name
:
'sentinelDashboardApp'
,
files
:
[
'app/scripts/controllers/gateway/flow_v2.js'
,
]
});
}]
}
});
});
}]);
}]);
\ No newline at end of file
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/gateway/api_v2.js
0 → 100644
View file @
6d512971
var
app
=
angular
.
module
(
'sentinelDashboardApp'
);
app
.
controller
(
'GatewayApiCtlV2'
,
[
'$scope'
,
'$stateParams'
,
'GatewayApiServiceV2'
,
'ngDialog'
,
'MachineService'
,
function
(
$scope
,
$stateParams
,
GatewayApiService
,
ngDialog
,
MachineService
)
{
$scope
.
app
=
$stateParams
.
app
;
$scope
.
apisPageConfig
=
{
pageSize
:
10
,
currentPageIndex
:
1
,
totalPage
:
1
,
totalCount
:
0
,
};
$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
;
}
};
getApis
();
function
getApis
()
{
if
(
!
$scope
.
macInputModel
)
{
return
;
}
var
mac
=
$scope
.
macInputModel
.
split
(
':'
);
GatewayApiService
.
queryApis
(
$scope
.
app
,
mac
[
0
],
mac
[
1
]).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
&&
data
.
data
)
{
// To merge rows for api who has more than one predicateItems, here we build data manually
$scope
.
apis
=
[];
data
.
data
.
forEach
(
function
(
api
)
{
api
[
"predicateItems"
].
forEach
(
function
(
item
,
index
)
{
var
newItem
=
{};
newItem
[
"id"
]
=
api
[
"id"
];
newItem
[
"app"
]
=
api
[
"app"
];
newItem
[
"ip"
]
=
api
[
"ip"
];
newItem
[
"port"
]
=
api
[
"port"
];
newItem
[
"apiName"
]
=
api
[
"apiName"
];
newItem
[
"pattern"
]
=
item
[
"pattern"
];
newItem
[
"matchStrategy"
]
=
item
[
"matchStrategy"
];
// The itemSize indicates how many rows to merge, by using rowspan="{{api.itemSize}}" in <td> tag
newItem
[
"itemSize"
]
=
api
[
"predicateItems"
].
length
;
// Mark the flag of first item to zero, indicates the start row to merge
newItem
[
"firstFlag"
]
=
index
==
0
?
0
:
1
;
// Still hold the data of predicateItems, in order to bind data in edit dialog html
newItem
[
"predicateItems"
]
=
api
[
"predicateItems"
];
$scope
.
apis
.
push
(
newItem
);
});
});
$scope
.
apisPageConfig
.
totalCount
=
data
.
data
.
length
;
}
else
{
$scope
.
apis
=
[];
$scope
.
apisPageConfig
.
totalCount
=
0
;
}
});
};
$scope
.
getApis
=
getApis
;
var
gatewayApiDialog
;
$scope
.
editApi
=
function
(
api
)
{
$scope
.
currentApi
=
angular
.
copy
(
api
);
$scope
.
gatewayApiDialog
=
{
title
:
'编辑自定义 API'
,
type
:
'edit'
,
confirmBtnText
:
'保存'
};
gatewayApiDialog
=
ngDialog
.
open
({
template
:
'/app/views/dialog/gateway/api-dialog.html'
,
width
:
900
,
overlay
:
true
,
scope
:
$scope
});
};
$scope
.
addNewApi
=
function
()
{
var
mac
=
$scope
.
macInputModel
.
split
(
':'
);
$scope
.
currentApi
=
{
grade
:
0
,
app
:
$scope
.
app
,
ip
:
mac
[
0
],
port
:
mac
[
1
],
predicateItems
:
[{
matchStrategy
:
0
,
pattern
:
''
}]
};
$scope
.
gatewayApiDialog
=
{
title
:
'新增自定义 API'
,
type
:
'add'
,
confirmBtnText
:
'新增'
};
gatewayApiDialog
=
ngDialog
.
open
({
template
:
'/app/views/dialog/gateway/api-dialog.html'
,
width
:
900
,
overlay
:
true
,
scope
:
$scope
});
};
$scope
.
saveApi
=
function
()
{
var
apiNames
=
[];
if
(
$scope
.
gatewayApiDialog
.
type
===
'add'
)
{
apiNames
=
$scope
.
apis
.
map
(
function
(
item
,
index
,
array
)
{
return
item
[
"apiName"
];
}).
filter
(
function
(
item
,
index
,
array
)
{
return
array
.
indexOf
(
item
)
===
index
;
});
}
if
(
!
GatewayApiService
.
checkApiValid
(
$scope
.
currentApi
,
apiNames
))
{
return
;
}
if
(
$scope
.
gatewayApiDialog
.
type
===
'add'
)
{
addNewApi
(
$scope
.
currentApi
);
}
else
if
(
$scope
.
gatewayApiDialog
.
type
===
'edit'
)
{
saveApi
(
$scope
.
currentApi
,
true
);
}
};
function
addNewApi
(
api
)
{
GatewayApiService
.
newApi
(
api
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
getApis
();
gatewayApiDialog
.
close
();
}
else
{
alert
(
'新增自定义API失败!'
+
data
.
msg
);
}
});
};
function
saveApi
(
api
,
edit
)
{
GatewayApiService
.
saveApi
(
api
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
getApis
();
if
(
edit
)
{
gatewayApiDialog
.
close
();
}
else
{
confirmDialog
.
close
();
}
}
else
{
alert
(
'修改自定义API失败!'
+
data
.
msg
);
}
});
};
var
confirmDialog
;
$scope
.
deleteApi
=
function
(
api
)
{
$scope
.
currentApi
=
api
;
$scope
.
confirmDialog
=
{
title
:
'删除自定义API'
,
type
:
'delete_api'
,
attentionTitle
:
'请确认是否删除如下自定义API'
,
attention
:
'API名称: '
+
api
.
apiName
,
confirmBtnText
:
'删除'
,
};
confirmDialog
=
ngDialog
.
open
({
template
:
'/app/views/dialog/confirm-dialog.html'
,
scope
:
$scope
,
overlay
:
true
});
};
$scope
.
confirm
=
function
()
{
if
(
$scope
.
confirmDialog
.
type
==
'delete_api'
)
{
deleteApi
(
$scope
.
currentApi
);
}
else
{
console
.
error
(
'error'
);
}
};
function
deleteApi
(
api
)
{
GatewayApiService
.
deleteApi
(
api
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
getApis
();
confirmDialog
.
close
();
}
else
{
alert
(
'删除自定义API失败!'
+
data
.
msg
);
}
});
};
$scope
.
addNewMatchPattern
=
function
()
{
var
total
;
if
(
$scope
.
currentApi
.
predicateItems
==
null
)
{
$scope
.
currentApi
.
predicateItems
=
[];
total
=
0
;
}
else
{
total
=
$scope
.
currentApi
.
predicateItems
.
length
;
}
$scope
.
currentApi
.
predicateItems
.
splice
(
total
+
1
,
0
,
{
matchStrategy
:
0
,
pattern
:
''
});
};
$scope
.
removeMatchPattern
=
function
(
$index
)
{
if
(
$scope
.
currentApi
.
predicateItems
.
length
<=
1
)
{
// Should never happen since no remove button will display when only one predicateItem.
alert
(
'至少有一个匹配规则'
);
return
;
}
$scope
.
currentApi
.
predicateItems
.
splice
(
$index
,
1
);
};
queryAppMachines
();
function
queryAppMachines
()
{
MachineService
.
getAppMachines
(
$scope
.
app
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
// $scope.machines = data.data;
if
(
data
.
data
)
{
$scope
.
machines
=
[];
$scope
.
macsInputOptions
=
[];
data
.
data
.
forEach
(
function
(
item
)
{
if
(
item
.
healthy
)
{
$scope
.
macsInputOptions
.
push
({
text
:
item
.
ip
+
':'
+
item
.
port
,
value
:
item
.
ip
+
':'
+
item
.
port
});
}
});
}
if
(
$scope
.
macsInputOptions
.
length
>
0
)
{
$scope
.
macInputModel
=
$scope
.
macsInputOptions
[
0
].
value
;
}
}
else
{
$scope
.
macsInputOptions
=
[];
}
}
);
};
$scope
.
$watch
(
'macInputModel'
,
function
()
{
if
(
$scope
.
macInputModel
)
{
getApis
();
}
});
}]
);
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/gateway/flow_v2.js
0 → 100644
View file @
6d512971
var
app
=
angular
.
module
(
'sentinelDashboardApp'
);
app
.
controller
(
'GatewayFlowCtlV2'
,
[
'$scope'
,
'$stateParams'
,
'GatewayFlowServiceV2'
,
'GatewayApiServiceV2'
,
'ngDialog'
,
'MachineService'
,
function
(
$scope
,
$stateParams
,
GatewayFlowService
,
GatewayApiService
,
ngDialog
,
MachineService
)
{
$scope
.
app
=
$stateParams
.
app
;
$scope
.
rulesPageConfig
=
{
pageSize
:
10
,
currentPageIndex
:
1
,
totalPage
:
1
,
totalCount
:
0
,
};
$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
;
}
};
getMachineRules
();
function
getMachineRules
()
{
if
(
!
$scope
.
macInputModel
)
{
return
;
}
var
mac
=
$scope
.
macInputModel
.
split
(
':'
);
GatewayFlowService
.
queryRules
(
$scope
.
app
,
mac
[
0
],
mac
[
1
]).
success
(
function
(
data
)
{
console
.
log
(
data
);
if
(
data
.
code
==
0
&&
data
.
data
)
{
// rule
$scope
.
rules
=
data
.
data
.
flow
;
$scope
.
rulesPageConfig
.
totalCount
=
$scope
.
rules
.
length
;
//api
if
(
data
.
data
.
api
)
{
$scope
.
apiNames
=
[];
data
.
data
.
api
.
forEach
(
function
(
api
)
{
$scope
.
apiNames
.
push
(
api
[
"apiName"
]);
});
}
}
else
{
$scope
.
rules
=
[];
$scope
.
rulesPageConfig
.
totalCount
=
0
;
}
});
// function (data) {
// if (data.code == 0 && data.data) {
// $scope.rules = data.data;
// $scope.rulesPageConfig.totalCount = $scope.rules.length;
// } else {
// $scope.rules = [];
// $scope.rulesPageConfig.totalCount = 0;
// }
// });
};
$scope
.
getMachineRules
=
getMachineRules
;
// getApiNames();
// function getApiNames() {
// if (!$scope.macInputModel) {
// return;
// }
//
// var mac = $scope.macInputModel.split(':');
// GatewayApiServiceV2.queryApis($scope.app, mac[0], mac[1]).success(
// function (data) {
// if (data.code == 0 && data.data) {
// $scope.apiNames = [];
//
// data.data.forEach(function (api) {
// $scope.apiNames.push(api["apiName"]);
// });
// }
// });
// }
$scope
.
intervalUnits
=
[{
val
:
0
,
desc
:
'秒'
},
{
val
:
1
,
desc
:
'分'
},
{
val
:
2
,
desc
:
'时'
},
{
val
:
3
,
desc
:
'天'
}];
var
gatewayFlowRuleDialog
;
$scope
.
editRule
=
function
(
rule
)
{
$scope
.
currentRule
=
angular
.
copy
(
rule
);
$scope
.
gatewayFlowRuleDialog
=
{
title
:
'编辑网关流控规则'
,
type
:
'edit'
,
confirmBtnText
:
'保存'
};
gatewayFlowRuleDialog
=
ngDialog
.
open
({
template
:
'/app/views/dialog/gateway/flow-rule-dialog.html'
,
width
:
780
,
overlay
:
true
,
scope
:
$scope
});
};
$scope
.
addNewRule
=
function
()
{
var
mac
=
$scope
.
macInputModel
.
split
(
':'
);
$scope
.
currentRule
=
{
grade
:
1
,
app
:
$scope
.
app
,
ip
:
mac
[
0
],
port
:
mac
[
1
],
resourceMode
:
0
,
interval
:
1
,
intervalUnit
:
0
,
controlBehavior
:
0
,
burst
:
0
,
maxQueueingTimeoutMs
:
0
};
$scope
.
gatewayFlowRuleDialog
=
{
title
:
'新增网关流控规则'
,
type
:
'add'
,
confirmBtnText
:
'新增'
};
gatewayFlowRuleDialog
=
ngDialog
.
open
({
template
:
'/app/views/dialog/gateway/flow-rule-dialog.html'
,
width
:
780
,
overlay
:
true
,
scope
:
$scope
});
};
$scope
.
saveRule
=
function
()
{
if
(
!
GatewayFlowService
.
checkRuleValid
(
$scope
.
currentRule
))
{
return
;
}
if
(
$scope
.
gatewayFlowRuleDialog
.
type
===
'add'
)
{
addNewRule
(
$scope
.
currentRule
);
}
else
if
(
$scope
.
gatewayFlowRuleDialog
.
type
===
'edit'
)
{
saveRule
(
$scope
.
currentRule
,
true
);
}
};
$scope
.
useRouteID
=
function
()
{
$scope
.
currentRule
.
resource
=
''
;
};
$scope
.
useCustormAPI
=
function
()
{
$scope
.
currentRule
.
resource
=
''
;
};
$scope
.
useParamItem
=
function
()
{
$scope
.
currentRule
.
paramItem
=
{
parseStrategy
:
0
,
matchStrategy
:
0
};
};
$scope
.
notUseParamItem
=
function
()
{
$scope
.
currentRule
.
paramItem
=
null
;
};
$scope
.
useParamItemVal
=
function
()
{
$scope
.
currentRule
.
paramItem
.
pattern
=
""
;
$scope
.
currentRule
.
paramItem
.
matchStrategy
=
0
;
};
$scope
.
notUseParamItemVal
=
function
()
{
$scope
.
currentRule
.
paramItem
.
pattern
=
null
;
$scope
.
currentRule
.
paramItem
.
matchStrategy
=
null
;
};
function
addNewRule
(
rule
)
{
GatewayFlowService
.
newRule
(
rule
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
getMachineRules
();
gatewayFlowRuleDialog
.
close
();
}
else
{
alert
(
'新增网关流控规则失败!'
+
data
.
msg
);
}
});
};
function
saveRule
(
rule
,
edit
)
{
GatewayFlowService
.
saveRule
(
rule
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
getMachineRules
();
if
(
edit
)
{
gatewayFlowRuleDialog
.
close
();
}
else
{
confirmDialog
.
close
();
}
}
else
{
alert
(
'修改网关流控规则失败!'
+
data
.
msg
);
}
});
};
var
confirmDialog
;
$scope
.
deleteRule
=
function
(
rule
)
{
$scope
.
currentRule
=
rule
;
$scope
.
confirmDialog
=
{
title
:
'删除网关流控规则'
,
type
:
'delete_rule'
,
attentionTitle
:
'请确认是否删除如下规则'
,
attention
:
'API名称: '
+
rule
.
resource
+
', '
+
(
rule
.
grade
==
1
?
'QPS阈值'
:
'线程数'
)
+
': '
+
rule
.
count
,
confirmBtnText
:
'删除'
,
};
confirmDialog
=
ngDialog
.
open
({
template
:
'/app/views/dialog/confirm-dialog.html'
,
scope
:
$scope
,
overlay
:
true
});
};
$scope
.
confirm
=
function
()
{
if
(
$scope
.
confirmDialog
.
type
==
'delete_rule'
)
{
deleteRule
(
$scope
.
currentRule
);
}
else
{
console
.
error
(
'error'
);
}
};
function
deleteRule
(
rule
)
{
GatewayFlowService
.
deleteRule
(
rule
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
getMachineRules
();
confirmDialog
.
close
();
}
else
{
alert
(
'删除网关流控规则失败!'
+
data
.
msg
);
}
});
};
queryAppMachines
();
function
queryAppMachines
()
{
MachineService
.
getAppMachines
(
$scope
.
app
).
success
(
function
(
data
)
{
if
(
data
.
code
==
0
)
{
if
(
data
.
data
)
{
$scope
.
machines
=
[];
$scope
.
macsInputOptions
=
[];
data
.
data
.
forEach
(
function
(
item
)
{
if
(
item
.
healthy
)
{
$scope
.
macsInputOptions
.
push
({
text
:
item
.
ip
+
':'
+
item
.
port
,
value
:
item
.
ip
+
':'
+
item
.
port
});
}
});
}
if
(
$scope
.
macsInputOptions
.
length
>
0
)
{
$scope
.
macInputModel
=
$scope
.
macsInputOptions
[
0
].
value
;
}
}
else
{
$scope
.
macsInputOptions
=
[];
}
}
);
};
$scope
.
$watch
(
'macInputModel'
,
function
()
{
if
(
$scope
.
macInputModel
)
{
getMachineRules
();
// getApiNames();
}
});
}]
);
sentinel-dashboard/src/main/webapp/resources/app/scripts/directives/sidebar/sidebar.html
View file @
6d512971
...
@@ -44,13 +44,22 @@
...
@@ -44,13 +44,22 @@
<!--<a ui-sref="dashboard.flow({app: entry.app})">-->
<!--<a ui-sref="dashboard.flow({app: entry.app})">-->
<!--<i class="glyphicon glyphicon-filter"></i> 流控规则 V1</a>-->
<!--<i class="glyphicon glyphicon-filter"></i> 流控规则 V1</a>-->
<!--</li>-->
<!--</li>-->
<!-- 网关 -->
<!-- <li ui-sref-active="active" ng-if="entry.isGateway">-->
<!-- <a ui-sref="dashboard.gatewayApi({app: entry.app})">-->
<!-- <i class="glyphicon glyphicon-tags"></i> API 管理</a>-->
<!-- </li>-->
<!-- <li ui-sref-active="active" ng-if="entry.isGateway">-->
<!-- <a ui-sref="dashboard.gatewayFlow({app: entry.app})">-->
<!-- <i class="glyphicon glyphicon-filter"></i> 流控规则</a>-->
<!-- </li>-->
<!-- 网关v2 -->
<li
ui-sref-active=
"active"
ng-if=
"entry.isGateway"
>
<li
ui-sref-active=
"active"
ng-if=
"entry.isGateway"
>
<a
ui-sref=
"dashboard.gatewayApi({app: entry.app})"
>
<a
ui-sref=
"dashboard.gatewayApi
V2
({app: entry.app})"
>
<i
class=
"glyphicon glyphicon-tags"
></i>
API 管理
</a>
<i
class=
"glyphicon glyphicon-tags"
></i>
API 管理
</a>
</li>
</li>
<li
ui-sref-active=
"active"
ng-if=
"entry.isGateway"
>
<li
ui-sref-active=
"active"
ng-if=
"entry.isGateway"
>
<a
ui-sref=
"dashboard.gatewayFlow({app: entry.app})"
>
<a
ui-sref=
"dashboard.gatewayFlow
V2
({app: entry.app})"
>
<i
class=
"glyphicon glyphicon-filter"
></i>
流控规则
</a>
<i
class=
"glyphicon glyphicon-filter"
></i>
流控规则
</a>
</li>
</li>
...
...
sentinel-dashboard/src/main/webapp/resources/app/scripts/services/gateway/api_service_v2.js
0 → 100644
View file @
6d512971
var
app
=
angular
.
module
(
'sentinelDashboardApp'
);
app
.
service
(
'GatewayApiServiceV2'
,
[
'$http'
,
function
(
$http
)
{
this
.
queryApis
=
function
(
app
,
ip
,
port
)
{
var
param
=
{
app
:
app
,
ip
:
ip
,
port
:
port
};
return
$http
({
url
:
'/v2/gateway/api/list.json'
,
params
:
param
,
method
:
'GET'
});
};
this
.
newApi
=
function
(
api
)
{
return
$http
({
url
:
'/v2/gateway/api/new.json'
,
data
:
api
,
method
:
'POST'
});
};
this
.
saveApi
=
function
(
api
)
{
return
$http
({
url
:
'/v2/gateway/api/save.json'
,
data
:
api
,
method
:
'POST'
});
};
this
.
deleteApi
=
function
(
api
)
{
var
param
=
{
id
:
api
.
id
,
app
:
api
.
app
};
return
$http
({
url
:
'/v2/gateway/api/delete.json'
,
params
:
param
,
method
:
'POST'
});
};
this
.
checkApiValid
=
function
(
api
,
apiNames
)
{
if
(
api
.
apiName
===
undefined
||
api
.
apiName
===
''
)
{
alert
(
'API名称不能为空'
);
return
false
;
}
if
(
api
.
predicateItems
==
null
||
api
.
predicateItems
.
length
===
0
)
{
// Should never happen since no remove button will display when only one predicateItem.
alert
(
'至少有一个匹配规则'
);
return
false
;
}
for
(
var
i
=
0
;
i
<
api
.
predicateItems
.
length
;
i
++
)
{
var
predicateItem
=
api
.
predicateItems
[
i
];
var
pattern
=
predicateItem
.
pattern
;
if
(
pattern
===
undefined
||
pattern
===
''
)
{
alert
(
'匹配串不能为空,请检查'
);
return
false
;
}
}
if
(
apiNames
.
indexOf
(
api
.
apiName
)
!==
-
1
)
{
alert
(
'API名称('
+
api
.
apiName
+
')已存在'
);
return
false
;
}
return
true
;
};
}]);
sentinel-dashboard/src/main/webapp/resources/app/scripts/services/gateway/flow_service_v2.js
0 → 100644
View file @
6d512971
var
app
=
angular
.
module
(
'sentinelDashboardApp'
);
app
.
service
(
'GatewayFlowServiceV2'
,
[
'$http'
,
function
(
$http
)
{
this
.
queryRules
=
function
(
app
,
ip
,
port
)
{
var
param
=
{
app
:
app
,
ip
:
ip
,
port
:
port
};
return
$http
({
url
:
'/v2/gateway/flow/list.json'
,
params
:
param
,
method
:
'GET'
});
};
this
.
newRule
=
function
(
rule
)
{
return
$http
({
url
:
'/v2/gateway/flow/new.json'
,
data
:
rule
,
method
:
'POST'
});
};
this
.
saveRule
=
function
(
rule
)
{
return
$http
({
url
:
'/v2/gateway/flow/save.json'
,
data
:
rule
,
method
:
'POST'
});
};
this
.
deleteRule
=
function
(
rule
)
{
var
param
=
{
id
:
rule
.
id
,
app
:
rule
.
app
};
return
$http
({
url
:
'/v2/gateway/flow/delete.json'
,
params
:
param
,
method
:
'POST'
});
};
this
.
checkRuleValid
=
function
(
rule
)
{
if
(
rule
.
resource
===
undefined
||
rule
.
resource
===
''
)
{
alert
(
'API名称不能为空'
);
return
false
;
}
if
(
rule
.
paramItem
!=
null
)
{
if
(
rule
.
paramItem
.
parseStrategy
==
2
||
rule
.
paramItem
.
parseStrategy
==
3
||
rule
.
paramItem
.
parseStrategy
==
4
)
{
if
(
rule
.
paramItem
.
fieldName
===
undefined
||
rule
.
paramItem
.
fieldName
===
''
)
{
alert
(
'当参数属性为Header、URL参数、Cookie时,参数名称不能为空'
);
return
false
;
}
if
(
rule
.
paramItem
.
pattern
===
''
)
{
alert
(
'匹配串不能为空'
);
return
false
;
}
}
}
if
(
rule
.
count
===
undefined
||
rule
.
count
<
0
)
{
alert
((
rule
.
grade
===
1
?
'QPS阈值'
:
'线程数'
)
+
'必须大于等于 0'
);
return
false
;
}
return
true
;
};
}]);
sentinel-dashboard/src/main/webapp/resources/app/views/gateway/api_v2.html
0 → 100644
View file @
6d512971
<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-outline-primary"
style=
"float: right; margin-right: 10px;"
ng-disabled=
"!macInputModel"
ng-click=
"addNewApi()"
>
<i
class=
"fa fa-plus"
></i>
新增 API 分组
</button>
<a
class=
"btn btn-default-inverse"
style=
"float: right; margin-right: 10px;"
ui-sref=
"dashboard.gatewayApi({app: app})"
>
回到单机页面
</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;"
>
API 分组管理
</span>
<button
class=
"btn btn-primary"
style=
"float: right; margin-right: 10px; height: 30px;font-size: 12px;"
ng-click=
"getApis()"
>
刷新
</button>
<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>
</div>
</div>
<!--.tools-header -->
<div
class=
"card-body"
style=
"padding: 0px 0px;"
>
<table
class=
"table"
style=
"border-left: none; border-right:none;margin-top: 10px;"
>
<thead>
<tr
style=
"background: #F3F5F7;"
>
<td>
API 名称
</td>
<td>
匹配模式
</td>
<td>
匹配串
</td>
<td>
操作
</td>
</tr>
</thead>
<tbody>
<tr
dir-paginate=
"api in apis | filter: searchKey | itemsPerPage: apisPageConfig.pageSize"
current-page=
"apisPageConfig.currentPageIndex"
pagination-id=
"entriesPagination"
>
<td
ng-if=
"api.firstFlag==0"
rowspan=
"{{api.itemSize}}"
style=
"vertical-align: middle;"
>
{{api.apiName}}
</td>
<td>
<span
ng-if=
"api.matchStrategy == 0"
>
精确
</span>
<span
ng-if=
"api.matchStrategy == 1"
>
前缀
</span>
<span
ng-if=
"api.matchStrategy == 2"
>
正则
</span>
</td>
<td>
{{api.pattern}}
</td>
<td
ng-if=
"api.firstFlag==0"
rowspan=
"{{api.itemSize}}"
style=
"vertical-align: middle;"
>
<button
class=
"btn btn-xs btn-outline-primary"
type=
"button"
ng-click=
"editApi(api)"
style=
"font-size: 12px; height:25px;"
>
编辑
</button>
<button
class=
"btn btn-xs btn-outline-danger"
type=
"button"
ng-click=
"deleteApi(api)"
style=
"font-size: 12px; height:25px;"
>
删除
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- .card-body -->
<div
class=
"pagination-footer"
>
<dir-pagination-controls
boundary-links=
"true"
template-url=
"app/views/pagination.tpl.html"
pagination-id=
"entriesPagination"
on-page-change=
""
>
</dir-pagination-controls>
<div
class=
"tools"
style=
""
>
<span>
共 {{apisPageConfig.totalCount}} 条记录,
</span>
<span>
每页
<input
class=
"form-control"
ng-model=
"apisPageConfig.pageSize"
>
条记录
</span>
<!--<span>第 {{apisPageConfig.currentPageIndex}} / {{apisPageConfig.totalPage}} 页</span>-->
</div>
<!-- .tools -->
</div>
<!-- pagination-footer -->
</div>
<!-- .card -->
</div>
<!-- .col-md-12 -->
</div>
<!-- -->
</div>
<!-- .container-fluid -->
sentinel-dashboard/src/main/webapp/resources/app/views/gateway/flow_v2.html
0 → 100644
View file @
6d512971
<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-outline-primary"
style=
"float: right; margin-right: 10px;"
ng-disabled=
"!macInputModel"
ng-click=
"addNewRule()"
>
<i
class=
"fa fa-plus"
></i>
新增网关流控规则
</button>
<a
class=
"btn btn-default-inverse"
style=
"float: right; margin-right: 10px;"
ui-sref=
"dashboard.gatewayFlow({app: app})"
>
回到单机页面
</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;"
>
网关流控规则
</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"
>
<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>
</div>
</div>
<!--.tools-header -->
<div
class=
"card-body"
style=
"padding: 0px 0px;"
>
<table
class=
"table"
style=
"border-left: none; border-right:none;margin-top: 10px;"
>
<thead>
<tr
style=
"background: #F3F5F7;"
>
<td>
API 名称
</td>
<td>
API 类型
</td>
<td>
阈值类型
</td>
<td>
单机阈值
</td>
<td>
操作
</td>
</tr>
</thead>
<tbody>
<tr
dir-paginate=
"rule in rules | filter: searchKey | itemsPerPage: rulesPageConfig.pageSize "
current-page=
"rulesPageConfig.currentPageIndex"
pagination-id=
"entriesPagination"
>
<td>
{{rule.resource}}
</td>
<td>
<span
ng-if=
"rule.resourceMode == 0"
>
Route ID
</span>
<span
ng-if=
"rule.resourceMode == 1"
>
API 分组
</span>
</td>
<td>
<span
ng-if=
"rule.grade == 1"
>
QPS
</span>
<span
ng-if=
"rule.grade == 0"
>
线程数
</span>
</td>
<td>
{{rule.count}}
</td>
<td>
<button
class=
"btn btn-xs btn-outline-primary"
type=
"button"
ng-click=
"editRule(rule)"
style=
"font-size: 12px; height:25px;"
>
编辑
</button>
<button
class=
"btn btn-xs btn-outline-danger"
type=
"button"
ng-click=
"deleteRule(rule)"
style=
"font-size: 12px; height:25px;"
>
删除
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- .card-body -->
<div
class=
"pagination-footer"
>
<dir-pagination-controls
boundary-links=
"true"
template-url=
"app/views/pagination.tpl.html"
pagination-id=
"entriesPagination"
on-page-change=
""
>
</dir-pagination-controls>
<div
class=
"tools"
style=
""
>
<span>
共 {{rulesPageConfig.totalCount}} 条记录,
</span>
<span>
每页
<input
class=
"form-control"
ng-model=
"rulesPageConfig.pageSize"
>
条记录
</span>
<!--<span>第 {{apisPageConfig.currentPageIndex}} / {{apisPageConfig.totalPage}} 页</span>-->
</div>
<!-- .tools -->
</div>
<!-- pagination-footer -->
</div>
<!-- .card -->
</div>
<!-- .col-md-12 -->
</div>
<!-- -->
</div>
<!-- .container-fluid -->
sentinel-dashboard/src/main/webapp/resources/app/views/metric.html
View file @
6d512971
...
@@ -22,10 +22,10 @@
...
@@ -22,10 +22,10 @@
<input
class=
"form-control witdh-200"
placeholder=
"关键字"
ng-model=
"serviceQuery"
ng-change=
"searchService()"
style=
"margin-right: 20px;"
>
<input
class=
"form-control witdh-200"
placeholder=
"关键字"
ng-model=
"serviceQuery"
ng-change=
"searchService()"
style=
"margin-right: 20px;"
>
</div>
</div>
<div
class=
"input-append date"
id=
"datetimepicker"
data-date=
"12-02-2012"
data-date-format=
"dd-mm-yyyy"
>
<!-- <div class="input-append date" id="datetimepicker" data-date="12-02-2012" data-date-format="dd-mm-yyyy">--
>
<input
size=
"16"
type=
"text"
value=
"12-02-2012"
readonly
>
<!-- <input size="16" type="text" value="12-02-2012" readonly>--
>
<span
class=
"add-on"
><i
class=
"icon-th"
></i></span
>
<!-- <span class="add-on"><i class="icon-th"></i></span>--
>
</div
>
<!-- </div>--
>
<!--.tools-header -->
<!--.tools-header -->
<!--<div id="g2container"></div>-->
<!--<div id="g2container"></div>-->
<div
class=
"card-body"
>
<div
class=
"card-body"
>
...
...
sentinel-dashboard/src/main/webapp/resources/gulpfile.js
View file @
6d512971
...
@@ -59,7 +59,9 @@ const JS_APP = [
...
@@ -59,7 +59,9 @@ const JS_APP = [
'app/scripts/services/authority_service.js'
,
'app/scripts/services/authority_service.js'
,
'app/scripts/services/cluster_state_service.js'
,
'app/scripts/services/cluster_state_service.js'
,
'app/scripts/services/gateway/api_service.js'
,
'app/scripts/services/gateway/api_service.js'
,
'app/scripts/services/gateway/api_service_v2.js'
,
'app/scripts/services/gateway/flow_service.js'
,
'app/scripts/services/gateway/flow_service.js'
,
'app/scripts/services/gateway/flow_service_v2.js'
,
];
];
gulp
.
task
(
'lib'
,
function
()
{
gulp
.
task
(
'lib'
,
function
()
{
...
...
sentinel-dashboard/src/main/webapp/resources/index.htm
View file @
6d512971
...
@@ -19,7 +19,9 @@
...
@@ -19,7 +19,9 @@
</div>
</div>
<script
src=
"./lib/js/jquery.min.js"
></script>
<script
src=
"./lib/js/jquery.min.js"
></script>
<script
src=
"./lib/js/bootstrap.min.js"
></script>
<script
src=
"./lib/js/bootstrap.min.js"
></script>
<script
src=
"./lib/js/angular.min.js"
></script>
<!-- <script src="./lib/js/angular.min.js"></script>-->
<script
src=
"http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"
></script>
<script
src=
"./lib/js/g2.min.js"
></script>
<script
src=
"./lib/js/g2.min.js"
></script>
<script
src=
"./dist/js/app.vendor.js"
></script>
<script
src=
"./dist/js/app.vendor.js"
></script>
...
...
sentinel-demo-springboot-nacos/pom.xml
View file @
6d512971
...
@@ -17,10 +17,10 @@
...
@@ -17,10 +17,10 @@
<dependencies>
<dependencies>
<dependency
>
<!-- <dependency>--
>
<groupId>
com.alibaba.csp
</groupId
>
<!-- <groupId>com.alibaba.csp</groupId>--
>
<artifactId>
sentinel-core
</artifactId
>
<!-- <artifactId>sentinel-core</artifactId>--
>
</dependency
>
<!-- </dependency>--
>
<dependency>
<dependency>
<groupId>
com.alibaba.csp
</groupId>
<groupId>
com.alibaba.csp
</groupId>
<artifactId>
sentinel-transport-simple-http
</artifactId>
<artifactId>
sentinel-transport-simple-http
</artifactId>
...
@@ -41,6 +41,70 @@
...
@@ -41,6 +41,70 @@
</dependency>
</dependency>
</dependencies>
</dependencies>
<!-- <dependencies>-->
<!-- <!–nacos config–>-->
<!-- <!–<dependency>–>-->
<!-- <!–<groupId>com.alibaba.cloud</groupId>–>-->
<!-- <!–<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>–>-->
<!-- <!–</dependency>–>-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>-->
<!-- </dependency>-->
<!-- <!–用nacos 和 sentinel 就用下面三个–>-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>-->
<!-- </dependency>-->
<!-- <!–做持久化用–>-->
<!-- <dependency>-->
<!-- <groupId>com.alibaba.csp</groupId>-->
<!-- <artifactId>sentinel-datasource-nacos</artifactId>-->
<!-- </dependency>-->
<!-- <!–<dependency>–>-->
<!-- <!–<groupId>org.springframework.cloud</groupId>–>-->
<!-- <!–<artifactId>spring-cloud-starter-openfeign</artifactId>–>-->
<!-- <!–</dependency>–>-->
<!-- <!–引入自己api–>-->
<!--<!– <dependency>–>-->
<!--<!– <groupId>cn.dongfang.clouddemo</groupId>–>-->
<!--<!– <artifactId>apicommons</artifactId>–>-->
<!--<!– <version>${project.version}</version>–>-->
<!--<!– </dependency>–>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-web</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-actuator</artifactId>-->
<!-- </dependency>-->
<!-- <!–热部署–>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-devtools</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- <optional>true</optional>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.projectlombok</groupId>-->
<!-- <artifactId>lombok</artifactId>-->
<!-- <optional>true</optional>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- </dependencies>-->
...
...
sentinel-demo-springboot-nacos/sentinel-demo-springboot-nacos.iml
View file @
6d512971
...
@@ -20,7 +20,6 @@
...
@@ -20,7 +20,6 @@
</content>
</content>
<orderEntry
type=
"jdk"
jdkName=
"1.8"
jdkType=
"JavaSDK"
/>
<orderEntry
type=
"jdk"
jdkName=
"1.8"
jdkType=
"JavaSDK"
/>
<orderEntry
type=
"sourceFolder"
forTests=
"false"
/>
<orderEntry
type=
"sourceFolder"
forTests=
"false"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-core:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-transport-simple-http:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-transport-simple-http:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-transport-common:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-transport-common:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba:fastjson:1.2.62"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba:fastjson:1.2.62"
level=
"project"
/>
...
@@ -47,6 +46,7 @@
...
@@ -47,6 +46,7 @@
<orderEntry
type=
"library"
name=
"Maven: org.springframework.boot:spring-boot-starter-aop:2.1.6.RELEASE"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.springframework.boot:spring-boot-starter-aop:2.1.6.RELEASE"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-datasource-nacos:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-datasource-nacos:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-datasource-extension:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-datasource-extension:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.csp:sentinel-core:1.7.1"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.nacos:nacos-client:1.1.4"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.nacos:nacos-client:1.1.4"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.nacos:nacos-common:1.1.4"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: com.alibaba.nacos:nacos-common:1.1.4"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.slf4j:slf4j-api:1.7.7"
level=
"project"
/>
<orderEntry
type=
"library"
name=
"Maven: org.slf4j:slf4j-api:1.7.7"
level=
"project"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment