1. 服务器配置管理概述

服务器配置管理是现代运维体系的核心组成部分,通过Java实现配置管理、自动化部署、服务监控等功能,可以大大提高运维效率。本文将详细介绍基于Java的服务器配置管理实现,包括配置管理、环境部署、服务监控、自动化运维的完整解决方案。

1.1 核心功能

  1. 配置管理: 统一管理服务器配置文件
  2. 环境部署: 自动化部署应用到不同环境
  3. 服务监控: 实时监控服务器状态和服务健康度
  4. 自动化运维: 自动化的运维操作和故障处理
  5. 版本控制: 配置版本管理和回滚机制

1.2 技术架构

1
2
3
配置中心 → 环境管理 → 部署引擎 → 服务监控 → 告警通知
↓ ↓ ↓ ↓ ↓
配置存储 → 环境隔离 → 自动化部署 → 健康检查 → 故障处理

2. Maven依赖配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!-- pom.xml -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.server</groupId>
<artifactId>server-config-demo</artifactId>
<version>1.0.0</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>

<properties>
<java.version>11</java.version>
</properties>

<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Spring Boot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- Spring Boot Configuration Processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<!-- SSH连接 -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>

<!-- 文件操作 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

<!-- YAML处理 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>

<!-- JSON处理 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

3. 配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# application.yml
server:
port: 8080

spring:
application:
name: server-config-demo

# Redis配置
redis:
host: localhost
port: 6379
database: 0

# 数据库配置
datasource:
url: jdbc:mysql://localhost:3306/server_config?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: update
show-sql: true

# 服务器配置管理
server-config:
# 配置存储路径
config-path: /opt/server-configs
# 备份路径
backup-path: /opt/config-backups
# 环境配置
environments:
- name: dev
servers:
- host: dev-server1
port: 22
username: root
- host: dev-server2
port: 22
username: root
- name: test
servers:
- host: test-server1
port: 22
username: root
- host: test-server2
port: 22
username: root
- name: prod
servers:
- host: prod-server1
port: 22
username: root
- host: prod-server2
port: 22
username: root

# 部署配置
deployment:
# 部署超时时间(秒)
timeout: 300
# 重试次数
retry-count: 3
# 健康检查间隔(秒)
health-check-interval: 30
# 健康检查超时(秒)
health-check-timeout: 10

# 监控配置
monitoring:
# 监控间隔(秒)
interval: 60
# 告警阈值
thresholds:
cpu: 80
memory: 85
disk: 90
# 告警通知
notifications:
email:
enabled: true
recipients:
- admin@example.com
webhook:
enabled: true
url: http://monitoring.example.com/webhook

# 监控配置
management:
endpoints:
web:
exposure:
include: "*"
metrics:
export:
prometheus:
enabled: true

4. 服务器实体定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package com.server.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.List;

/**
* 服务器实体
* @author Java实战
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "server", indexes = {
@Index(name = "idx_server_host", columnList = "host"),
@Index(name = "idx_server_env", columnList = "environment"),
@Index(name = "idx_server_status", columnList = "status")
})
public class Server {

/**
* 主键ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

/**
* 服务器主机名
*/
@Column(nullable = false, length = 100)
private String host;

/**
* 服务器IP地址
*/
@Column(length = 50)
private String ipAddress;

/**
* SSH端口
*/
@Column(nullable = false)
private Integer port;

/**
* SSH用户名
*/
@Column(nullable = false, length = 50)
private String username;

/**
* SSH密码(加密存储)
*/
@Column(length = 200)
private String password;

/**
* SSH私钥路径
*/
@Column(length = 200)
private String privateKeyPath;

/**
* 环境名称
*/
@Column(nullable = false, length = 50)
private String environment;

/**
* 服务器状态:ONLINE-在线, OFFLINE-离线, MAINTENANCE-维护中
*/
@Column(nullable = false, length = 20)
private String status;

/**
* 服务器描述
*/
@Column(length = 500)
private String description;

/**
* 操作系统
*/
@Column(length = 100)
private String os;

/**
* CPU核心数
*/
private Integer cpuCores;

/**
* 内存大小(GB)
*/
private Integer memorySize;

/**
* 磁盘大小(GB)
*/
private Integer diskSize;

/**
* 创建时间
*/
@Column(nullable = false)
private LocalDateTime createTime;

