refactor(integration): 重构集成服务的降级机制

-移除各服务自定义的降级服务类,统一降级逻辑
- 新增 IntegrationFallbackService作为通用降级服务
- 更新设备和景区服务的降级处理方式
- 优化降级缓存管理,增加统计信息和批量清理功能
- 调整 API 接口,移除扁平化批量更新等相关方法
This commit is contained in:
2025-09-02 12:24:55 +08:00
parent d35a1facbd
commit 8c8a6baa5e
13 changed files with 757 additions and 260 deletions

View File

@@ -17,6 +17,7 @@ The integration package (`com.ycwl.basic.integration`) is responsible for extern
- **IntegrationException**: Standardized exception for integration failures
- **CommonResponse/PageResponse**: Standard response wrappers for external service calls
- **ConfigValueUtil**: Utility for handling configuration values
- **IntegrationFallbackService**: Universal fallback service for handling integration failures
#### Service-Specific Integrations
Currently implemented:
@@ -35,6 +36,91 @@ service/
└── example/ # Usage examples
```
## Integration Fallback Mechanism
### Overview
The integration package includes a comprehensive fallback mechanism that provides automatic degradation when external microservices are unavailable or return errors. This mechanism ensures system resilience and maintains service availability even when dependencies fail.
### Core Components
#### IntegrationFallbackService
Universal fallback service that handles failure degradation for all microservice integrations:
**Key Features:**
- **Automatic Fallback**: Transparently handles service failures and returns cached results
- **Configurable TTL**: Service-specific cache TTL configuration (default: 7 days)
- **Cache Management**: Comprehensive cache statistics, cleanup, and monitoring
- **Service Isolation**: Per-service cache namespacing and configuration
- **Operation Types**: Supports both query operations (return cached data) and mutation operations (ignore failures with history)
**Core Methods:**
```java
// Query operations with fallback
<T> T executeWithFallback(String serviceName, String cacheKey, Supplier<T> operation, Class<T> resultClass)
// Mutation operations with fallback
void executeWithFallback(String serviceName, String cacheKey, Runnable operation)
// Cache management
boolean hasFallbackCache(String serviceName, String cacheKey)
void clearFallbackCache(String serviceName, String cacheKey)
void clearAllFallbackCache(String serviceName)
FallbackCacheStats getFallbackCacheStats(String serviceName)
```
### Fallback Strategy
#### Query Operations (GET methods) - WITH FALLBACK
1. **Normal Execution**: Execute the primary operation
2. **Success Handling**: Store successful result in fallback cache for future degradation
3. **Failure Handling**: On failure, attempt to retrieve cached result from previous success
4. **Final Fallback**: If no cached result exists, propagate the original exception
#### Mutation Operations (PUT/POST/DELETE methods) - NO FALLBACK
1. **Direct Execution**: Execute the primary operation directly without fallback
2. **Success Handling**: Operation completes successfully
3. **Failure Handling**: Immediately propagate the original exception to caller
4. **Rationale**: Users need to know if their create/update/delete operations truly succeeded or failed
### Configuration
#### Properties Structure
```yaml
integration:
fallback:
enabled: true # Global fallback switch
cachePrefix: "integration:fallback:" # Global cache prefix
defaultTtlDays: 7 # Default cache TTL in days
# Service-specific configurations
scenic:
enabled: true # Service-specific fallback switch
ttlDays: 10 # Custom TTL for scenic service
cachePrefix: "scenic:fallback:" # Custom cache prefix (optional)
device:
enabled: true
ttlDays: 5 # Custom TTL for device service
```
#### Configuration Priority
1. **Service-specific settings**: Override global defaults when specified
2. **Global defaults**: Used when service-specific settings are not provided
3. **Hardcoded defaults**: Final fallback when no configuration is available
### Cache Key Strategy
Cache keys follow a standardized naming convention:
```
{cachePrefix}{serviceName}:{operationType}:{resourceId}
```
**Examples:**
- `integration:fallback:zt-device:device:1001` - Device info cache
- `integration:fallback:zt-device:device:config:1001` - Device config cache
- `integration:fallback:zt-scenic:scenic:2001` - Scenic info cache
- `integration:fallback:zt-scenic:scenic:flat:config:2001` - Scenic flat config cache
## Scenic Integration (ZT-Scenic Microservice)
### Key Components
@@ -45,8 +131,8 @@ service/
- **DefaultConfigClient**: Default configuration operations
#### Services
- **ScenicIntegrationService**: High-level scenic operations
- **ScenicConfigIntegrationService**: Configuration management
- **ScenicIntegrationService**: High-level scenic operations (with automatic fallback)
- **ScenicConfigIntegrationService**: Configuration management (with automatic fallback)
- **DefaultConfigIntegrationService**: Default configuration handling
#### Configuration
@@ -63,37 +149,74 @@ integration:
### Usage Examples
#### Basic Scenic Operations
#### Basic Scenic Operations (with Automatic Fallback)
```java
@Autowired
private ScenicIntegrationService scenicService;
// Get scenic with configuration
// Get scenic with configuration (automatically falls back to cache on failure)
ScenicV2WithConfigDTO scenic = scenicService.getScenicWithConfig(scenicId);
// Create new scenic
// Get scenic basic info (automatically falls back to cache on failure)
ScenicV2DTO scenicInfo = scenicService.getScenic(scenicId);
// Get flat configuration (automatically falls back to cache on failure)
Map<String, Object> config = scenicService.getScenicFlatConfig(scenicId);
// Create new scenic (direct operation, fails immediately on error)
CreateScenicRequest request = new CreateScenicRequest();
request.setName("Test Scenic");
ScenicV2DTO result = scenicService.createScenic(request);
// Filter scenics
// Update scenic (direct operation, fails immediately on error)
UpdateScenicRequest updateRequest = new UpdateScenicRequest();
updateRequest.setName("Updated Scenic");
ScenicV2DTO updated = scenicService.updateScenic(scenicId, updateRequest);
// Filter scenics (no fallback for complex queries)
ScenicFilterRequest filterRequest = new ScenicFilterRequest();
// configure filters...
ScenicFilterPageResponse response = scenicService.filterScenics(filterRequest);
```
#### Configuration Management
#### Configuration Management (with Automatic Fallback)
```java
@Autowired
private ScenicConfigIntegrationService configService;
// Get flat configuration
Map<String, Object> config = scenicService.getScenicFlatConfig(scenicId);
// Get flat configuration (automatically falls back to cache on failure)
Map<String, Object> config = configService.getFlatConfigs(scenicId);
// Batch update configurations
// Batch update configurations (direct operation, fails immediately on error)
BatchConfigRequest batchRequest = new BatchConfigRequest();
// configure batch updates...
configService.batchUpdateConfigs(scenicId, batchRequest);
BatchUpdateResponse result = configService.batchUpdateConfigs(scenicId, batchRequest);
// Batch flat update configurations (direct operation, fails immediately on error)
Map<String, Object> flatUpdates = new HashMap<>();
flatUpdates.put("max_visitors", "5000");
flatUpdates.put("opening_hours", "08:00-18:00");
BatchUpdateResponse flatResult = configService.batchFlatUpdateConfigs(scenicId, flatUpdates);
```
#### Fallback Cache Management for Scenics
```java
@Autowired
private IntegrationFallbackService fallbackService;
// Check fallback cache status
boolean hasScenicCache = fallbackService.hasFallbackCache("zt-scenic", "scenic:2001");
boolean hasConfigCache = fallbackService.hasFallbackCache("zt-scenic", "scenic:flat:configs:2001");
// Get cache statistics
IntegrationFallbackService.FallbackCacheStats stats = fallbackService.getFallbackCacheStats("zt-scenic");
log.info("Scenic fallback cache: {} items, TTL: {} days", stats.getTotalCacheCount(), stats.getFallbackTtlDays());
// Clear specific cache
fallbackService.clearFallbackCache("zt-scenic", "scenic:2001");
// Clear all scenic caches
fallbackService.clearAllFallbackCache("zt-scenic");
```
## Device Integration (ZT-Device Microservice)
@@ -105,8 +228,8 @@ configService.batchUpdateConfigs(scenicId, batchRequest);
- **DeviceConfigV2Client**: Device configuration management
#### Services
- **DeviceIntegrationService**: High-level device operations
- **DeviceConfigIntegrationService**: Device configuration management
- **DeviceIntegrationService**: High-level device operations (with automatic fallback)
- **DeviceConfigIntegrationService**: Device configuration management (with automatic fallback)
#### Configuration
```yaml
@@ -122,52 +245,56 @@ integration:
### Usage Examples
#### Basic Device Operations
#### Basic Device Operations (with Automatic Fallback)
```java
@Autowired
private DeviceIntegrationService deviceService;
// Create IPC camera device
// Create IPC camera device (operation tracked for future fallback)
DeviceV2DTO ipcDevice = deviceService.createIpcDevice("前门摄像头", "CAM001", scenicId);
// Get device with configuration
// Get device with configuration (automatically falls back to cache on failure)
DeviceV2WithConfigDTO device = deviceService.getDeviceWithConfig(deviceId);
// Get device by number
// Get device by number (automatically falls back to cache on failure)
DeviceV2DTO deviceByNo = deviceService.getDeviceByNo("CAM001");
// List scenic devices
// Get basic device info (automatically falls back to cache on failure)
DeviceV2DTO basicDevice = deviceService.getDevice(deviceId);
// List scenic devices (no fallback for list operations)
DeviceV2ListResponse deviceList = deviceService.getScenicIpcDevices(scenicId, 1, 10);
// Enable/disable device
// Enable/disable device (direct operation, fails immediately on error)
deviceService.enableDevice(deviceId);
deviceService.disableDevice(deviceId);
// Update device (direct operation, fails immediately on error)
UpdateDeviceRequest updateRequest = new UpdateDeviceRequest();
updateRequest.setName("更新后的摄像头");
deviceService.updateDevice(deviceId, updateRequest);
```
#### Device Configuration Management
#### Device Configuration Management (with Automatic Fallback)
```java
@Autowired
private DeviceConfigIntegrationService configService;
// Configure camera basic parameters
configService.configureCameraBasicParams(deviceId, "192.168.1.100", "1920x1080", 30, "RTSP");
// Get device configurations (with fallback)
List<DeviceConfigV2DTO> configs = configService.getDeviceConfigs(deviceId);
// Configure camera with authentication
configService.configureCameraFullParams(deviceId, "192.168.1.100", "1920x1080", 30, "RTSP", "admin", "password");
// Set specific configuration
configService.setDeviceIpAddress(deviceId, "192.168.1.101");
configService.setDeviceResolution(deviceId, "2560x1440");
configService.setDeviceFramerate(deviceId, 60);
// Get flat configuration
// Get flat configuration (automatically falls back to cache on failure)
Map<String, Object> config = configService.getDeviceFlatConfig(deviceId);
// Batch update configurations (simple way)
Map<String, Object> batchConfigs = new HashMap<>();
batchConfigs.put("brightness", "50");
batchConfigs.put("contrast", "80");
configService.batchFlatUpdateDeviceConfig(deviceId, batchConfigs);
// Get flat configuration by device number (with fallback)
Map<String, Object> configByNo = configService.getDeviceFlatConfigByNo("CAM001");
// Batch update configurations (direct operation, fails immediately on error)
BatchDeviceConfigRequest batchRequest = configService.createBatchConfigBuilder()
.addConfig("brightness", "50")
.addConfig("contrast", "80")
.build();
configService.batchUpdateDeviceConfig(deviceId, batchRequest);
// New batch configuration API with detailed results
BatchDeviceConfigRequest request = configService.createBatchConfigBuilder()
@@ -189,20 +316,32 @@ if (result.getFailed() > 0) {
#### Device Management Patterns
```java
// Create and configure camera in one operation
// Create and configure camera in one operation (both operations direct, no fallback)
DeviceV2DTO camera = deviceService.createIpcDevice("摄像头1", "CAM001", scenicId);
configService.configureCameraFullParams(camera.getId(), "192.168.1.100", "1920x1080", 30, "RTSP", "admin", "password");
// Use batch configuration to set camera parameters (direct operation)
BatchDeviceConfigRequest cameraConfig = configService.createBatchConfigBuilder()
.addConfig("ip_address", "192.168.1.100")
.addConfig("resolution", "1920x1080")
.addConfig("framerate", "30")
.addConfig("protocol", "RTSP")
.addConfig("username", "admin")
.addConfig("password", "password")
.build();
configService.batchUpdateDeviceConfig(camera.getId(), cameraConfig);
// Get scenic camera status
DeviceV2WithConfigListResponse camerasWithConfig =
deviceService.listDevicesWithConfig(1, 100, null, null, "IPC", 1, scenicId);
// Batch update camera resolution
// Batch update camera resolution (direct operations, no fallback)
for (DeviceV2WithConfigDTO device : camerasWithConfig.getList()) {
configService.setDeviceResolution(device.getId(), "2560x1440");
BatchDeviceConfigRequest resolutionUpdate = configService.createBatchConfigBuilder()
.addConfig("resolution", "2560x1440")
.build();
configService.batchUpdateDeviceConfig(device.getId(), resolutionUpdate);
}
// Monitor device configuration completeness
// Monitor device configuration completeness (with automatic fallback)
for (DeviceV2DTO device : activeDevices.getList()) {
Map<String, Object> config = configService.getDeviceFlatConfig(device.getId());
boolean hasIpConfig = config.containsKey("ip_address");
@@ -210,6 +349,26 @@ for (DeviceV2DTO device : activeDevices.getList()) {
}
```
#### Fallback Cache Management for Devices
```java
@Autowired
private IntegrationFallbackService fallbackService;
// Check fallback cache status
boolean hasDeviceCache = fallbackService.hasFallbackCache("zt-device", "device:1001");
boolean hasConfigCache = fallbackService.hasFallbackCache("zt-device", "device:flat:config:1001");
// Get cache statistics
IntegrationFallbackService.FallbackCacheStats stats = fallbackService.getFallbackCacheStats("zt-device");
log.info("Device fallback cache: {} items, TTL: {} days", stats.getTotalCacheCount(), stats.getFallbackTtlDays());
// Clear specific cache
fallbackService.clearFallbackCache("zt-device", "device:1001");
// Clear all device caches
fallbackService.clearAllFallbackCache("zt-device");
```
### Enhanced Batch Configuration API
Device Integration now supports an enhanced batch configuration API that provides detailed processing results and supports default configuration rules.
@@ -359,6 +518,24 @@ Automatically converts Feign errors to IntegrationException:
### Properties Structure
```yaml
integration:
# Fallback configuration
fallback:
enabled: true # Global fallback switch
cachePrefix: "integration:fallback:" # Global cache prefix
defaultTtlDays: 7 # Default cache TTL in days
# Service-specific fallback configurations
scenic:
enabled: true # Enable fallback for scenic service
ttlDays: 10 # Custom TTL for scenic (longer due to stable data)
# cachePrefix: "scenic:fallback:" # Optional custom prefix
device:
enabled: true # Enable fallback for device service
ttlDays: 5 # Custom TTL for device (shorter due to dynamic data)
# cachePrefix: "device:fallback:" # Optional custom prefix
# Service configurations
scenic:
enabled: true
serviceName: zt-scenic
@@ -449,10 +626,23 @@ logging:
- Provide meaningful error messages for business context
- Include service name in IntegrationException for debugging
### Fallback Strategy Best Practices
- **Query operations only**: Only apply fallback to GET operations (data retrieval)
- **No fallback for mutations**: CREATE/UPDATE/DELETE operations should fail immediately to provide clear feedback
- **Cache key design**: Use clear, hierarchical cache keys for easy identification and cleanup
- **TTL management**: Set appropriate TTL based on data freshness requirements
- **Monitoring**: Regularly check fallback cache statistics and cleanup stale entries
- **Service isolation**: Configure service-specific fallback settings based on reliability needs
- **Error transparency**: Let users know exactly when their modification operations fail
### Configuration
- Use environment-specific configuration profiles
- Set appropriate timeouts based on service characteristics
- Enable retries only when safe (idempotent operations)
- Configure fallback TTL based on business requirements:
- **Critical data**: Longer TTL (7-14 days) for essential operations
- **Volatile data**: Shorter TTL (1-3 days) for frequently changing data
- **Configuration data**: Medium TTL (5-7 days) for semi-static settings
### DTOs and Mapping
- Keep DTOs simple and focused on data transfer
@@ -462,4 +652,11 @@ logging:
### Service Layer Design
- Keep integration services focused on external service calls
- Handle response transformation and error conversion
- Avoid business logic in integration services
- Avoid business logic in integration services
- Use fallback service for resilience without changing business logic
### Cache Management Strategies
- **Proactive cleanup**: Monitor cache size and clean up periodically
- **Service-specific management**: Separate cache management per service
- **Debugging support**: Use cache statistics for troubleshooting
- **Configuration validation**: Ensure fallback configuration matches service requirements