Dashboard部署方案
方式1:Jar包直接部署
# 1. 下载Dashboard
wget https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
# 2. 启动Dashboard
java -Dserver.port=8080 \
-Dcsp.sentinel.dashboard.server=localhost:8080 \
-Dproject.name=sentinel-dashboard \
-jar sentinel-dashboard-1.8.6.jar
# 3. 访问控制台
# http://localhost:8080
# 默认账号/密码:sentinel/sentinel
方式2:Docker部署
FROM openjdk:8-jre-slim
# 下载Dashboard
ADD https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar /app.jar
# 暴露端口
EXPOSE 8080
# 启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
# 构建镜像
docker build -t sentinel-dashboard:1.8.6 .
# 运行容器
docker run -d \
--name sentinel-dashboard \
-p 8080:8080 \
sentinel-dashboard:1.8.6
方式3:Kubernetes部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: sentinel-dashboard
spec:
replicas: 2
selector:
matchLabels:
app: sentinel-dashboard
template:
metadata:
labels:
app: sentinel-dashboard
spec:
containers:
- name: dashboard
image: sentinel-dashboard:1.8.6
ports:
- containerPort: 8080
env:
- name: JAVA_OPTS
value: "-Xms512m -Xmx512m"
---
apiVersion: v1
kind: Service
metadata:
name: sentinel-dashboard
spec:
selector:
app: sentinel-dashboard
ports:
- port: 8080
targetPort: 8080
type: LoadBalancer
生产配置
application.properties
# 服务端口
server.port=8080
# Session超时时间(30分钟)
server.servlet.session.timeout=30m
# 认证配置
auth.enabled=true
auth.username=admin
auth.password=your_password
# 数据源配置(持久化到Nacos)
nacos.server-addr=localhost:8848
nacos.namespace=production
nacos.group-id=SENTINEL_GROUP
# 规则推送模式
sentinel.rule.push.mode=nacos
JVM参数
java -Xms1g -Xmx1g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-Xloggc:logs/gc.log \
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-jar sentinel-dashboard.jar
改造Dashboard
持久化到Nacos
1. 修改pom.xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
2. 配置Nacos
@Configuration
public class NacosConfig {
@Bean
public ConfigService nacosConfigService() throws Exception {
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, "localhost:8848");
properties.put(PropertyKeyConst.NAMESPACE, "production");
return ConfigFactory.createConfigService(properties);
}
}
3. 规则发布器
@Component
public class FlowRuleNacosPublisher implements DynamicRulePublisher<List<FlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Override
public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
String dataId = app + "-flow-rules";
configService.publishConfig(
dataId,
"SENTINEL_GROUP",
JSON.toJSONString(rules),
ConfigType.JSON.getType()
);
}
}
@Component
public class FlowRuleNacosProvider implements DynamicRuleProvider<List<FlowRuleEntity>> {
@Autowired
private ConfigService configService;
@Override
public List<FlowRuleEntity> getRules(String appName) throws Exception {
String dataId = appName + "-flow-rules";
String rules = configService.getConfig(dataId, "SENTINEL_GROUP", 3000);
return StringUtil.isEmpty(rules) ? new ArrayList<>() :
JSON.parseArray(rules, FlowRuleEntity.class);
}
}
4. Controller改造
@RestController
@RequestMapping("/v1/flow")
public class FlowControllerV2 {
@Autowired
private DynamicRuleProvider<List<FlowRuleEntity>> ruleProvider;
@Autowired
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher;
@GetMapping("/rules")
public Result<List<FlowRuleEntity>> apiQueryRules(@RequestParam String app) {
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(app);
return Result.ofSuccess(rules);
} catch (Exception e) {
return Result.ofFail(-1, e.getMessage());
}
}
@PostMapping("/rule")
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) {
try {
List<FlowRuleEntity> rules = ruleProvider.getRules(entity.getApp());
rules.add(entity);
rulePublisher.publish(entity.getApp(), rules);
return Result.ofSuccess(entity);
} catch (Exception e) {
return Result.ofFail(-1, e.getMessage());
}
}
}
权限控制
自定义用户认证
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("{noop}admin123").roles("ADMIN")
.and()
.withUser("user").password("{noop}user123").roles("USER");
}
}
基于角色的权限控制
@RestController
@RequestMapping("/v1/flow")
public class FlowController {
@GetMapping("/rules")
@PreAuthorize("hasAnyRole('ADMIN', 'USER')")
public Result apiQueryRules(@RequestParam String app) {
// ...
}
@PostMapping("/rule")
@PreAuthorize("hasRole('ADMIN')")
public Result apiAddRule(@RequestBody FlowRuleEntity entity) {
// ...
}
@DeleteMapping("/rule/{id}")
@PreAuthorize("hasRole('ADMIN')")
public Result apiDeleteRule(@PathVariable Long id) {
// ...
}
}
监控告警
Prometheus集成
@Configuration
public class PrometheusConfig {
@Bean
MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("application", "sentinel-dashboard");
}
}
Grafana Dashboard
{
"dashboard": {
"title": "Sentinel Dashboard Monitoring",
"panels": [
{
"title": "QPS",
"targets": [
{
"expr": "rate(sentinel_pass_qps[1m])"
}
]
},
{
"title": "Block Rate",
"targets": [
{
"expr": "rate(sentinel_block_qps[1m]) / rate(sentinel_pass_qps[1m])"
}
]
}
]
}
}
高可用部署
Nginx负载均衡
upstream sentinel_dashboard {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
server {
listen 80;
server_name dashboard.example.com;
location / {
proxy_pass http://sentinel_dashboard;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Session共享
# Redis共享Session
spring.session.store-type=redis
spring.redis.host=localhost
spring.redis.port=6379
运维脚本
启动脚本
#!/bin/bash
# start.sh
JAVA_OPTS="-Xms1g -Xmx1g -XX:+UseG1GC"
APP_NAME="sentinel-dashboard"
APP_JAR="sentinel-dashboard.jar"
nohup java $JAVA_OPTS -jar $APP_JAR > logs/dashboard.log 2>&1 &
echo $! > dashboard.pid
echo "Dashboard started"
停止脚本
#!/bin/bash
# stop.sh
if [ -f dashboard.pid ]; then
kill $(cat dashboard.pid)
rm -f dashboard.pid
echo "Dashboard stopped"
else
echo "PID file not found"
fi
健康检查
#!/bin/bash
# health_check.sh
URL="http://localhost:8080/actuator/health"
if curl -f $URL > /dev/null 2>&1; then
echo "Dashboard is healthy"
exit 0
else
echo "Dashboard is down"
exit 1
fi
总结
Dashboard生产部署要点:
- 部署方式:Jar包、Docker、Kubernetes
- 持久化:改造Dashboard支持Nacos
- 权限控制:用户认证、角色权限
- 高可用:多实例部署、Nginx负载均衡
- 监控告警:Prometheus + Grafana
最佳实践:
- 使用Nacos持久化规则
- 配置权限控制保护Dashboard
- 部署多实例保证高可用
- 集成监控系统实时告警