/**
* 更新时间
*/
private LocalDateTime updateTime;

/**
* 最后检查时间
*/
private LocalDateTime lastCheckTime;

/**
* 服务器配置列表(一对多关系)
*/
@OneToMany(mappedBy = "server", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<ServerConfig> configs;
}

5. 配置管理服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
package com.server.service;

import com.server.entity.Server;
import com.server.entity.ServerConfig;
import com.server.repository.ServerRepository;
import com.server.repository.ServerConfigRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
* 配置管理服务
* @author Java实战
*/
@Slf4j
@Service
public class ConfigManagementService {

@Autowired
private ServerRepository serverRepository;

@Autowired
private ServerConfigRepository configRepository;

@Value("${server-config.config-path:/opt/server-configs}")
private String configPath;

@Value("${server-config.backup-path:/opt/config-backups}")
private String backupPath;

/**
* 创建服务器配置
*/
@Transactional
public ServerConfig createConfig(Long serverId, String configName, String configContent, String configType) {
try {
log.info("创建服务器配置: serverId={}, configName={}", serverId, configName);

Optional<Server> serverOpt = serverRepository.findById(serverId);
if (!serverOpt.isPresent()) {
throw new RuntimeException("服务器不存在");
}

Server server = serverOpt.get();

// 创建配置实体
ServerConfig config = ServerConfig.builder()
.server(server)
.configName(configName)
.configContent(configContent)
.configType(configType)
.version(1)
.status("ACTIVE")
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.build();

// 保存到数据库
config = configRepository.save(config);

// 创建配置文件
createConfigFile(server, config);

log.info("服务器配置创建成功: configId={}", config.getId());
return config;

} catch (Exception e) {
log.error("创建服务器配置失败", e);
throw new RuntimeException("创建服务器配置失败", e);
}
}

/**
* 更新服务器配置
*/
@Transactional
public ServerConfig updateConfig(Long configId, String configContent) {
try {
log.info("更新服务器配置: configId={}", configId);

Optional<ServerConfig> configOpt = configRepository.findById(configId);
if (!configOpt.isPresent()) {
throw new RuntimeException("配置不存在");
}

ServerConfig config = configOpt.get();

// 备份当前配置
backupConfig(config);

// 更新配置
config.setConfigContent(configContent);
config.setVersion(config.getVersion() + 1);
config.setUpdateTime(LocalDateTime.now());

config = configRepository.save(config);

// 更新配置文件
updateConfigFile(config);

log.info("服务器配置更新成功: configId={}, version={}", configId, config.getVersion());
return config;

} catch (Exception e) {
log.error("更新服务器配置失败", e);
throw new RuntimeException("更新服务器配置失败", e);
}
}

/**
* 部署配置到服务器
*/
@Transactional
public boolean deployConfig(Long configId) {
try {
log.info("部署配置到服务器: configId={}", configId);

Optional<ServerConfig> configOpt = configRepository.findById(configId);
if (!configOpt.isPresent()) {
throw new RuntimeException("配置不存在");
}

ServerConfig config = configOpt.get();
Server server = config.getServer();

// 检查服务器状态
if (!"ONLINE".equals(server.getStatus())) {
throw new RuntimeException("服务器状态异常,无法部署");
}

// 部署配置
boolean success = deployConfigToServer(server, config);

if (success) {
config.setLastDeployTime(LocalDateTime.now());
config.setDeployStatus("SUCCESS");
configRepository.save(config);

log.info("配置部署成功: configId={}", configId);
} else {
config.setDeployStatus("FAILED");
configRepository.save(config);

log.error("配置部署失败: configId={}", configId);
}

return success;

} catch (Exception e) {
log.error("部署配置失败", e);
throw new RuntimeException("部署配置失败", e);
}
}

/**
* 回滚配置
*/
@Transactional
public boolean rollbackConfig(Long configId, Integer targetVersion) {
try {
log.info("回滚配置: configId={}, targetVersion={}", configId, targetVersion);

Optional<ServerConfig> configOpt = configRepository.findById(configId);
if (!configOpt.isPresent()) {
throw new RuntimeException("配置不存在");
}

ServerConfig config = configOpt.get();

// 查找目标版本的配置
Optional<ServerConfig> targetConfigOpt = configRepository
.findByServerAndConfigNameAndVersion(
config.getServer(),
config.getConfigName(),
targetVersion);

if (!targetConfigOpt.isPresent()) {
throw new RuntimeException("目标版本配置不存在");
}

ServerConfig targetConfig = targetConfigOpt.get();

// 回滚配置
config.setConfigContent(targetConfig.getConfigContent());
config.setVersion(config.getVersion() + 1);
config.setUpdateTime(LocalDateTime.now());
config.setDeployStatus("ROLLBACK");

config = configRepository.save(config);

// 部署回滚后的配置
boolean success = deployConfigToServer(config.getServer(), config);

if (success) {
log.info("配置回滚成功: configId={}, version={}", configId, config.getVersion());
} else {
log.error("配置回滚失败: configId={}", configId);
}

return success;

} catch (Exception e) {
log.error("回滚配置失败", e);
throw new RuntimeException("回滚配置失败", e);
}
}

/**
* 获取服务器配置列表
*/
public List<ServerConfig> getServerConfigs(Long serverId) {
try {
log.info("获取服务器配置列表: serverId={}", serverId);

Optional<Server> serverOpt = serverRepository.findById(serverId);
if (!serverOpt.isPresent()) {
throw new RuntimeException("服务器不存在");
}

List<ServerConfig> configs = configRepository.findByServerOrderByCreateTimeDesc(serverOpt.get());

log.info("获取服务器配置列表成功,数量: {}", configs.size());
return configs;

} catch (Exception e) {
log.error("获取服务器配置列表失败", e);
throw new RuntimeException("获取服务器配置列表失败", e);
}
}

/**
* 创建配置文件
*/
private void createConfigFile(Server server, ServerConfig config) throws IOException {
String fileName = String.format("%s_%s_%d.%s",
server.getHost(),
config.getConfigName(),
config.getVersion(),
getFileExtension(config.getConfigType()));

Path filePath = Paths.get(configPath, server.getEnvironment(), fileName);

// 确保目录存在
Files.createDirectories(filePath.getParent());

// 写入配置文件
Files.write(filePath, config.getConfigContent().getBytes());

log.info("配置文件创建成功: {}", filePath);
}

/**
* 更新配置文件
*/
private void updateConfigFile(ServerConfig config) throws IOException {
Server server = config.getServer();
String fileName = String.format("%s_%s_%d.%s",
server.getHost(),
config.getConfigName(),
config.getVersion(),
getFileExtension(config.getConfigType()));

Path filePath = Paths.get(configPath, server.getEnvironment(), fileName);

// 写入配置文件
Files.write(filePath, config.getConfigContent().getBytes());

log.info("配置文件更新成功: {}", filePath);
}

/**
* 备份配置文件
*/
private void backupConfig(ServerConfig config) throws IOException {
Server server = config.getServer();
String fileName = String.format("%s_%s_%d_%s.%s",
server.getHost(),
config.getConfigName(),
config.getVersion(),
LocalDateTime.now().toString().replace(":", "-"),
getFileExtension(config.getConfigType()));

Path backupFilePath = Paths.get(backupPath, server.getEnvironment(), fileName);

// 确保备份目录存在
Files.createDirectories(backupFilePath.getParent());

// 写入备份文件
Files.write(backupFilePath, config.getConfigContent().getBytes());

log.info("配置文件备份成功: {}", backupFilePath);
}

/**
* 部署配置到服务器
*/
private boolean deployConfigToServer(Server server, ServerConfig config) {
try {
log.info("部署配置到服务器: host={}, configName={}", server.getHost(), config.getConfigName());

// 这里应该实现SSH连接和文件传输逻辑
// 简化实现,实际应该使用SSH客户端

// 模拟部署过程
Thread.sleep(1000);

log.info("配置部署到服务器成功: host={}", server.getHost());
return true;

} catch (Exception e) {
log.error("部署配置到服务器失败", e);
return false;
}
}

/**
* 获取文件扩展名
*/
private String getFileExtension(String configType) {
switch (configType.toUpperCase()) {
case "YAML":
case "YML":
return "yml";
case "JSON":
return "json";
case "XML":
return "xml";
case "PROPERTIES":
return "properties";
default:
return "txt";
}
}
}

