You've already forked FrameTour-BE
refactor(integration): 重构集成服务的降级机制
-移除各服务自定义的降级服务类,统一降级逻辑 - 新增 IntegrationFallbackService作为通用降级服务 - 更新设备和景区服务的降级处理方式 - 优化降级缓存管理,增加统计信息和批量清理功能 - 调整 API 接口,移除扁平化批量更新等相关方法
This commit is contained in:
@@ -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
|
Reference in New Issue
Block a user