微服务项目,临时挂起某个接口怎么实现
·
针对微服务项目中临时挂起接口的需求,以下是几种常见的实现方案:
一、配置中心方案(推荐)
1. 基于Spring Cloud Config/Nacos/Apollo
@Component
@RefreshScope
public class ApiSwitchConfig {
@Value("${api.switch.sampleApi:true}")
private Boolean sampleApiEnabled;
public Boolean isSampleApiEnabled() {
return sampleApiEnabled;
}
}
@RestController
@RequestMapping("/api")
public class SampleController {
@Autowired
private ApiSwitchConfig apiSwitchConfig;
@GetMapping("/sample")
public ResponseEntity<?> sampleApi() {
if (!apiSwitchConfig.isSampleApiEnabled()) {
return ResponseEntity.status(503)
.body(new ApiResponse(503, "接口维护中,请稍后重试"));
}
// 正常业务逻辑
return ResponseEntity.ok("success");
}
}
2. 通过Actuator端点动态更新
# application.yml
management:
endpoints:
web:
exposure:
include: refresh, apiswitch
@RestController
@RequestMapping("/manage")
@RefreshScope
public class ApiSwitchController {
private Map<String, Boolean> apiSwitchMap = new ConcurrentHashMap<>();
@PostMapping("/switch/{apiName}")
public String switchApi(@PathVariable String apiName,
@RequestParam Boolean enabled) {
apiSwitchMap.put(apiName, enabled);
return "接口" + apiName + (enabled ? "已启用" : "已禁用");
}
public boolean isApiEnabled(String apiName) {
return apiSwitchMap.getOrDefault(apiName, true);
}
}
二、API网关方案
1. Spring Cloud Gateway 过滤器
@Component
public class ApiDisableFilter implements GlobalFilter, Ordered {
@Autowired
private ApiSwitchService switchService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String path = exchange.getRequest().getPath().value();
if (switchService.isDisabled(path)) {
exchange.getResponse().setStatusCode(HttpStatus.SERVICE_UNAVAILABLE);
exchange.getResponse().getHeaders()
.add("Content-Type", "application/json");
String body = "{\"code\":503,\"msg\":\"接口维护中\"}";
DataBuffer buffer = exchange.getResponse()
.bufferFactory().wrap(body.getBytes());
return exchange.getResponse().writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
}
2. Nginx配置
location /api/sample {
# 临时返回503
return 503 '{"code": 503, "msg": "服务维护中"}';
# 或者重写到维护页面
# rewrite ^ /maintenance.html break;
# 或者限制特定IP访问
# allow 192.168.1.0/24;
# deny all;
}
三、数据库控制方案
@Service
public class ApiSwitchService {
@Autowired
private ApiSwitchRepository switchRepository;
// 接口开关缓存
private Cache<String, Boolean> apiSwitchCache = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS)
.build();
public boolean isApiEnabled(String apiPath) {
try {
return apiSwitchCache.get(apiPath, () -> {
ApiSwitchConfig config = switchRepository.findByApiPath(apiPath);
return config == null || config.isEnabled();
});
} catch (Exception e) {
return true; // 降级处理
}
}
@Scheduled(fixedDelay = 30000) // 30秒同步一次
public void syncApiSwitch() {
apiSwitchCache.invalidateAll();
}
}
@Entity
@Table(name = "api_switch_config")
public class ApiSwitchConfig {
@Id
private Long id;
private String apiPath;
private Boolean enabled = true;
private String remark;
private Date disableStartTime;
private Date disableEndTime;
}
四、AOP切面方案
@Aspect
@Component
public class ApiSwitchAspect {
@Autowired
private ApiSwitchService apiSwitchService;
@Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
public void apiOperation() {}
@Around("apiOperation()")
public Object aroundApi(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String apiPath = getApiPath(signature.getMethod());
if (!apiSwitchService.isApiEnabled(apiPath)) {
throw new ApiDisabledException("接口暂时不可用");
}
return joinPoint.proceed();
}
private String getApiPath(Method method) {
RequestMapping classMapping = method.getDeclaringClass()
.getAnnotation(RequestMapping.class);
RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);
return (classMapping.value()[0] + methodMapping.value()[0])
.replace("//", "/");
}
}
五、运维层面方案
1. Kubernetes Pod标签选择
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
version: v1.0
# 通过修改标签临时摘除流量
# enabled: "false"
template:
metadata:
labels:
app: user-service
version: v1.0
enabled: "true"
2. Istio流量管理
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: user-service-route
spec:
hosts:
- user-service
http:
- match:
- uri:
prefix: /api/sample
fault:
abort:
percentage:
value: 100.0
httpStatus: 503
六、综合管理平台方案
@RestController
@RequestMapping("/admin/api-switch")
public class ApiSwitchAdminController {
@PostMapping("/disable")
public Result disableApi(@RequestBody DisableApiRequest request) {
// 1. 更新数据库
apiSwitchService.disableApi(request.getApiPath(),
request.getReason(),
request.getEndTime());
// 2. 通知配置中心刷新
configService.publishConfig("API_SWITCH", buildConfig());
// 3. 刷新网关路由
gatewayService.refreshRoutes();
// 4. 记录操作日志
logService.logOperation("disable_api", request);
// 5. 发送通知
notifyService.sendMaintenanceNotice(request);
return Result.success();
}
@Data
public static class DisableApiRequest {
private String apiPath;
private String reason;
private Date endTime;
private String operator;
private List<String> notifyChannels; // 通知渠道
}
}
选择建议
-
快速临时关闭:使用API网关或Nginx配置
-
精确控制:使用配置中心 + 应用内检查
-
长期维护:数据库方案 + 管理平台
-
云原生环境:Kubernetes + Istio
-
需要审计:数据库方案 + 操作日志
最佳实践
-
提供友好的维护页面
-
设置合理的超时时间
-
支持灰度恢复
-
保留操作日志
-
多渠道通知(钉钉、邮件、短信)
-
自动恢复机制(避免忘记开启)
更多推荐
所有评论(0)