6. 服务器监控服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package com.server.service;

import com.server.entity.Server;
import com.server.repository.ServerRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
* 服务器监控服务
* @author Java实战
*/
@Slf4j
@Service
public class ServerMonitoringService {

@Autowired
private ServerRepository serverRepository;

@Autowired
private NotificationService notificationService;

/**
* 监控服务器状态(每分钟执行一次)
*/
@Scheduled(fixedRate = 60000)
public void monitorServers() {
try {
log.info("开始监控服务器状态");

List<Server> servers = serverRepository.findAll();

for (Server server : servers) {
monitorServer(server);
}

log.info("服务器状态监控完成");

} catch (Exception e) {
log.error("服务器监控异常", e);
}
}

/**
* 监控单个服务器
*/
private void monitorServer(Server server) {
try {
log.debug("监控服务器: {}", server.getHost());

// 检查服务器连通性
boolean isOnline = checkServerConnectivity(server);

// 检查系统资源
ServerMetrics metrics = getServerMetrics(server);

// 更新服务器状态
updateServerStatus(server, isOnline, metrics);

// 检查告警条件
checkAlerts(server, metrics);

} catch (Exception e) {
log.error("监控服务器失败: {}", server.getHost(), e);

// 更新服务器状态为离线
server.setStatus("OFFLINE");
server.setLastCheckTime(LocalDateTime.now());
serverRepository.save(server);
}
}

/**
* 检查服务器连通性
*/
private boolean checkServerConnectivity(Server server) {
try {
// 这里应该实现实际的连通性检查
// 简化实现,实际应该使用SSH连接测试

log.debug("检查服务器连通性: {}", server.getHost());

// 模拟连通性检查
Thread.sleep(100);

return true; // 简化实现,总是返回true

} catch (Exception e) {
log.error("检查服务器连通性失败: {}", server.getHost(), e);
return false;
}
}

/**
* 获取服务器指标
*/
private ServerMetrics getServerMetrics(Server server) {
try {
log.debug("获取服务器指标: {}", server.getHost());

// 这里应该实现实际的指标获取
// 简化实现,返回模拟数据

return ServerMetrics.builder()
.cpuUsage(Math.random() * 100)
.memoryUsage(Math.random() * 100)
.diskUsage(Math.random() * 100)
.networkIn(1000 + Math.random() * 1000)
.networkOut(1000 + Math.random() * 1000)
.timestamp(LocalDateTime.now())
.build();

} catch (Exception e) {
log.error("获取服务器指标失败: {}", server.getHost(), e);
return null;
}
}

/**
* 更新服务器状态
*/
private void updateServerStatus(Server server, boolean isOnline, ServerMetrics metrics) {
try {
String oldStatus = server.getStatus();
String newStatus = isOnline ? "ONLINE" : "OFFLINE";

server.setStatus(newStatus);
server.setLastCheckTime(LocalDateTime.now());

if (metrics != null) {
server.setCpuUsage(metrics.getCpuUsage());
server.setMemoryUsage(metrics.getMemoryUsage());
server.setDiskUsage(metrics.getDiskUsage());
}

serverRepository.save(server);

// 状态变化时发送通知
if (!oldStatus.equals(newStatus)) {
notificationService.sendStatusChangeNotification(server, oldStatus, newStatus);
}

} catch (Exception e) {
log.error("更新服务器状态失败: {}", server.getHost(), e);
}
}

/**
* 检查告警条件
*/
private void checkAlerts(Server server, ServerMetrics metrics) {
if (metrics == null) return;

try {
// CPU使用率告警
if (metrics.getCpuUsage() > 80) {
notificationService.sendAlertNotification(server, "CPU",
String.format("CPU使用率过高: %.2f%%", metrics.getCpuUsage()));
}

// 内存使用率告警
if (metrics.getMemoryUsage() > 85) {
notificationService.sendAlertNotification(server, "MEMORY",
String.format("内存使用率过高: %.2f%%", metrics.getMemoryUsage()));
}

// 磁盘使用率告警
if (metrics.getDiskUsage() > 90) {
notificationService.sendAlertNotification(server, "DISK",
String.format("磁盘使用率过高: %.2f%%", metrics.getDiskUsage()));
}

} catch (Exception e) {
log.error("检查告警条件失败: {}", server.getHost(), e);
}
}

/**
* 服务器指标
*/
@lombok.Data
@lombok.Builder
public static class ServerMetrics {
private Double cpuUsage;
private Double memoryUsage;
private Double diskUsage;
private Double networkIn;
private Double networkOut;
private LocalDateTime timestamp;
}
}

