Appearance
监控和管理
概述
Spring Cloud Gateway 的 /gateway Actuator 端点是一个强大的监控和管理工具,它允许我们监控和交互网关应用程序。在微服务架构中,网关作为流量的入口和出口,其健康状态和路由配置的实时监控对于系统稳定性至关重要。
为了能够远程访问这些端点,必须在应用程序属性中启用并通过 HTTP 或 JMX 暴露端点。
实际应用场景
在生产环境中,Gateway Actuator API 主要解决以下业务问题:
- 运维监控:实时查看网关路由状态和过滤器配置
- 故障排查:当某个服务出现问题时,快速检查路由配置是否正确
- 动态管理:在不重启服务的情况下,动态添加、删除或修改路由
- 性能优化:通过查看过滤器链的执行顺序,优化请求处理流程
配置启用
基本配置
properties
# 启用 gateway 端点(默认为 true)
management.endpoint.gateway.enabled=true
# 通过 HTTP 暴露 gateway 端点
management.endpoints.web.exposure.include=gatewaykotlin
@Configuration
@EnableConfigurationProperties(GatewayProperties::class)
class GatewayConfig {
/**
* 配置管理端点的安全性
*/
@Bean
fun managementSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
return http
.securityMatcher("/actuator/**")
.authorizeHttpRequests { auth ->
auth.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/gateway/**").hasRole("ADMIN")
.anyRequest().authenticated()
}
.httpBasic(Customizer.withDefaults())
.build()
}
}java
@Configuration
@EnableConfigurationProperties(GatewayProperties.class)
public class GatewayConfig {
/**
* 配置管理端点的安全性
*/
@Bean
public SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.securityMatcher("/actuator/**")
.authorizeHttpRequests(auth ->
auth.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/gateway/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.build();
}
}可用端点概览
当访问 /actuator/gateway 时,会返回所有可用的子端点及其支持的 HTTP 方法:
json
[
{
"href": "/actuator/gateway/",
"methods": ["GET"]
},
{
"href": "/actuator/gateway/routes",
"methods": ["POST", "GET"]
},
{
"href": "/actuator/gateway/globalfilters",
"methods": ["GET"]
},
{
"href": "/actuator/gateway/routefilters",
"methods": ["GET"]
},
{
"href": "/actuator/gateway/refresh",
"methods": ["POST"]
}
]详细功能解析
1. 详细路由格式 (Verbose Actuator Format)
Spring Cloud Gateway 提供了更详细的路由信息格式,包含每个路由的谓词、过滤器和配置信息。
json
[
{
"predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",
"route_id": "add_request_header_test",
"filters": [
"[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",
"[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",
"[[PrefixPath prefix = '/httpbin'], order = 2]"
],
"uri": "lb://testservice",
"order": 0
}
]控制详细格式
properties
# 禁用详细格式(默认启用)
spring.cloud.gateway.actuator.verbose.enabled=false详细格式在调试和故障排查时非常有用,建议在开发和测试环境中保持启用。
2. 路由过滤器管理
全局过滤器查询
通过 GET /actuator/gateway/globalfilters 查看应用于所有路由的全局过滤器:
响应示例:
json
{
"org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@77856cc5": 10100,
"org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,
"org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1,
"org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647,
"org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647
}数字表示过滤器在过滤器链中的执行顺序,数字越小优先级越高。
路由过滤器查询
通过 GET /actuator/gateway/routefilters 查看可用的 GatewayFilter 工厂:
json
{
"[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
"[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
"[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}3. 路由缓存刷新
在生产环境中,有时需要动态刷新路由配置而不重启服务:
全量刷新
bash
curl -X POST http://localhost:8080/actuator/gateway/refresh基于元数据的选择性刷新
bash
# 只刷新指定分组的路由
curl -X POST "http://localhost:8080/actuator/gateway/refresh?metadata=group:group-1"kotlin
@Service
class RouteRefreshService(
private val routeDefinitionRepository: RouteDefinitionRepository,
private val applicationEventPublisher: ApplicationEventPublisher
) {
/**
* 基于元数据刷新特定路由
* 适用场景:微服务分组部署,只刷新特定业务模块的路由
*/
fun refreshRoutesByMetadata(metadataKey: String, metadataValue: String) {
val routesToRefresh = routeDefinitionRepository.routeDefinitions
.filter { route ->
route.metadata[metadataKey] == metadataValue
}
.collectList()
.block()
routesToRefresh?.forEach { route ->
// 重新加载路由定义
applicationEventPublisher.publishEvent(RefreshRoutesEvent(this))
logger.info("刷新路由: ${route.id}, 元数据: $metadataKey=$metadataValue")
}
}
companion object {
private val logger = LoggerFactory.getLogger(RouteRefreshService::class.java)
}
}java
@Service
public class RouteRefreshService {
private final RouteDefinitionRepository routeDefinitionRepository;
private final ApplicationEventPublisher applicationEventPublisher;
private static final Logger logger = LoggerFactory.getLogger(RouteRefreshService.class);
public RouteRefreshService(RouteDefinitionRepository routeDefinitionRepository,
ApplicationEventPublisher applicationEventPublisher) {
this.routeDefinitionRepository = routeDefinitionRepository;
this.applicationEventPublisher = applicationEventPublisher;
}
/**
* 基于元数据刷新特定路由
* 适用场景:微服务分组部署,只刷新特定业务模块的路由
*/
public void refreshRoutesByMetadata(String metadataKey, String metadataValue) {
List<RouteDefinition> routesToRefresh = routeDefinitionRepository.getRouteDefinitions()
.filter(route -> metadataValue.equals(route.getMetadata().get(metadataKey)))
.collectList()
.block();
if (routesToRefresh != null) {
routesToRefresh.forEach(route -> {
// 重新加载路由定义
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
logger.info("刷新路由: {}, 元数据: {}={}", route.getId(), metadataKey, metadataValue);
});
}
}
}4. 路由信息查询
查询所有路由
GET /actuator/gateway/routes 返回网关中定义的所有路由:
json
[
{
"route_id": "user_service_route",
"route_object": {
"predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d",
"filters": [
"OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}"
]
},
"order": 0
}
]查询特定路由
GET /actuator/gateway/routes/{id} 获取特定路由的详细信息:
json
{
"id": "user_service_route",
"predicates": [
{
"name": "Path",
"args": { "_genkey_0": "/api/users/**" }
}
],
"filters": [
{
"name": "StripPrefix",
"args": { "_genkey_0": "2" }
}
],
"uri": "lb://user-service",
"order": 0
}5. 动态路由管理
创建路由
bash
curl -X POST http://localhost:8080/actuator/gateway/routes/new_route \
-H "Content-Type: application/json" \
-d '{
"predicates": [{
"name": "Path",
"args": {"_genkey_0": "/api/orders/**"}
}],
"filters": [{
"name": "StripPrefix",
"args": {"_genkey_0": "2"}
}],
"uri": "lb://order-service",
"order": 100
}'删除路由
bash
curl -X DELETE http://localhost:8080/actuator/gateway/routes/route_to_deletekotlin
@RestController
@RequestMapping("/admin/routes")
class DynamicRouteController(
private val routeDefinitionRepository: RouteDefinitionRepository,
private val applicationEventPublisher: ApplicationEventPublisher
) {
/**
* 动态添加路由 - 适用于新服务上线场景
*/
@PostMapping("/{serviceId}")
fun addServiceRoute(
@PathVariable serviceId: String,
@RequestBody request: CreateRouteRequest
): ResponseEntity<String> {
val routeDefinition = RouteDefinition().apply {
id = "${serviceId}_route"
uri = URI.create("lb://$serviceId")
order = request.order ?: 100
// 添加路径谓词
predicates = listOf(
PredicateDefinition().apply {
name = "Path"
addArg("_genkey_0", "/api/$serviceId/**")
}
)
// 添加默认过滤器
filters = listOf(
FilterDefinition().apply {
name = "StripPrefix"
addArg("_genkey_0", "2")
},
FilterDefinition().apply {
name = "AddRequestHeader"
addArg("_genkey_0", "X-Service-Name")
addArg("_genkey_1", serviceId)
}
)
// 添加元数据
metadata["service"] = serviceId
metadata["created_by"] = "admin"
metadata["created_at"] = Instant.now().toString()
}
return try {
routeDefinitionRepository.save(Mono.just(routeDefinition)).block()
// 触发路由刷新事件
applicationEventPublisher.publishEvent(RefreshRoutesEvent(this))
ResponseEntity.ok("路由 ${routeDefinition.id} 创建成功")
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("创建路由失败: ${e.message}")
}
}
/**
* 批量创建路由 - 适用于微服务集群初始化
*/
@PostMapping("/batch")
fun createMultipleRoutes(@RequestBody services: List<String>): ResponseEntity<Map<String, String>> {
val results = mutableMapOf<String, String>()
services.forEach { serviceId ->
try {
val routeDefinition = createDefaultRoute(serviceId)
routeDefinitionRepository.save(Mono.just(routeDefinition)).block()
results[serviceId] = "成功"
} catch (e: Exception) {
results[serviceId] = "失败: ${e.message}"
}
}
// 统一刷新路由
applicationEventPublisher.publishEvent(RefreshRoutesEvent(this))
return ResponseEntity.ok(results)
}
private fun createDefaultRoute(serviceId: String): RouteDefinition {
return RouteDefinition().apply {
id = "${serviceId}_default_route"
uri = URI.create("lb://$serviceId")
order = 100
predicates = listOf(
PredicateDefinition().apply {
name = "Path"
addArg("_genkey_0", "/api/$serviceId/**")
}
)
filters = listOf(
FilterDefinition().apply {
name = "StripPrefix"
addArg("_genkey_0", "2")
}
)
metadata["service"] = serviceId
metadata["type"] = "default"
}
}
data class CreateRouteRequest(
val path: String? = null,
val order: Int? = null,
val filters: List<String>? = null
)
}java
@RestController
@RequestMapping("/admin/routes")
public class DynamicRouteController {
private final RouteDefinitionRepository routeDefinitionRepository;
private final ApplicationEventPublisher applicationEventPublisher;
public DynamicRouteController(RouteDefinitionRepository routeDefinitionRepository,
ApplicationEventPublisher applicationEventPublisher) {
this.routeDefinitionRepository = routeDefinitionRepository;
this.applicationEventPublisher = applicationEventPublisher;
}
/**
* 动态添加路由 - 适用于新服务上线场景
*/
@PostMapping("/{serviceId}")
public ResponseEntity<String> addServiceRoute(@PathVariable String serviceId,
@RequestBody CreateRouteRequest request) {
RouteDefinition routeDefinition = new RouteDefinition();
routeDefinition.setId(serviceId + "_route");
routeDefinition.setUri(URI.create("lb://" + serviceId));
routeDefinition.setOrder(request.getOrder() != null ? request.getOrder() : 100);
// 添加路径谓词
PredicateDefinition pathPredicate = new PredicateDefinition();
pathPredicate.setName("Path");
pathPredicate.addArg("_genkey_0", "/api/" + serviceId + "/**");
routeDefinition.setPredicates(List.of(pathPredicate));
// 添加默认过滤器
FilterDefinition stripPrefixFilter = new FilterDefinition();
stripPrefixFilter.setName("StripPrefix");
stripPrefixFilter.addArg("_genkey_0", "2");
FilterDefinition headerFilter = new FilterDefinition();
headerFilter.setName("AddRequestHeader");
headerFilter.addArg("_genkey_0", "X-Service-Name");
headerFilter.addArg("_genkey_1", serviceId);
routeDefinition.setFilters(List.of(stripPrefixFilter, headerFilter));
// 添加元数据
routeDefinition.setMetadata(Map.of(
"service", serviceId,
"created_by", "admin",
"created_at", Instant.now().toString()
));
try {
routeDefinitionRepository.save(Mono.just(routeDefinition)).block();
// 触发路由刷新事件
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
return ResponseEntity.ok("路由 " + routeDefinition.getId() + " 创建成功");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("创建路由失败: " + e.getMessage());
}
}
public static class CreateRouteRequest {
private String path;
private Integer order;
private List<String> filters;
// getters and setters
public String getPath() { return path; }
public void setPath(String path) { this.path = path; }
public Integer getOrder() { return order; }
public void setOrder(Integer order) { this.order = order; }
public List<String> getFilters() { return filters; }
public void setFilters(List<String> filters) { this.filters = filters; }
}
}实际业务场景示例
场景一:新服务上线
当新的微服务需要接入网关时,可以使用 Actuator API 动态添加路由:
场景二:故障排查
当某个服务出现问题时,运维人员可以通过 Actuator API 快速排查:
- 检查路由配置:
GET /actuator/gateway/routes/problematic-service - 查看过滤器状态:
GET /actuator/gateway/globalfilters - 验证路由谓词:分析返回的 predicate 配置
场景三:灰度发布
在灰度发布场景中,可以动态调整路由权重:
kotlin
@RestController
@RequestMapping("/admin/gray-release")
class GrayReleaseController(
private val routeDefinitionRepository: RouteDefinitionRepository,
private val applicationEventPublisher: ApplicationEventPublisher
) {
/**
* 创建灰度路由 - 将部分流量导向新版本
*/
@PostMapping("/{serviceId}/enable")
fun enableGrayRelease(
@PathVariable serviceId: String,
@RequestParam(defaultValue = "10") weight: Int
): ResponseEntity<String> {
// 创建灰度路由(权重路由)
val grayRoute = RouteDefinition().apply {
id = "${serviceId}_gray_route"
uri = URI.create("lb://${serviceId}-gray")
order = 1 // 优先级高于正常路由
predicates = listOf(
PredicateDefinition().apply {
name = "Path"
addArg("_genkey_0", "/api/$serviceId/**")
},
PredicateDefinition().apply {
name = "Weight"
addArg("_genkey_0", serviceId)
addArg("_genkey_1", weight.toString())
}
)
filters = listOf(
FilterDefinition().apply {
name = "AddRequestHeader"
addArg("_genkey_0", "X-Gray-Release")
addArg("_genkey_1", "true")
}
)
metadata["type"] = "gray-release"
metadata["weight"] = weight.toString()
}
// 更新正常路由的权重
val normalWeight = 100 - weight
updateNormalRouteWeight(serviceId, normalWeight)
routeDefinitionRepository.save(Mono.just(grayRoute)).block()
applicationEventPublisher.publishEvent(RefreshRoutesEvent(this))
return ResponseEntity.ok("灰度发布已启用,灰度流量占比: $weight%")
}
private fun updateNormalRouteWeight(serviceId: String, weight: Int) {
// 实现正常路由权重更新逻辑
// ...
}
}java
@RestController
@RequestMapping("/admin/gray-release")
public class GrayReleaseController {
private final RouteDefinitionRepository routeDefinitionRepository;
private final ApplicationEventPublisher applicationEventPublisher;
public GrayReleaseController(RouteDefinitionRepository routeDefinitionRepository,
ApplicationEventPublisher applicationEventPublisher) {
this.routeDefinitionRepository = routeDefinitionRepository;
this.applicationEventPublisher = applicationEventPublisher;
}
/**
* 创建灰度路由 - 将部分流量导向新版本
*/
@PostMapping("/{serviceId}/enable")
public ResponseEntity<String> enableGrayRelease(@PathVariable String serviceId,
@RequestParam(defaultValue = "10") int weight) {
// 创建灰度路由(权重路由)
RouteDefinition grayRoute = new RouteDefinition();
grayRoute.setId(serviceId + "_gray_route");
grayRoute.setUri(URI.create("lb://" + serviceId + "-gray"));
grayRoute.setOrder(1); // 优先级高于正常路由
// 设置谓词
PredicateDefinition pathPredicate = new PredicateDefinition();
pathPredicate.setName("Path");
pathPredicate.addArg("_genkey_0", "/api/" + serviceId + "/**");
PredicateDefinition weightPredicate = new PredicateDefinition();
weightPredicate.setName("Weight");
weightPredicate.addArg("_genkey_0", serviceId);
weightPredicate.addArg("_genkey_1", String.valueOf(weight));
grayRoute.setPredicates(List.of(pathPredicate, weightPredicate));
// 设置过滤器
FilterDefinition headerFilter = new FilterDefinition();
headerFilter.setName("AddRequestHeader");
headerFilter.addArg("_genkey_0", "X-Gray-Release");
headerFilter.addArg("_genkey_1", "true");
grayRoute.setFilters(List.of(headerFilter));
// 设置元数据
grayRoute.setMetadata(Map.of(
"type", "gray-release",
"weight", String.valueOf(weight)
));
// 更新正常路由的权重
int normalWeight = 100 - weight;
updateNormalRouteWeight(serviceId, normalWeight);
routeDefinitionRepository.save(Mono.just(grayRoute)).block();
applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
return ResponseEntity.ok("灰度发布已启用,灰度流量占比: " + weight + "%");
}
private void updateNormalRouteWeight(String serviceId, int weight) {
// 实现正常路由权重更新逻辑
// ...
}
}端点安全配置
在生产环境中,这些管理端点需要适当的安全保护:
kotlin
@Configuration
@EnableWebSecurity
class ActuatorSecurityConfig {
@Bean
fun actuatorSecurityFilterChain(http: HttpSecurity): SecurityFilterChain {
return http
.securityMatcher("/actuator/**")
.authorizeHttpRequests { auth ->
auth
// 健康检查端点允许匿名访问
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/info").permitAll()
// 网关管理端点需要管理员权限
.requestMatchers("/actuator/gateway/**").hasRole("GATEWAY_ADMIN")
// 其他端点需要运维权限
.requestMatchers("/actuator/**").hasRole("OPS")
.anyRequest().authenticated()
}
.httpBasic(Customizer.withDefaults())
.sessionManagement { session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
}
.build()
}
@Bean
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()
@Bean
fun userDetailsService(passwordEncoder: PasswordEncoder): UserDetailsService {
val admin = User.builder()
.username("gateway-admin")
.password(passwordEncoder.encode("secure-password"))
.roles("GATEWAY_ADMIN", "OPS")
.build()
val ops = User.builder()
.username("ops-user")
.password(passwordEncoder.encode("ops-password"))
.roles("OPS")
.build()
return InMemoryUserDetailsManager(admin, ops)
}
}java
@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig {
@Bean
public SecurityFilterChain actuatorSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.securityMatcher("/actuator/**")
.authorizeHttpRequests(auth ->
auth
// 健康检查端点允许匿名访问
.requestMatchers("/actuator/health").permitAll()
.requestMatchers("/actuator/info").permitAll()
// 网关管理端点需要管理员权限
.requestMatchers("/actuator/gateway/**").hasRole("GATEWAY_ADMIN")
// 其他端点需要运维权限
.requestMatchers("/actuator/**").hasRole("OPS")
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails admin = User.builder()
.username("gateway-admin")
.password(passwordEncoder.encode("secure-password"))
.roles("GATEWAY_ADMIN", "OPS")
.build();
UserDetails ops = User.builder()
.username("ops-user")
.password(passwordEncoder.encode("ops-password"))
.roles("OPS")
.build();
return new InMemoryUserDetailsManager(admin, ops);
}
}监控和告警
结合监控系统,可以对网关状态进行实时监控:
kotlin
@Service
class GatewayMonitoringService(
private val webClient: WebClient,
private val meterRegistry: MeterRegistry
) {
private val logger = LoggerFactory.getLogger(GatewayMonitoringService::class.java)
/**
* 定期检查网关健康状态
*/
@Scheduled(fixedRate = 30000) // 每30秒检查一次
fun checkGatewayHealth() {
try {
val routes = getGatewayRoutes()
val routeCount = routes.size
// 记录路由数量指标
meterRegistry.gauge("gateway.routes.count", routeCount)
// 检查路由健康状态
routes.forEach { route ->
checkRouteHealth(route)
}
logger.debug("网关健康检查完成,当前路由数量: $routeCount")
} catch (e: Exception) {
logger.error("网关健康检查失败", e)
// 发送告警
sendAlert("网关健康检查失败: ${e.message}")
}
}
private fun getGatewayRoutes(): List<RouteInfo> {
return webClient.get()
.uri("/actuator/gateway/routes")
.retrieve()
.bodyToMono(object : ParameterizedTypeReference<List<RouteInfo>>() {})
.block() ?: emptyList()
}
private fun checkRouteHealth(route: RouteInfo) {
// 检查特定路由的健康状态
// 可以通过调用目标服务的健康检查端点
// ...
}
private fun sendAlert(message: String) {
// 实现告警逻辑(如发送到Slack、钉钉等)
logger.warn("发送告警: $message")
}
data class RouteInfo(
val route_id: String,
val uri: String,
val order: Int
)
}java
@Service
public class GatewayMonitoringService {
private final WebClient webClient;
private final MeterRegistry meterRegistry;
private static final Logger logger = LoggerFactory.getLogger(GatewayMonitoringService.class);
public GatewayMonitoringService(WebClient webClient, MeterRegistry meterRegistry) {
this.webClient = webClient;
this.meterRegistry = meterRegistry;
}
/**
* 定期检查网关健康状态
*/
@Scheduled(fixedRate = 30000) // 每30秒检查一次
public void checkGatewayHealth() {
try {
List<RouteInfo> routes = getGatewayRoutes();
int routeCount = routes.size();
// 记录路由数量指标
meterRegistry.gauge("gateway.routes.count", routeCount);
// 检查路由健康状态
routes.forEach(this::checkRouteHealth);
logger.debug("网关健康检查完成,当前路由数量: {}", routeCount);
} catch (Exception e) {
logger.error("网关健康检查失败", e);
// 发送告警
sendAlert("网关健康检查失败: " + e.getMessage());
}
}
private List<RouteInfo> getGatewayRoutes() {
return webClient.get()
.uri("/actuator/gateway/routes")
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<RouteInfo>>() {})
.block();
}
private void checkRouteHealth(RouteInfo route) {
// 检查特定路由的健康状态
// 可以通过调用目标服务的健康检查端点
// ...
}
private void sendAlert(String message) {
// 实现告警逻辑(如发送到Slack、钉钉等)
logger.warn("发送告警: {}", message);
}
public static class RouteInfo {
private String route_id;
private String uri;
private int order;
// getters and setters
public String getRoute_id() { return route_id; }
public void setRoute_id(String route_id) { this.route_id = route_id; }
public String getUri() { return uri; }
public void setUri(String uri) { this.uri = uri; }
public int getOrder() { return order; }
public void setOrder(int order) { this.order = order; }
}
}端点总览
| 端点 | HTTP 方法 | 描述 | 应用场景 |
|---|---|---|---|
globalfilters | GET | 显示应用于所有路由的全局过滤器列表 | 调试过滤器执行顺序 |
routefilters | GET | 显示应用于特定路由的 GatewayFilter 工厂列表 | 了解可用的过滤器类型 |
refresh | POST | 清除路由缓存 | 配置更新后刷新路由 |
routes | GET | 显示网关中定义的路由列表 | 查看当前所有路由配置 |
routes | POST | 批量创建多个路由定义 | 批量部署新服务 |
routes/{id} | GET | 显示特定路由的信息 | 故障排查特定路由 |
routes/{id} | POST | 向网关添加新路由 | 动态添加新服务路由 |
routes/{id} | DELETE | 从网关删除现有路由 | 下线服务时清理路由 |
最佳实践
TIP
运维建议
- 在生产环境中,建议为 Actuator 端点配置独立的端口和安全认证
- 定期监控路由数量和配置变化,及时发现异常
- 在自动化部署流程中集成路由管理 API,实现服务的自动接入和下线
WARNING
安全注意事项
- 网关管理端点具有很高的权限,必须严格控制访问权限
- 避免在公网暴露管理端点,建议通过 VPN 或内网访问
- 定期审计管理端点的访问日志
CAUTION
操作风险
- 删除路由操作不可逆,删除前务必确认影响范围
- 批量操作时,如果某个路由配置错误,可能影响整个操作的成功
- 刷新路由缓存时,可能短暂影响正在处理的请求
通过 Spring Cloud Gateway 的 Actuator API,我们可以实现网关的可观测性和动态管理,这对于构建稳定、可靠的微服务架构至关重要。合理使用这些 API 可以大大提升系统的运维效率和故障处理能力。