7. 通知服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package com.server.service;

import com.server.entity.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.List;

/**
* 通知服务
* @author Java实战
*/
@Slf4j
@Service
public class NotificationService {

@Autowired
private JavaMailSender mailSender;

@Autowired
private RestTemplate restTemplate;

@Value("${server-config.monitoring.notifications.email.enabled:false}")
private boolean emailEnabled;

@Value("${server-config.monitoring.notifications.webhook.enabled:false}")
private boolean webhookEnabled;

@Value("${server-config.monitoring.notifications.email.recipients:}")
private List<String> emailRecipients;

@Value("${server-config.monitoring.notifications.webhook.url:}")
private String webhookUrl;

/**
* 发送状态变化通知
*/
public void sendStatusChangeNotification(Server server, String oldStatus, String newStatus) {
try {
log.info("发送状态变化通知: host={}, {} -> {}", server.getHost(), oldStatus, newStatus);

String subject = String.format("服务器状态变化 - %s", server.getHost());
String content = String.format(
"服务器: %s\n" +
"IP地址: %s\n" +
"环境: %s\n" +
"状态变化: %s -> %s\n" +
"时间: %s",
server.getHost(),
server.getIpAddress(),
server.getEnvironment(),
oldStatus,
newStatus,
LocalDateTime.now()
);

// 发送邮件通知
if (emailEnabled) {
sendEmailNotification(subject, content);
}

// 发送Webhook通知
if (webhookEnabled) {
sendWebhookNotification("STATUS_CHANGE", subject, content, server);
}

} catch (Exception e) {
log.error("发送状态变化通知失败", e);
}
}

/**
* 发送告警通知
*/
public void sendAlertNotification(Server server, String alertType, String message) {
try {
log.warn("发送告警通知: host={}, type={}, message={}", server.getHost(), alertType, message);

String subject = String.format("服务器告警 - %s (%s)", server.getHost(), alertType);
String content = String.format(
"服务器: %s\n" +
"IP地址: %s\n" +
"环境: %s\n" +
"告警类型: %s\n" +
"告警信息: %s\n" +
"时间: %s",
server.getHost(),
server.getIpAddress(),
server.getEnvironment(),
alertType,
message,
LocalDateTime.now()
);

// 发送邮件通知
if (emailEnabled) {
sendEmailNotification(subject, content);
}

// 发送Webhook通知
if (webhookEnabled) {
sendWebhookNotification("ALERT", subject, content, server);
}

} catch (Exception e) {
log.error("发送告警通知失败", e);
}
}

/**
* 发送部署通知
*/
public void sendDeploymentNotification(Server server, String configName, boolean success) {
try {
log.info("发送部署通知: host={}, config={}, success={}", server.getHost(), configName, success);

String subject = String.format("配置部署%s - %s", success ? "成功" : "失败", server.getHost());
String content = String.format(
"服务器: %s\n" +
"IP地址: %s\n" +
"环境: %s\n" +
"配置名称: %s\n" +
"部署结果: %s\n" +
"时间: %s",
server.getHost(),
server.getIpAddress(),
server.getEnvironment(),
configName,
success ? "成功" : "失败",
LocalDateTime.now()
);

// 发送邮件通知
if (emailEnabled) {
sendEmailNotification(subject, content);
}

// 发送Webhook通知
if (webhookEnabled) {
sendWebhookNotification("DEPLOYMENT", subject, content, server);
}

} catch (Exception e) {
log.error("发送部署通知失败", e);
}
}

/**
* 发送邮件通知
*/
private void sendEmailNotification(String subject, String content) {
try {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(emailRecipients.toArray(new String[0]));
message.setSubject(subject);
message.setText(content);

mailSender.send(message);

log.info("邮件通知发送成功: {}", subject);

} catch (Exception e) {
log.error("发送邮件通知失败", e);
}
}

/**
* 发送Webhook通知
*/
private void sendWebhookNotification(String type, String subject, String content, Server server) {
try {
WebhookPayload payload = WebhookPayload.builder()
.type(type)
.subject(subject)
.content(content)
.server(server)
.timestamp(LocalDateTime.now())
.build();

restTemplate.postForObject(webhookUrl, payload, String.class);

log.info("Webhook通知发送成功: {}", type);

} catch (Exception e) {
log.error("发送Webhook通知失败", e);
}
}

/**
* Webhook载荷
*/
@lombok.Data
@lombok.Builder
public static class WebhookPayload {
private String type;
private String subject;
private String content;
private Server server;
private LocalDateTime timestamp;
}
}

8. 控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package com.server.controller;

import com.server.entity.Server;
import com.server.entity.ServerConfig;
import com.server.service.ConfigManagementService;
import com.server.service.ServerMonitoringService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
* 服务器配置控制器
* @author Java实战
*/
@Slf4j
@RestController
@RequestMapping("/api/server")
public class ServerConfigController {

@Autowired
private ConfigManagementService configManagementService;

@Autowired
private ServerMonitoringService serverMonitoringService;

/**
* 创建服务器配置
*/
@PostMapping("/{serverId}/config")
public ResponseEntity<ServerConfig> createConfig(
@PathVariable Long serverId,
@RequestParam String configName,
@RequestParam String configContent,
@RequestParam String configType) {
try {
ServerConfig config = configManagementService.createConfig(
serverId, configName, configContent, configType);
return ResponseEntity.ok(config);
} catch (Exception e) {
log.error("创建服务器配置失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 更新服务器配置
*/
@PutMapping("/config/{configId}")
public ResponseEntity<ServerConfig> updateConfig(
@PathVariable Long configId,
@RequestParam String configContent) {
try {
ServerConfig config = configManagementService.updateConfig(configId, configContent);
return ResponseEntity.ok(config);
} catch (Exception e) {
log.error("更新服务器配置失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 部署配置
*/
@PostMapping("/config/{configId}/deploy")
public ResponseEntity<Boolean> deployConfig(@PathVariable Long configId) {
try {
boolean success = configManagementService.deployConfig(configId);
return ResponseEntity.ok(success);
} catch (Exception e) {
log.error("部署配置失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 回滚配置
*/
@PostMapping("/config/{configId}/rollback")
public ResponseEntity<Boolean> rollbackConfig(
@PathVariable Long configId,
@RequestParam Integer targetVersion) {
try {
boolean success = configManagementService.rollbackConfig(configId, targetVersion);
return ResponseEntity.ok(success);
} catch (Exception e) {
log.error("回滚配置失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 获取服务器配置列表
*/
@GetMapping("/{serverId}/configs")
public ResponseEntity<List<ServerConfig>> getServerConfigs(@PathVariable Long serverId) {
try {
List<ServerConfig> configs = configManagementService.getServerConfigs(serverId);
return ResponseEntity.ok(configs);
} catch (Exception e) {
log.error("获取服务器配置列表失败", e);
return ResponseEntity.internalServerError().build();
}
}

/**
* 手动触发服务器监控
*/
@PostMapping("/monitor")
public ResponseEntity<String> triggerMonitoring() {
try {
serverMonitoringService.monitorServers();
return ResponseEntity.ok("监控任务已触发");
} catch (Exception e) {
log.error("触发监控失败", e);
return ResponseEntity.internalServerError().build();
}
}
}

9. 总结

服务器配置管理与自动化部署是现代化运维体系的重要组成部分。通过本文的详细介绍,我们了解了:

  1. 配置管理: 统一管理服务器配置文件
  2. 自动化部署: 实现配置的自动化部署和回滚
  3. 服务监控: 实时监控服务器状态和资源使用
  4. 告警通知: 及时通知运维人员处理问题
  5. 版本控制: 配置版本管理和历史记录

通过合理的架构设计和实现,可以为运维团队提供高效、可靠的服务器管理工具。


Java实战要点:

  • Spring Boot提供完整的应用框架
  • 定时任务实现自动化监控
  • 事务管理保证数据一致性
  • 异常处理确保系统稳定性
  • 邮件和Webhook实现多渠道通知

代码注解说明:

  • @Scheduled: 定时任务注解
  • @Transactional: 事务管理注解
  • @Value: 配置属性注入
  • @Service: 服务层注解
  • @RestController: REST控制器注解
  • 配置管理: 支持多种配置格式和版本控制