系统架构设计的组件和子系统间交互

系统架构设计的组件/子系统间交互:

  1. 定义交互的接口(API、消息格式、协议)。

  2. 明确交互的机制(同步调用、异步消息、事件、共享存储)。

  3. 描述交互的数据流和控制流。

我们继续以智能家居系统为例,详细说明组件/子系统间的交互。我们将使用UML图和多种编程语言示例来展示交互的接口、机制以及数据流和控制流。

一、组件交互概述

在智能家居系统中,组件间的交互可以分为以下几种模式:

  1. 同步调用:如REST API、gRPC,用于需要立即响应的操作。

  2. 异步消息:如消息队列(Kafka、RabbitMQ),用于解耦和异步处理。

  3. 事件驱动:如发布-订阅模式,用于状态变化通知和事件处理。

  4. 共享存储:如数据库、缓存,用于数据共享和状态持久化。

二、同步调用示例:设备控制

2.1 UML时序图

@startuml
participant "移动App" as App
participant "API网关" as Gateway
participant "设备管理服务" as DeviceMgr
participant "Zigbee适配器" as Zigbee
participant "设备" as Device

App -> Gateway: HTTP POST /api/devices/{id}/commands
Gateway -> DeviceMgr: 转发请求(负载均衡)
DeviceMgr -> Zigbee: 发送控制命令(协议转换)
Zigbee -> Device: Zigbee协议命令
Device --> Zigbee: 命令确认
Zigbee --> DeviceMgr: 返回设备响应
DeviceMgr --> Gateway: 返回HTTP 200
Gateway --> App: 返回命令执行结果
@enduml

2.2 接口定义(OpenAPI 3.0)

openapi: 3.0.0
info:
  title: 智能家居设备控制API
  version: 1.0.0

paths:
  /devices/{deviceId}/commands:
    post:
      summary: 发送设备控制命令
      parameters:
        - name: deviceId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DeviceCommand'
      responses:
        '200':
          description: 命令执行成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommandResult'
        '400':
          description: 无效请求
        '404':
          description: 设备未找到
        '500':
          description: 内部服务器错误

components:
  schemas:
    DeviceCommand:
      type: object
      required:
        - command
      properties:
        command:
          type: string
          enum: [turn_on, turn_off, set_brightness, set_color]
        parameters:
          type: object
          additionalProperties: true
    CommandResult:
      type: object
      properties:
        success:
          type: boolean
        message:
          type: string
        timestamp:
          type: string
          format: date-time

2.3 Java实现(Spring Boot)

// 设备控制命令请求体
@Data
public class DeviceCommandRequest {
    private String command;
    private Map<String, Object> parameters;
}

// 设备控制命令结果
@Data
public class CommandResult {
    private boolean success;
    private String message;
    private LocalDateTime timestamp;
    
    public static CommandResult success(String message) {
        CommandResult result = new CommandResult();
        result.setSuccess(true);
        result.setMessage(message);
        result.setTimestamp(LocalDateTime.now());
        return result;
    }
    
    public static CommandResult failure(String message) {
        CommandResult result = new CommandResult();
        result.setSuccess(false);
        result.setMessage(message);
        result.setTimestamp(LocalDateTime.now());
        return result;
    }
}

// 设备控制器
@RestController
@RequestMapping("/api/devices")
public class DeviceController {
    
    @Autowired
    private DeviceCommandService deviceCommandService;
    
    @PostMapping("/{deviceId}/commands")
    public ResponseEntity<CommandResult> sendCommand(
            @PathVariable String deviceId,
            @RequestBody DeviceCommandRequest commandRequest) {
        
        try {
            CommandResult result = deviceCommandService.executeCommand(
                deviceId, 
                commandRequest.getCommand(), 
                commandRequest.getParameters()
            );
            
            return ResponseEntity.ok(result);
        } catch (DeviceNotFoundException e) {
            return ResponseEntity.notFound().build();
        } catch (InvalidCommandException e) {
            return ResponseEntity.badRequest().body(CommandResult.failure(e.getMessage()));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(CommandResult.failure("内部服务器错误"));
        }
    }
}

// 设备命令服务
@Service
public class DeviceCommandService {
    
    @Autowired
    private DeviceRepository deviceRepository;
    
    @Autowired
    private DeviceAdapterFactory adapterFactory;
    
    public CommandResult executeCommand(String deviceId, String command, 
                                        Map<String, Object> parameters) {
        // 查找设备
        Device device = deviceRepository.findById(deviceId)
            .orElseThrow(() -> new DeviceNotFoundException(deviceId));
        
        // 获取设备适配器
        DeviceAdapter adapter = adapterFactory.getAdapter(device.getProtocol());
        
        // 执行命令
        return adapter.executeCommand(device, command, parameters);
    }
}

2.4 Python实现(FastAPI)

# device_controller.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, Dict, Any
from datetime import datetime

app = FastAPI()

class DeviceCommand(BaseModel):
    command: str
    parameters: Optional[Dict[str, Any]] = None

class CommandResult(BaseModel):
    success: bool
    message: str
    timestamp: datetime

class DeviceCommandService:
    async def execute_command(self, device_id: str, command: str, parameters: Dict[str, Any]) -> CommandResult:
        # 实现设备命令执行逻辑
        pass

service = DeviceCommandService()

@app.post("/devices/{device_id}/commands")
async def send_command(device_id: str, command: DeviceCommand) -> CommandResult:
    try:
        result = await service.execute_command(
            device_id, 
            command.command, 
            command.parameters or {}
        )
        return result
    except DeviceNotFoundException:
        raise HTTPException(status_code=404, detail="Device not found")
    except InvalidCommandException as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception:
        raise HTTPException(status_code=500, detail="Internal server error")

三、异步消息示例:设备状态更新

3.1 UML时序图

@startuml
participant "设备" as Device
participant "Zigbee适配器" as Zigbee
participant "消息队列" as MQ
participant "设备管理服务" as DeviceMgr
participant "场景引擎服务" as SceneEngine
participant "能源管理服务" as EnergyMgr

Device -> Zigbee: 状态更新(Zigbee协议)
Zigbee -> MQ: 发布设备状态事件
MQ -> DeviceMgr: 消费事件,更新设备状态
MQ -> SceneEngine: 消费事件,触发场景规则
MQ -> EnergyMgr: 消费事件,记录能耗数据
@enduml

3.2 消息格式定义(JSON Schema)

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "设备状态事件",
  "type": "object",
  "properties": {
    "eventId": {
      "type": "string",
      "format": "uuid",
      "description": "事件唯一标识"
    },
    "eventType": {
      "type": "string",
      "enum": ["DEVICE_STATUS_CHANGED"],
      "description": "事件类型"
    },
    "deviceId": {
      "type": "string",
      "description": "设备ID"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "description": "事件发生时间"
    },
    "payload": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string",
          "description": "设备状态"
        },
        "attributes": {
          "type": "object",
          "additionalProperties": true,
          "description": "设备属性"
        }
      },
      "required": ["status"]
    }
  },
  "required": ["eventId", "eventType", "deviceId", "timestamp", "payload"]
}

3.3 Java实现(Spring Cloud Stream + Kafka)

// 设备状态事件
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DeviceStatusEvent {
    private String eventId;
    private String eventType = "DEVICE_STATUS_CHANGED";
    private String deviceId;
    private LocalDateTime timestamp;
    private DeviceStatusPayload payload;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class DeviceStatusPayload {
        private String status;
        private Map<String, Object> attributes;
    }
}

// 事件生产者(Zigbee适配器)
@Component
public class DeviceEventProducer {
    
    @Autowired
    private StreamBridge streamBridge;
    
    public void publishStatusChanged(String deviceId, String status, 
                                     Map<String, Object> attributes) {
        DeviceStatusEvent event = new DeviceStatusEvent(
            UUID.randomUUID().toString(),
            "DEVICE_STATUS_CHANGED",
            deviceId,
            LocalDateTime.now(),
            new DeviceStatusPayload(status, attributes)
        );
        
        streamBridge.send("deviceStatusChanged-out-0", event);
        log.info("Published device status event: {}", event);
    }
}

// 事件消费者(设备管理服务)
@Component
@Slf4j
public class DeviceStatusConsumer {
    
    @Autowired
    private DeviceService deviceService;
    
    @Bean
    public Consumer<DeviceStatusEvent> handleDeviceStatusChanged() {
        return event -> {
            log.info("Received device status event: {}", event);
            
            // 更新设备状态
            deviceService.updateDeviceStatus(
                event.getDeviceId(),
                event.getPayload().getStatus(),
                event.getPayload().getAttributes()
            );
        };
    }
}

// 事件消费者(场景引擎服务)
@Component
@Slf4j
public class SceneTriggerConsumer {
    
    @Autowired
    private SceneEngineService sceneEngineService;
    
    @Bean
    public Consumer<DeviceStatusEvent> handleDeviceStatusForScenes() {
        return event -> {
            log.info("Checking scenes for device event: {}", event);
            
            // 检查是否有场景被触发
            sceneEngineService.evaluateScenesForEvent(event);
        };
    }
}

3.4 Python实现(Kafka)

# event_producer.py
import json
from datetime import datetime
from uuid import uuid4
from kafka import KafkaProducer

class DeviceEventProducer:
    def __init__(self, bootstrap_servers):
        self.producer = KafkaProducer(
            bootstrap_servers=bootstrap_servers,
            value_serializer=lambda v: json.dumps(v).encode('utf-8')
        )
    
    def publish_status_changed(self, device_id, status, attributes):
        event = {
            "eventId": str(uuid4()),
            "eventType": "DEVICE_STATUS_CHANGED",
            "deviceId": device_id,
            "timestamp": datetime.now().isoformat(),
            "payload": {
                "status": status,
                "attributes": attributes
            }
        }
        
        self.producer.send('device-status-events', event)
        self.producer.flush()
        print(f"Published device status event: {event}")

# event_consumer.py
from kafka import KafkaConsumer
import json

class DeviceStatusConsumer:
    def __init__(self, bootstrap_servers):
        self.consumer = KafkaConsumer(
            'device-status-events',
            bootstrap_servers=bootstrap_servers,
            value_deserializer=lambda v: json.loads(v.decode('utf-8')),
            group_id='device-service'
        )
    
    def start_consuming(self):
        for message in self.consumer:
            event = message.value
            print(f"Received device status event: {event}")
            
            # 处理事件
            self.handle_event(event)
    
    def handle_event(self, event):
        # 更新设备状态逻辑
        pass

# 启动消费者
consumer = DeviceStatusConsumer(['localhost:9092'])
consumer.start_consuming()

四、事件驱动示例:场景自动化

4.1 UML状态图

@startuml
state SceneAutomation {
    [*] -> Idle : 初始化
    Idle -> Evaluating : 触发事件
    Evaluating -> Executing : 条件满足
    Evaluating -> Idle : 条件不满足
    Executing -> Idle : 执行完成
    Executing -> Failed : 执行失败
    Failed -> Idle : 重试或放弃
}
@enduml

4.2 事件格式定义(CloudEvents)

{
  "specversion": "1.0",
  "type": "com.smarthome.scene.triggered",
  "source": "/scene-engine/scene-123",
  "id": "uuid-1234-5678",
  "time": "2024-01-15T12:00:00Z",
  "datacontenttype": "application/json",
  "data": {
    "sceneId": "scene-123",
    "trigger": {
      "type": "DEVICE_EVENT",
      "deviceId": "light-001",
      "event": "status_changed"
    },
    "actions": [
      {
        "type": "DEVICE_CONTROL",
        "deviceId": "outlet-001",
        "command": "turn_on"
      }
    ],
    "executionId": "exec-123456",
    "timestamp": "2024-01-15T12:00:00Z"
  }
}

4.3 C#实现(.NET Core + Azure Event Grid)

// 场景触发事件
public class SceneTriggeredEvent
{
    [JsonPropertyName("specversion")]
    public string SpecVersion { get; set; } = "1.0";
    
    [JsonPropertyName("type")]
    public string Type { get; set; } = "com.smarthome.scene.triggered";
    
    [JsonPropertyName("source")]
    public string Source { get; set; }
    
    [JsonPropertyName("id")]
    public string Id { get; set; }
    
    [JsonPropertyName("time")]
    public DateTimeOffset Time { get; set; }
    
    [JsonPropertyName("datacontenttype")]
    public string DataContentType { get; set; } = "application/json";
    
    [JsonPropertyName("data")]
    public SceneTriggerData Data { get; set; }
}

public class SceneTriggerData
{
    [JsonPropertyName("sceneId")]
    public string SceneId { get; set; }
    
    [JsonPropertyName("trigger")]
    public SceneTrigger Trigger { get; set; }
    
    [JsonPropertyName("actions")]
    public List<SceneAction> Actions { get; set; }
    
    [JsonPropertyName("executionId")]
    public string ExecutionId { get; set; }
    
    [JsonPropertyName("timestamp")]
    public DateTimeOffset Timestamp { get; set; }
}

// 场景引擎服务
public class SceneEngineService
{
    private readonly IEventGridPublisher _eventGridPublisher;
    
    public SceneEngineService(IEventGridPublisher eventGridPublisher)
    {
        _eventGridPublisher = eventGridPublisher;
    }
    
    public async Task TriggerSceneAsync(string sceneId, SceneTrigger trigger, 
                                        List<SceneAction> actions)
    {
        var executionId = Guid.NewGuid().ToString();
        
        var eventData = new SceneTriggeredEvent
        {
            Source = $"/scene-engine/{sceneId}",
            Id = Guid.NewGuid().ToString(),
            Time = DateTimeOffset.UtcNow,
            Data = new SceneTriggerData
            {
                SceneId = sceneId,
                Trigger = trigger,
                Actions = actions,
                ExecutionId = executionId,
                Timestamp = DateTimeOffset.UtcNow
            }
        };
        
        // 发布事件到Event Grid
        await _eventGridPublisher.PublishEventAsync(eventData);
        
        // 执行场景动作
        await ExecuteSceneActionsAsync(actions, executionId);
    }
    
    private async Task ExecuteSceneActionsAsync(List<SceneAction> actions, string executionId)
    {
        foreach (var action in actions)
        {
            try
            {
                await ExecuteActionAsync(action, executionId);
            }
            catch (Exception ex)
            {
                // 记录失败并继续执行其他动作
                await LogActionFailureAsync(action, executionId, ex);
            }
        }
    }
}

// 事件处理器(通知服务)
public class SceneTriggeredEventHandler
{
    private readonly INotificationService _notificationService;
    
    public SceneTriggeredEventHandler(INotificationService notificationService)
    {
        _notificationService = notificationService;
    }
    
    [FunctionName("HandleSceneTriggered")]
    public async Task Run(
        [EventGridTrigger] EventGridEvent eventGridEvent)
    {
        var sceneEvent = eventGridEvent.Data.ToObjectFromJson<SceneTriggeredEvent>();
        
        // 发送场景执行通知
        await _notificationService.SendSceneNotificationAsync(
            sceneEvent.Data.SceneId,
            sceneEvent.Data.ExecutionId,
            sceneEvent.Data.Timestamp
        );
    }
}

五、共享存储示例:设备状态缓存

5.1 UML类图

@startuml
class DeviceCacheService {
    +getDeviceStatus(deviceId: String): DeviceStatus
    +updateDeviceStatus(deviceId: String, status: DeviceStatus): void
    +removeDeviceStatus(deviceId: String): void
}

class RedisCache {
    +get(key: String): Object
    +set(key: String, value: Object, ttl: int): void
    +delete(key: String): void
}

class DeviceStatus {
    -deviceId: String
    -status: String
    -lastUpdated: DateTime
    -attributes: Map<String, Object>
}

DeviceCacheService --> RedisCache : 使用
DeviceCacheService --> DeviceStatus : 管理
@enduml

5.2 Java实现(Spring Boot + Redis)

// 设备状态缓存服务
@Service
public class DeviceCacheService {
    
    private static final String CACHE_PREFIX = "device:status:";
    private static final long CACHE_TTL = 300; // 5分钟
    
    @Autowired
    private RedisTemplate<String, DeviceStatus> redisTemplate;
    
    public DeviceStatus getDeviceStatus(String deviceId) {
        String key = getCacheKey(deviceId);
        return redisTemplate.opsForValue().get(key);
    }
    
    public void updateDeviceStatus(String deviceId, DeviceStatus status) {
        String key = getCacheKey(deviceId);
        redisTemplate.opsForValue().set(key, status, CACHE_TTL, TimeUnit.SECONDS);
    }
    
    public void removeDeviceStatus(String deviceId) {
        String key = getCacheKey(deviceId);
        redisTemplate.delete(key);
    }
    
    public Map<String, DeviceStatus> getBulkStatus(List<String> deviceIds) {
        List<String> keys = deviceIds.stream()
            .map(this::getCacheKey)
            .collect(Collectors.toList());
        
        List<DeviceStatus> statuses = redisTemplate.opsForValue().multiGet(keys);
        
        Map<String, DeviceStatus> result = new HashMap<>();
        for (int i = 0; i < deviceIds.size(); i++) {
            result.put(deviceIds.get(i), statuses.get(i));
        }
        
        return result;
    }
    
    private String getCacheKey(String deviceId) {
        return CACHE_PREFIX + deviceId;
    }
}

// 设备状态
@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash(value = "DeviceStatus", timeToLive = 300)
public class DeviceStatus implements Serializable {
    @Id
    private String deviceId;
    private String status;
    private LocalDateTime lastUpdated;
    private Map<String, Object> attributes;
}

// Redis配置
@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, DeviceStatus> redisTemplate(
            RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, DeviceStatus> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        Jackson2JsonRedisSerializer<DeviceStatus> serializer = 
            new Jackson2JsonRedisSerializer<>(DeviceStatus.class);
        
        template.setValueSerializer(serializer);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        
        return template;
    }
}

5.3 Python实现(Redis)

# device_cache.py
import json
import pickle
from datetime import datetime
from typing import Optional, Dict, Any
import redis

class DeviceStatus:
    def __init__(self, device_id: str, status: str, attributes: Dict[str, Any]):
        self.device_id = device_id
        self.status = status
        self.last_updated = datetime.now()
        self.attributes = attributes
    
    def to_dict(self):
        return {
            'device_id': self.device_id,
            'status': self.status,
            'last_updated': self.last_updated.isoformat(),
            'attributes': self.attributes
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]):
        device_status = cls(
            data['device_id'],
            data['status'],
            data['attributes']
        )
        device_status.last_updated = datetime.fromisoformat(data['last_updated'])
        return device_status

class DeviceCacheService:
    def __init__(self, host='localhost', port=6379, db=0):
        self.redis_client = redis.Redis(host=host, port=port, db=db)
        self.cache_prefix = 'device:status:'
        self.cache_ttl = 300  # 5分钟
    
    def get_device_status(self, device_id: str) -> Optional[DeviceStatus]:
        key = self._get_cache_key(device_id)
        data = self.redis_client.get(key)
        
        if data:
            return DeviceStatus.from_dict(pickle.loads(data))
        return None
    
    def update_device_status(self, device_id: str, status: str, 
                            attributes: Dict[str, Any]):
        device_status = DeviceStatus(device_id, status, attributes)
        key = self._get_cache_key(device_id)
        
        self.redis_client.setex(
            key,
            self.cache_ttl,
            pickle.dumps(device_status.to_dict())
        )
    
    def remove_device_status(self, device_id: str):
        key = self._get_cache_key(device_id)
        self.redis_client.delete(key)
    
    def get_bulk_status(self, device_ids: list) -> Dict[str, Optional[DeviceStatus]]:
        keys = [self._get_cache_key(device_id) for device_id in device_ids]
        data_list = self.redis_client.mget(keys)
        
        result = {}
        for i, data in enumerate(data_list):
            device_id = device_ids[i]
            if data:
                result[device_id] = DeviceStatus.from_dict(pickle.loads(data))
            else:
                result[device_id] = None
        
        return result
    
    def _get_cache_key(self, device_id: str) -> str:
        return f"{self.cache_prefix}{device_id}"

六、交互机制总结

6.1 交互模式对比

交互模式适用场景优点缺点
同步调用需要立即响应的操作,如设备控制实时性强,开发简单耦合度高,可用性受依赖服务影响
异步消息耗时操作、事件通知、日志记录解耦,提高系统吞吐量复杂性高,需要考虑消息顺序和一致性
事件驱动状态变化通知、业务逻辑触发松耦合,易于扩展事件追踪和调试困难
共享存储数据共享、状态缓存、会话管理访问速度快,减少重复计算数据一致性难以保证

6.2 数据流和控制流

在智能家居系统中,典型的数据流和控制流如下:

  1. 设备状态更新流程

    • 控制流:设备 → 适配器 → 消息队列 → 多个消费者

    • 数据流:设备状态数据被多个服务并行处理

  2. 设备控制流程

    • 控制流:客户端 → API网关 → 设备服务 → 适配器 → 设备

    • 数据流:控制命令传递,响应原路返回

  3. 场景自动化流程

    • 控制流:事件触发 → 场景引擎 → 动作执行 → 设备控制

    • 数据流:事件数据 → 规则评估 → 动作命令

6.3 最佳实践

  1. 接口设计

    • 使用标准协议和格式(REST、gRPC、JSON、Protobuf)

    • 提供清晰的API文档(OpenAPI、gRPC Proto)

    • 版本化管理接口

  2. 消息设计

    • 定义统一的消息格式(CloudEvents)

    • 确保消息的幂等性

    • 设计合理的消息分区策略

  3. 错误处理

    • 同步调用:明确的错误码和重试机制

    • 异步消息:死信队列和重试队列

    • 事件驱动:事件溯源和补偿事务

  4. 监控和追踪

    • 分布式追踪(Trace ID)

    • 完善的日志记录

    • 监控指标收集

通过合理的组件交互设计,可以构建出高可用、可扩展、易维护的智能家居系统。

组件/子系统间交互:接口、机制与数据流

下面将通过智能家居系统的完整案例,详细展示组件间交互的核心机制、接口设计、协议定义和数据流控制,并用多种语言实现关键交互模式。

一、交互模式概述与选择框架

1.1 交互模式决策树

组件交互需求
是否需要实时响应?
调用方是否需要立即结果?
异步消息/事件驱动
性能要求高吗?
gRPC/二进制协议
REST/HTTP
需要广播通知吗?
发布-订阅模式
需要持久化保证吗?
消息队列 + 持久化
进程内事件/内存消息

1.2 交互模式对比矩阵

交互模式对比:
  同步调用:
    适用场景: "命令与控制、查询操作、需要立即结果的交互"
    延迟: "毫秒到秒级"
    可靠性: "依赖网络和服务的可用性"
    复杂性: "中等"
    示例: "设备控制、用户认证、实时查询"
  
  异步消息:
    适用场景: "后台处理、批量操作、解耦系统"
    延迟: "秒到分钟级"
    可靠性: "高(消息持久化)"
    复杂性: "高(需要处理消息顺序、幂等性)"
    示例: "日志处理、数据同步、报表生成"
  
  事件驱动:
    适用场景: "状态变更通知、实时处理、复杂事件处理"
    延迟: "毫秒级"
    可靠性: "取决于实现(可持久化事件)"
    复杂性: "高(事件溯源、CQRS)"
    示例: "设备状态变化、用户行为跟踪、系统告警"
  
  共享存储:
    适用场景: "数据共享、缓存、会话状态"
    延迟: "微秒到毫秒级"
    可靠性: "高(支持复制)"
    复杂性: "中等(需要处理并发)"
    示例: "用户会话、设备状态缓存、分布式锁"

二、接口定义与协议设计

2.1 统一接口规范框架

2.1.1 OpenAPI 3.0规范(REST接口)
# openapi.yaml
openapi: 3.0.3
info:
  title: 智能家居系统API
  version: 1.0.0
  description: 智能家居系统组件间REST接口规范

servers:
  - url: https://api.smarthome.example.com/v1
    description: 生产环境
  
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
  
  schemas:
    # 统一响应格式
    ApiResponse:
      type: object
      properties:
        code:
          type: integer
          description: 状态码
        message:
          type: string
          description: 消息描述
        data:
          type: object
          nullable: true
          description: 响应数据
        timestamp:
          type: string
          format: date-time
          description: 响应时间戳
      required: [code, message, timestamp]
    
    # 分页响应
    PaginatedResponse:
      allOf:
        - $ref: '#/components/schemas/ApiResponse'
        - type: object
          properties:
            data:
              type: object
              properties:
                items:
                  type: array
                  description: 数据项列表
                total:
                  type: integer
                  description: 总记录数
                page:
                  type: integer
                  description: 当前页码
                pageSize:
                  type: integer
                  description: 每页大小
              required: [items, total, page, pageSize]
    
    # 错误响应
    ErrorResponse:
      type: object
      properties:
        code:
          type: integer
          description: 错误码
        message:
          type: string
          description: 错误信息
        details:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
                description: 字段名
              message:
                type: string
                description: 字段错误信息
        requestId:
          type: string
          description: 请求ID(用于追踪)
        timestamp:
          type: string
          format: date-time
      required: [code, message, timestamp]
2.1.2 Protocol Buffers规范(gRPC接口)
// device_service.proto
syntax = "proto3";

package smarthome.v1;

import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";

// 设备服务接口定义
service DeviceService {
  // 获取设备信息
  rpc GetDevice(GetDeviceRequest) returns (Device);
  
  // 获取设备列表
  rpc ListDevices(ListDevicesRequest) returns (ListDevicesResponse);
  
  // 创建设备
  rpc CreateDevice(CreateDeviceRequest) returns (Device);
  
  // 更新设备
  rpc UpdateDevice(UpdateDeviceRequest) returns (Device);
  
  // 删除设备
  rpc DeleteDevice(DeleteDeviceRequest) returns (google.protobuf.Empty);
  
  // 执行设备命令
  rpc ExecuteCommand(ExecuteCommandRequest) returns (CommandResult);
  
  // 设备状态流(服务器端流)
  rpc StreamDeviceStatus(StreamDeviceStatusRequest) returns (stream DeviceStatus);
  
  // 批量命令执行(客户端流)
  rpc ExecuteBatchCommands(stream DeviceCommand) returns (BatchCommandResult);
  
  // 双向流:实时命令与状态
  rpc RealTimeControl(stream ClientCommand) returns (stream ServerResponse);
}

// 消息定义
message Device {
  string id = 1;
  string name = 2;
  DeviceType type = 3;
  string manufacturer = 4;
  string model = 5;
  DeviceStatus status = 6;
  map<string, string> attributes = 7;
  google.protobuf.Timestamp created_at = 8;
  google.protobuf.Timestamp updated_at = 9;
}

message DeviceCommand {
  string device_id = 1;
  string command = 2;
  map<string, string> parameters = 3;
  google.protobuf.Timestamp timestamp = 4;
}

message CommandResult {
  bool success = 1;
  string message = 2;
  map<string, string> result_data = 3;
  google.protobuf.Timestamp executed_at = 4;
}

// 枚举定义
enum DeviceType {
  UNKNOWN = 0;
  LIGHT = 1;
  SWITCH = 2;
  SENSOR = 3;
  CAMERA = 4;
  THERMOSTAT = 5;
  DOOR_LOCK = 6;
}

enum DeviceStatus {
  OFFLINE = 0;
  ONLINE = 1;
  ERROR = 2;
  UPDATING = 3;
}

// 错误定义
message ErrorDetail {
  string code = 1;
  string message = 2;
  repeated string details = 3;
}

// 服务端元数据
extend grpc::ServiceOptions {
  string service_version = 50001;
  repeated string required_permissions = 50002;
}
2.1.3 异步消息规范(CloudEvents)
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "CloudEvents Schema for SmartHome",
  "type": "object",
  "properties": {
    "specversion": {
      "type": "string",
      "enum": ["1.0"],
      "description": "CloudEvents规范版本"
    },
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "事件唯一标识符"
    },
    "source": {
      "type": "string",
      "description": "事件源URI,格式:/{service}/{resource}/{id}",
      "pattern": "^/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+$"
    },
    "type": {
      "type": "string",
      "description": "事件类型,格式:com.smarthome.{domain}.{event}",
      "pattern": "^com\\.smarthome\\.[a-z]+\\.([a-z]+\\.)*[a-z]+$"
    },
    "time": {
      "type": "string",
      "format": "date-time",
      "description": "事件发生时间"
    },
    "datacontenttype": {
      "type": "string",
      "enum": ["application/json", "application/avro", "text/plain"],
      "default": "application/json"
    },
    "dataschema": {
      "type": "string",
      "format": "uri",
      "description": "数据模式URI"
    },
    "subject": {
      "type": "string",
      "description": "事件主题,通常是资源ID"
    },
    "data": {
      "type": "object",
      "description": "事件数据",
      "additionalProperties": true
    },
    "extensions": {
      "type": "object",
      "description": "扩展字段",
      "properties": {
        "correlationid": {
          "type": "string",
          "format": "uuid"
        },
        "userid": {
          "type": "string"
        },
        "tenantid": {
          "type": "string"
        },
        "traceparent": {
          "type": "string",
          "description": "W3C Trace Context"
        },
        "tracestate": {
          "type": "string"
        }
      }
    }
  },
  "required": ["specversion", "id", "source", "type", "time", "data"]
}

三、同步调用实现示例

3.1 REST API实现(Java + Spring Boot)

// 统一的REST响应包装器
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    private LocalDateTime timestamp;
    private String requestId;
    
    public static <T> ApiResponse<T> success(T data) {
        return ApiResponse.<T>builder()
            .code(200)
            .message("success")
            .data(data)
            .timestamp(LocalDateTime.now())
            .requestId(MDC.get("requestId"))
            .build();
    }
    
    public static <T> ApiResponse<T> success(T data, String message) {
        return ApiResponse.<T>builder()
            .code(200)
            .message(message)
            .data(data)
            .timestamp(LocalDateTime.now())
            .requestId(MDC.get("requestId"))
            .build();
    }
    
    public static <T> ApiResponse<T> error(int code, String message) {
        return ApiResponse.<T>builder()
            .code(code)
            .message(message)
            .timestamp(LocalDateTime.now())
            .requestId(MDC.get("requestId"))
            .build();
    }
    
    public static <T> ApiResponse<PageResponse<T>> paginated(
            List<T> items, long total, int page, int pageSize) {
        PageResponse<T> pageData = PageResponse.<T>builder()
            .items(items)
            .total(total)
            .page(page)
            .pageSize(pageSize)
            .build();
        
        return success(pageData);
    }
}

// 分页响应
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class PageResponse<T> {
    private List<T> items;
    private long total;
    private int page;
    private int pageSize;
    private int totalPages;
    
    @Builder.Default
    private boolean hasNext = false;
    @Builder.Default
    private boolean hasPrevious = false;
    
    public static <T> PageResponse<T> of(List<T> items, long total, int page, int pageSize) {
        int totalPages = (int) Math.ceil((double) total / pageSize);
        
        return PageResponse.<T>builder()
            .items(items)
            .total(total)
            .page(page)
            .pageSize(pageSize)
            .totalPages(totalPages)
            .hasNext(page < totalPages - 1)
            .hasPrevious(page > 0)
            .build();
    }
}

// 统一的异常处理器
@ControllerAdvice
public class GlobalExceptionHandler {
    
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ApiResponse<Object>> handleException(Exception ex, HttpServletRequest request) {
        String requestId = MDC.get("requestId");
        
        if (ex instanceof BusinessException) {
            BusinessException businessEx = (BusinessException) ex;
            log.warn("Business exception occurred: {}", businessEx.getMessage());
            
            ApiResponse<Object> response = ApiResponse.error(
                businessEx.getCode(),
                businessEx.getMessage()
            );
            
            return ResponseEntity.status(businessEx.getHttpStatus())
                .body(response);
        } else if (ex instanceof ValidationException) {
            ValidationException validationEx = (ValidationException) ex;
            log.warn("Validation exception: {}", validationEx.getMessage());
            
            ErrorDetail errorDetail = new ErrorDetail(
                "VALIDATION_ERROR",
                validationEx.getMessage(),
                validationEx.getErrors()
            );
            
            ApiResponse<Object> response = ApiResponse.error(
                400,
                "Validation failed"
            );
            response.setData(errorDetail);
            
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(response);
        } else if (ex instanceof ResourceNotFoundException) {
            log.warn("Resource not found: {}", ex.getMessage());
            
            ApiResponse<Object> response = ApiResponse.error(
                404,
                ex.getMessage()
            );
            
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(response);
        } else {
            log.error("Unexpected error occurred", ex);
            
            // 生产环境隐藏详细错误信息
            String message = isProduction() ? "Internal server error" : ex.getMessage();
            
            ApiResponse<Object> response = ApiResponse.error(
                500,
                message
            );
            
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(response);
        }
    }
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ApiResponse<Object>> handleValidationExceptions(
            MethodArgumentNotValidException ex) {
        
        List<String> errors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .collect(Collectors.toList());
        
        ErrorDetail errorDetail = new ErrorDetail(
            "VALIDATION_ERROR",
            "Request validation failed",
            errors
        );
        
        ApiResponse<Object> response = ApiResponse.error(400, "Validation failed");
        response.setData(errorDetail);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
            .body(response);
    }
}

// Feign客户端示例(服务间调用)
@FeignClient(
    name = "device-service",
    url = "${service.device.url:http://localhost:8081}",
    configuration = FeignClientConfig.class
)
public interface DeviceServiceClient {
    
    @GetMapping("/api/v1/devices/{deviceId}")
    ApiResponse<DeviceDTO> getDevice(@PathVariable("deviceId") String deviceId);
    
    @PostMapping("/api/v1/devices/{deviceId}/commands")
    ApiResponse<CommandResultDTO> executeCommand(
        @PathVariable("deviceId") String deviceId,
        @RequestBody DeviceCommandRequest command
    );
    
    @GetMapping("/api/v1/devices")
    ApiResponse<PageResponse<DeviceDTO>> listDevices(
        @RequestParam(value = "page", defaultValue = "0") int page,
        @RequestParam(value = "size", defaultValue = "20") int size,
        @RequestParam(value = "type", required = false) String type,
        @RequestParam(value = "status", required = false) String status
    );
}

// Feign配置
@Configuration
public class FeignClientConfig {
    
    @Bean
    public RequestInterceptor requestInterceptor() {
        return template -> {
            // 添加认证令牌
            String token = SecurityContextHolder.getContext()
                .getAuthentication()
                .getCredentials()
                .toString();
            template.header("Authorization", "Bearer " + token);
            
            // 添加请求ID
            String requestId = MDC.get("requestId");
            if (requestId != null) {
                template.header("X-Request-ID", requestId);
            }
            
            // 添加跟踪信息
            String traceId = MDC.get("traceId");
            if (traceId != null) {
                template.header("X-Trace-ID", traceId);
            }
        };
    }
    
    @Bean
    public Retryer retryer() {
        // 自定义重试策略
        return new Retryer.Default(100, 1000, 3);
    }
    
    @Bean
    public ErrorDecoder errorDecoder() {
        return (methodKey, response) -> {
            if (response.status() == 404) {
                return new ResourceNotFoundException("Resource not found");
            } else if (response.status() == 429) {
                return new RateLimitExceededException("Rate limit exceeded");
            } else if (response.status() >= 500) {
                return new ServiceUnavailableException("Service unavailable");
            } else {
                return FeignException.errorStatus(methodKey, response);
            }
        };
    }
}

// 使用Feign客户端的服务
@Service
public class SceneEngineService {
    
    @Autowired
    private DeviceServiceClient deviceServiceClient;
    
    @Autowired
    private CircuitBreakerFactory circuitBreakerFactory;
    
    public DeviceDTO getDeviceWithCircuitBreaker(String deviceId) {
        CircuitBreaker circuitBreaker = circuitBreakerFactory.create("device-service");
        
        return circuitBreaker.run(
            () -> {
                ApiResponse<DeviceDTO> response = deviceServiceClient.getDevice(deviceId);
                if (response.getCode() == 200) {
                    return response.getData();
                } else {
                    throw new ServiceException("Failed to get device: " + response.getMessage());
                }
            },
            throwable -> {
                // 降级逻辑
                return getCachedDevice(deviceId);
            }
        );
    }
    
    public CommandResultDTO executeSceneCommand(SceneCommand command) {
        List<CompletableFuture<CommandResultDTO>> futures = command.getDeviceCommands()
            .stream()
            .map(deviceCommand -> CompletableFuture.supplyAsync(() -> {
                try {
                    ApiResponse<CommandResultDTO> response = deviceServiceClient
                        .executeCommand(deviceCommand.getDeviceId(), deviceCommand);
                    
                    if (response.getCode() == 200) {
                        return response.getData();
                    } else {
                        throw new CommandExecutionException(
                            "Failed to execute command: " + response.getMessage()
                        );
                    }
                } catch (Exception e) {
                    throw new CommandExecutionException(
                        "Failed to execute command on device " + deviceCommand.getDeviceId(),
                        e
                    );
                }
            }))
            .collect(Collectors.toList());
        
        // 等待所有命令完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
            futures.toArray(new CompletableFuture[0])
        );
        
        try {
            allFutures.get(30, TimeUnit.SECONDS);
            
            // 收集结果
            List<CommandResultDTO> results = futures.stream()
                .map(CompletableFuture::join)
                .collect(Collectors.toList());
            
            return aggregateResults(results);
        } catch (TimeoutException e) {
            throw new CommandTimeoutException("Scene command execution timed out");
        } catch (Exception e) {
            throw new CommandExecutionException("Failed to execute scene command", e);
        }
    }
}

3.2 gRPC实现(Python)

# device_service_grpc.py
import grpc
from concurrent import futures
import time
from typing import Dict, List, Optional
from datetime import datetime
import json
import logging

from google.protobuf import timestamp_pb2
from google.protobuf.empty_pb2 import Empty

import device_service_pb2 as pb2
import device_service_pb2_grpc as pb2_grpc

logger = logging.getLogger(__name__)

class DeviceService(pb2_grpc.DeviceServiceServicer):
    """gRPC设备服务实现"""
    
    def __init__(self, device_manager):
        self.device_manager = device_manager
        self._active_streams: Dict[str, grpc.ServerStream] = {}
    
    def GetDevice(self, request, context):
        """获取单个设备信息"""
        try:
            device = self.device_manager.get_device(request.device_id)
            
            # 转换为Protobuf消息
            return self._device_to_proto(device)
            
        except DeviceNotFoundError as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details(str(e))
            return pb2.Device()
        except Exception as e:
            logger.error(f"Error getting device {request.device_id}: {e}")
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("Internal server error")
            return pb2.Device()
    
    def ListDevices(self, request, context):
        """获取设备列表"""
        try:
            # 解析过滤条件
            filters = {}
            if request.type:
                filters['type'] = pb2.DeviceType.Name(request.type)
            if request.status:
                filters['status'] = pb2.DeviceStatus.Name(request.status)
            
            # 获取设备列表
            devices, total = self.device_manager.list_devices(
                page=request.page,
                page_size=request.page_size,
                filters=filters
            )
            
            # 构建响应
            response = pb2.ListDevicesResponse()
            response.total = total
            response.page = request.page
            response.page_size = request.page_size
            
            for device in devices:
                response.devices.append(self._device_to_proto(device))
            
            return response
            
        except Exception as e:
            logger.error(f"Error listing devices: {e}")
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("Internal server error")
            return pb2.ListDevicesResponse()
    
    def ExecuteCommand(self, request, context):
        """执行设备命令"""
        try:
            # 验证命令参数
            if not request.device_id:
                context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                context.set_details("device_id is required")
                return pb2.CommandResult()
            
            if not request.command:
                context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
                context.set_details("command is required")
                return pb2.CommandResult()
            
            # 执行命令
            result = self.device_manager.execute_command(
                device_id=request.device_id,
                command=request.command,
                parameters=dict(request.parameters)
            )
            
            # 转换为Protobuf响应
            response = pb2.CommandResult()
            response.success = result.success
            response.message = result.message or ""
            
            for key, value in result.result_data.items():
                response.result_data[key] = str(value)
            
            response.executed_at.FromDatetime(datetime.now())
            
            return response
            
        except DeviceNotFoundError as e:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details(str(e))
            return pb2.CommandResult()
        except InvalidCommandError as e:
            context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
            context.set_details(str(e))
            return pb2.CommandResult()
        except Exception as e:
            logger.error(f"Error executing command: {e}")
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("Internal server error")
            return pb2.CommandResult()
    
    def StreamDeviceStatus(self, request, context):
        """流式获取设备状态"""
        device_id = request.device_id
        
        try:
            # 注册流
            self._register_stream(device_id, context)
            
            # 发送初始状态
            device = self.device_manager.get_device(device_id)
            yield self._device_status_to_proto(device)
            
            # 持续监听状态变化
            while not context.is_active():
                try:
                    # 检查状态变化(这里简化实现,实际应该用事件驱动)
                    device = self.device_manager.get_device(device_id)
                    status_update = self._device_status_to_proto(device)
                    
                    yield status_update
                    
                    # 等待一段时间
                    time.sleep(request.interval_seconds or 5)
                    
                except Exception as e:
                    logger.error(f"Error in status stream for device {device_id}: {e}")
                    break
                    
        except Exception as e:
            logger.error(f"Error starting status stream: {e}")
        finally:
            # 清理
            self._unregister_stream(device_id)
    
    def ExecuteBatchCommands(self, request_iterator, context):
        """批量执行设备命令(客户端流)"""
        results = []
        success_count = 0
        failure_count = 0
        
        try:
            for command in request_iterator:
                try:
                    result = self.device_manager.execute_command(
                        device_id=command.device_id,
                        command=command.command,
                        parameters=dict(command.parameters)
                    )
                    
                    command_result = pb2.CommandResult()
                    command_result.success = result.success
                    command_result.message = result.message or ""
                    command_result.executed_at.FromDatetime(datetime.now())
                    
                    results.append(command_result)
                    
                    if result.success:
                        success_count += 1
                    else:
                        failure_count += 1
                        
                except Exception as e:
                    logger.error(f"Error executing batch command: {e}")
                    failure_count += 1
            
            # 返回汇总结果
            response = pb2.BatchCommandResult()
            response.total_commands = len(results)
            response.successful_commands = success_count
            response.failed_commands = failure_count
            response.results.extend(results)
            
            return response
            
        except Exception as e:
            logger.error(f"Error in batch command execution: {e}")
            context.set_code(grpc.StatusCode.INTERNAL)
            context.set_details("Internal server error")
            return pb2.BatchCommandResult()
    
    def RealTimeControl(self, request_iterator, context):
        """双向流:实时设备控制"""
        try:
            for client_command in request_iterator:
                # 处理客户端命令
                if client_command.HasField("device_command"):
                    # 设备控制命令
                    command = client_command.device_command
                    
                    try:
                        result = self.device_manager.execute_command(
                            device_id=command.device_id,
                            command=command.command,
                            parameters=dict(command.parameters)
                        )
                        
                        # 发送响应
                        response = pb2.ServerResponse()
                        response.command_id = client_command.command_id
                        response.success = result.success
                        response.message = result.message or ""
                        
                        yield response
                        
                    except Exception as e:
                        logger.error(f"Error executing real-time command: {e}")
                        
                        response = pb2.ServerResponse()
                        response.command_id = client_command.command_id
                        response.success = False
                        response.message = str(e)
                        
                        yield response
                
                elif client_command.HasField("subscription_request"):
                    # 订阅请求
                    subscription = client_command.subscription_request
                    
                    # 处理订阅逻辑...
                    response = pb2.ServerResponse()
                    response.command_id = client_command.command_id
                    response.success = True
                    response.message = "Subscription processed"
                    
                    yield response
                    
        except Exception as e:
            logger.error(f"Error in real-time control stream: {e}")
    
    def _device_to_proto(self, device):
        """将设备对象转换为Protobuf消息"""
        pb_device = pb2.Device()
        pb_device.id = device.id
        pb_device.name = device.name
        pb_device.type = self._device_type_to_enum(device.type)
        pb_device.manufacturer = device.manufacturer or ""
        pb_device.model = device.model or ""
        pb_device.status = self._device_status_to_enum(device.status)
        
        for key, value in device.attributes.items():
            pb_device.attributes[key] = str(value)
        
        if device.created_at:
            pb_device.created_at.FromDatetime(device.created_at)
        if device.updated_at:
            pb_device.updated_at.FromDatetime(device.updated_at)
        
        return pb_device
    
    def _device_status_to_proto(self, device):
        """设备状态转换为Protobuf消息"""
        status = pb2.DeviceStatusUpdate()
        status.device_id = device.id
        status.status = self._device_status_to_enum(device.status)
        status.timestamp.FromDatetime(datetime.now())
        
        for key, value in device.attributes.items():
            status.attributes[key] = str(value)
        
        return status
    
    def _device_type_to_enum(self, device_type):
        """设备类型字符串转换为枚举"""
        type_map = {
            "light": pb2.DeviceType.LIGHT,
            "switch": pb2.DeviceType.SWITCH,
            "sensor": pb2.DeviceType.SENSOR,
            "camera": pb2.DeviceType.CAMERA,
            "thermostat": pb2.DeviceType.THERMOSTAT,
            "door_lock": pb2.DeviceType.DOOR_LOCK,
        }
        return type_map.get(device_type.lower(), pb2.DeviceType.UNKNOWN)
    
    def _device_status_to_enum(self, device_status):
        """设备状态字符串转换为枚举"""
        status_map = {
            "offline": pb2.DeviceStatus.OFFLINE,
            "online": pb2.DeviceStatus.ONLINE,
            "error": pb2.DeviceStatus.ERROR,
            "updating": pb2.DeviceStatus.UPDATING,
        }
        return status_map.get(device_status.lower(), pb2.DeviceStatus.OFFLINE)
    
    def _register_stream(self, device_id, context):
        """注册设备状态流"""
        self._active_streams[device_id] = context
    
    def _unregister_stream(self, device_id):
        """取消注册设备状态流"""
        if device_id in self._active_streams:
            del self._active_streams[device_id]

# gRPC服务器
def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    
    # 添加服务
    device_manager = DeviceManager()
    pb2_grpc.add_DeviceServiceServicer_to_server(
        DeviceService(device_manager), server
    )
    
    # 添加拦截器(用于认证、日志、监控等)
    server = grpc.server(
        futures.ThreadPoolExecutor(max_workers=10),
        interceptors=[
            LoggingInterceptor(),
            AuthenticationInterceptor(),
            MetricsInterceptor(),
            TracingInterceptor(),
        ]
    )
    
    # 启动服务器
    server.add_insecure_port('[::]:50051')
    server.start()
    
    logger.info("gRPC server started on port 50051")
    
    try:
        while True:
            time.sleep(86400)
    except KeyboardInterrupt:
        server.stop(0)

# gRPC客户端
class DeviceServiceClient:
    def __init__(self, host='localhost', port=50051):
        channel = grpc.insecure_channel(f'{host}:{port}')
        self.stub = pb2_grpc.DeviceServiceStub(channel)
        
        # 配置拦截器
        interceptors = [
            ClientLoggingInterceptor(),
            ClientTracingInterceptor(),
        ]
        self.stub = grpc.intercept_channel(channel, *interceptors)
    
    def get_device(self, device_id):
        """获取设备信息"""
        request = pb2.GetDeviceRequest(device_id=device_id)
        
        try:
            # 设置超时
            response = self.stub.GetDevice(request, timeout=10)
            return response
        except grpc.RpcError as e:
            logger.error(f"gRPC error getting device {device_id}: {e}")
            raise
    
    def execute_command(self, device_id, command, parameters=None):
        """执行设备命令"""
        request = pb2.ExecuteCommandRequest(
            device_id=device_id,
            command=command,
            parameters=parameters or {}
        )
        
        try:
            response = self.stub.ExecuteCommand(request, timeout=30)
            return response
        except grpc.RpcError as e:
            logger.error(f"gRPC error executing command: {e}")
            raise
    
    def stream_device_status(self, device_id, interval_seconds=5):
        """流式获取设备状态"""
        request = pb2.StreamDeviceStatusRequest(
            device_id=device_id,
            interval_seconds=interval_seconds
        )
        
        try:
            for status_update in self.stub.StreamDeviceStatus(request, timeout=300):
                yield status_update
        except grpc.RpcError as e:
            logger.error(f"gRPC error in status stream: {e}")
            raise
    
    def execute_batch_commands(self, commands):
        """批量执行命令(客户端流)"""
        def command_generator():
            for cmd in commands:
                yield pb2.DeviceCommand(
                    device_id=cmd['device_id'],
                    command=cmd['command'],
                    parameters=cmd.get('parameters', {})
                )
        
        try:
            response = self.stub.ExecuteBatchCommands(
                command_generator(),
                timeout=60
            )
            return response
        except grpc.RpcError as e:
            logger.error(f"gRPC error in batch commands: {e}")
            raise
    
    def real_time_control(self, command_handler):
        """双向流实时控制"""
        
        def request_generator():
            while True:
                command = command_handler.get_next_command()
                if command is None:
                    break
                yield command
        
        try:
            for response in self.stub.RealTimeControl(request_generator()):
                command_handler.handle_response(response)
        except grpc.RpcError as e:
            logger.error(f"gRPC error in real-time control: {e}")
            raise

# gRPC拦截器示例
class LoggingInterceptor(grpc.ServerInterceptor):
    def intercept_service(self, continuation, handler_call_details):
        """日志拦截器"""
        method = handler_call_details.method
        logger.info(f"gRPC request: {method}")
        
        start_time = time.time()
        
        def logging_wrapper(behavior, request_streaming, response_streaming):
            def new_behavior(request_or_iterator, context):
                # 记录请求
                if not request_streaming:
                    logger.debug(f"Request: {request_or_iterator}")
                
                # 调用原始行为
                response = behavior(request_or_iterator, context)
                
                # 记录响应和耗时
                elapsed = time.time() - start_time
                logger.info(f"gRPC response: {method}, elapsed: {elapsed:.3f}s")
                
                return response
            return new_behavior
        
        return continuation(handler_call_details).future(
            logging_wrapper
        )

class AuthenticationInterceptor(grpc.ServerInterceptor):
    def intercept_service(self, continuation, handler_call_details):
        """认证拦截器"""
        metadata = dict(handler_call_details.invocation_metadata)
        
        # 检查认证令牌
        token = metadata.get('authorization')
        if not token or not self._validate_token(token):
            context = grpc.ServicerContext()
            context.set_code(grpc.StatusCode.UNAUTHENTICATED)
            context.set_details('Authentication required')
            return None
        
        # 继续处理
        return continuation(handler_call_details)
    
    def _validate_token(self, token):
        """验证令牌(简化实现)"""
        # 实际项目中应该验证JWT令牌
        return token.startswith('Bearer ')

四、异步消息实现示例

4.1 消息队列实现(C# + RabbitMQ)

// IMessageBus.cs - 消息总线接口
public interface IMessageBus
{
    Task PublishAsync<TEvent>(TEvent @event, string routingKey = null, 
        CancellationToken cancellationToken = default) where TEvent : IIntegrationEvent;
    
    Task SubscribeAsync<TEvent, THandler>(string subscriptionId, 
        CancellationToken cancellationToken = default) 
        where TEvent : IIntegrationEvent
        where THandler : IIntegrationEventHandler<TEvent>;
    
    Task UnsubscribeAsync<TEvent>(string subscriptionId, 
        CancellationToken cancellationToken = default) where TEvent : IIntegrationEvent;
    
    Task<IDisposable> RegisterDeadLetterHandler(string queueName, 
        Func<IModel, BasicDeliverEventArgs, Task> deadLetterHandler);
}

// IntegrationEvent.cs - 集成事件基类
public abstract class IntegrationEvent : IIntegrationEvent
{
    public Guid Id { get; } = Guid.NewGuid();
    public DateTime OccurredOn { get; } = DateTime.UtcNow;
    public string EventType { get; }
    public string Source { get; set; }
    public Dictionary<string, string> Metadata { get; } = new();
    
    protected IntegrationEvent()
    {
        EventType = GetType().Name;
    }
}

// 具体事件示例
public class DeviceStatusChangedEvent : IntegrationEvent
{
    public string DeviceId { get; }
    public string Status { get; }
    public Dictionary<string, object> Attributes { get; }
    public DateTime ChangedAt { get; }
    
    public DeviceStatusChangedEvent(string deviceId, string status, 
        Dictionary<string, object> attributes)
    {
        DeviceId = deviceId;
        Status = status;
        Attributes = attributes;
        ChangedAt = DateTime.UtcNow;
        Source = $"/devices/{deviceId}";
    }
}

public class SceneTriggeredEvent : IntegrationEvent
{
    public string SceneId { get; }
    public string TriggerType { get; }
    public Dictionary<string, object> TriggerData { get; }
    public List<SceneAction> Actions { get; }
    
    public SceneTriggeredEvent(string sceneId, string triggerType, 
        Dictionary<string, object> triggerData, List<SceneAction> actions)
    {
        SceneId = sceneId;
        TriggerType = triggerType;
        TriggerData = triggerData;
        Actions = actions;
        Source = $"/scenes/{sceneId}";
    }
}

// RabbitMQ消息总线实现
public class RabbitMQMessageBus : IMessageBus, IDisposable
{
    private readonly IConnection _connection;
    private readonly IModel _channel;
    private readonly string _exchangeName;
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<RabbitMQMessageBus> _logger;
    
    private readonly Dictionary<string, EventingBasicConsumer> _consumers = new();
    private readonly Dictionary<string, string> _consumerTags = new();
    
    public RabbitMQMessageBus(
        string hostName, 
        string exchangeName,
        IServiceProvider serviceProvider,
        ILogger<RabbitMQMessageBus> logger)
    {
        _exchangeName = exchangeName;
        _serviceProvider = serviceProvider;
        _logger = logger;
        
        var factory = new ConnectionFactory
        {
            HostName = hostName,
            UserName = "guest",
            Password = "guest",
            AutomaticRecoveryEnabled = true,
            NetworkRecoveryInterval = TimeSpan.FromSeconds(10),
            DispatchConsumersAsync = true
        };
        
        _connection = factory.CreateConnection("SmartHomeMessageBus");
        _channel = _connection.CreateModel();
        
        // 声明主题交换器
        _channel.ExchangeDeclare(
            exchange: _exchangeName,
            type: ExchangeType.Topic,
            durable: true,
            autoDelete: false
        );
        
        _logger.LogInformation("RabbitMQ message bus initialized");
    }
    
    public async Task PublishAsync<TEvent>(TEvent @event, string routingKey = null, 
        CancellationToken cancellationToken = default) where TEvent : IIntegrationEvent
    {
        if (@event == null)
            throw new ArgumentNullException(nameof(@event));
        
        routingKey ??= GetRoutingKey<TEvent>();
        
        try
        {
            var message = SerializeEvent(@event);
            var properties = CreateBasicProperties();
            
            await Task.Run(() =>
            {
                _channel.BasicPublish(
                    exchange: _exchangeName,
                    routingKey: routingKey,
                    mandatory: true,
                    basicProperties: properties,
                    body: message
                );
            }, cancellationToken);
            
            _logger.LogDebug("Published event {EventType} with routing key {RoutingKey}", 
                @event.EventType, routingKey);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to publish event {EventType}", @event.EventType);
            throw;
        }
    }
    
    public async Task SubscribeAsync<TEvent, THandler>(string subscriptionId, 
        CancellationToken cancellationToken = default) 
        where TEvent : IIntegrationEvent
        where THandler : IIntegrationEventHandler<TEvent>
    {
        if (string.IsNullOrEmpty(subscriptionId))
            throw new ArgumentNullException(nameof(subscriptionId));
        
        var queueName = GetQueueName<TEvent>(subscriptionId);
        var routingKey = GetRoutingKey<TEvent>();
        
        try
        {
            // 声明队列
            var queueArgs = new Dictionary<string, object>
            {
                { "x-dead-letter-exchange", $"{_exchangeName}.dlx" },
                { "x-dead-letter-routing-key", $"{routingKey}.dlq" }
            };
            
            var queueDeclareOk = _channel.QueueDeclare(
                queue: queueName,
                durable: true,
                exclusive: false,
                autoDelete: false,
                arguments: queueArgs
            );
            
            // 绑定队列到交换器
            _channel.QueueBind(
                queue: queueName,
                exchange: _exchangeName,
                routingKey: routingKey
            );
            
            // 创建消费者
            var consumer = new AsyncEventingBasicConsumer(_channel);
            consumer.Received += async (model, ea) =>
            {
                await HandleMessageAsync<TEvent, THandler>(model, ea, subscriptionId);
            };
            
            // 开始消费
            var consumerTag = _channel.BasicConsume(
                queue: queueName,
                autoAck: false,
                consumer: consumer
            );
            
            _consumerTags[subscriptionId] = consumerTag;
            _consumers[subscriptionId] = consumer;
            
            _logger.LogInformation(
                "Subscribed to event {EventType} with subscription {SubscriptionId}", 
                typeof(TEvent).Name, subscriptionId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to subscribe to event {EventType}", typeof(TEvent).Name);
            throw;
        }
    }
    
    private async Task HandleMessageAsync<TEvent, THandler>(
        object model, BasicDeliverEventArgs ea, string subscriptionId) 
        where TEvent : IIntegrationEvent
        where THandler : IIntegrationEventHandler<TEvent>
    {
        var consumer = (AsyncEventingBasicConsumer)model;
        var channel = consumer.Model;
        
        try
        {
            // 反序列化事件
            var @event = DeserializeEvent<TEvent>(ea.Body.ToArray());
            
            // 创建作用域并获取处理器
            using var scope = _serviceProvider.CreateScope();
            var handler = scope.ServiceProvider.GetRequiredService<THandler>();
            
            // 处理事件
            await handler.HandleAsync(@event);
            
            // 确认消息
            channel.BasicAck(ea.DeliveryTag, multiple: false);
            
            _logger.LogDebug(
                "Successfully processed event {EventType} by subscription {SubscriptionId}", 
                @event.EventType, subscriptionId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, 
                "Failed to process event for subscription {SubscriptionId}", subscriptionId);
            
            // 拒绝消息并重新入队
            channel.BasicNack(ea.DeliveryTag, multiple: false, requeue: false);
        }
    }
    
    public async Task UnsubscribeAsync<TEvent>(string subscriptionId, 
        CancellationToken cancellationToken = default) where TEvent : IIntegrationEvent
    {
        if (!_consumerTags.TryGetValue(subscriptionId, out var consumerTag))
            return;
        
        try
        {
            _channel.BasicCancel(consumerTag);
            _consumerTags.Remove(subscriptionId);
            _consumers.Remove(subscriptionId);
            
            _logger.LogInformation(
                "Unsubscribed from event {EventType} with subscription {SubscriptionId}", 
                typeof(TEvent).Name, subscriptionId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to unsubscribe from event {EventType}", 
                typeof(TEvent).Name);
            throw;
        }
    }
    
    public Task<IDisposable> RegisterDeadLetterHandler(string queueName, 
        Func<IModel, BasicDeliverEventArgs, Task> deadLetterHandler)
    {
        // 声明死信交换器
        _channel.ExchangeDeclare(
            exchange: $"{_exchangeName}.dlx",
            type: ExchangeType.Topic,
            durable: true,
            autoDelete: false
        );
        
        // 声明死信队列
        var dlqName = $"{queueName}.dlq";
        _channel.QueueDeclare(
            queue: dlqName,
            durable: true,
            exclusive: false,
            autoDelete: false
        );
        
        // 绑定死信队列
        _channel.QueueBind(
            queue: dlqName,
            exchange: $"{_exchangeName}.dlx",
            routingKey: $"{queueName}.#"
        );
        
        // 创建死信消费者
        var consumer = new AsyncEventingBasicConsumer(_channel);
        consumer.Received += async (model, ea) =>
        {
            await deadLetterHandler(model, ea);
        };
        
        var consumerTag = _channel.BasicConsume(
            queue: dlqName,
            autoAck: false,
            consumer: consumer
        );
        
        var disposable = new DisposableAction(() =>
        {
            _channel.BasicCancel(consumerTag);
        });
        
        return Task.FromResult<IDisposable>(disposable);
    }
    
    private byte[] SerializeEvent<TEvent>(TEvent @event) where TEvent : IIntegrationEvent
    {
        var json = JsonSerializer.Serialize(@event, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
        
        return Encoding.UTF8.GetBytes(json);
    }
    
    private TEvent DeserializeEvent<TEvent>(byte[] body) where TEvent : IIntegrationEvent
    {
        var json = Encoding.UTF8.GetString(body);
        return JsonSerializer.Deserialize<TEvent>(json, new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
    }
    
    private IBasicProperties CreateBasicProperties()
    {
        var properties = _channel.CreateBasicProperties();
        properties.Persistent = true;
        properties.ContentType = "application/json";
        properties.MessageId = Guid.NewGuid().ToString();
        properties.Timestamp = new AmqpTimestamp(DateTimeOffset.UtcNow.ToUnixTimeSeconds());
        
        return properties;
    }
    
    private string GetRoutingKey<TEvent>() where TEvent : IIntegrationEvent
    {
        var eventType = typeof(TEvent).Name;
        return eventType.Replace("Event", "").ToLowerInvariant();
    }
    
    private string GetQueueName<TEvent>(string subscriptionId) where TEvent : IIntegrationEvent
    {
        var eventType = typeof(TEvent).Name.Replace("Event", "").ToLowerInvariant();
        return $"{eventType}.{subscriptionId}";
    }
    
    public void Dispose()
    {
        _channel?.Close();
        _connection?.Close();
        _channel?.Dispose();
        _connection?.Dispose();
    }
    
    private class DisposableAction : IDisposable
    {
        private readonly Action _action;
        private bool _disposed;
        
        public DisposableAction(Action action)
        {
            _action = action ?? throw new ArgumentNullException(nameof(action));
        }
        
        public void Dispose()
        {
            if (!_disposed)
            {
                _action();
                _disposed = true;
            }
        }
    }
}

// 事件处理器接口
public interface IIntegrationEventHandler<in TEvent> where TEvent : IIntegrationEvent
{
    Task HandleAsync(TEvent @event);
}

// 具体事件处理器
public class DeviceStatusChangedEventHandler : IIntegrationEventHandler<DeviceStatusChangedEvent>
{
    private readonly ISceneEngineService _sceneEngineService;
    private readonly IEnergyService _energyService;
    private readonly ILogger<DeviceStatusChangedEventHandler> _logger;
    
    public DeviceStatusChangedEventHandler(
        ISceneEngineService sceneEngineService,
        IEnergyService energyService,
        ILogger<DeviceStatusChangedEventHandler> logger)
    {
        _sceneEngineService = sceneEngineService;
        _energyService = energyService;
        _logger = logger;
    }
    
    public async Task HandleAsync(DeviceStatusChangedEvent @event)
    {
        _logger.LogInformation(
            "Processing device status change: Device={DeviceId}, Status={Status}", 
            @event.DeviceId, @event.Status);
        
        try
        {
            // 并行处理多个业务逻辑
            var tasks = new List<Task>
            {
                // 1. 触发相关场景
                _sceneEngineService.EvaluateScenesForDeviceEvent(@event),
                
                // 2. 记录能耗数据
                _energyService.RecordDeviceEnergyData(@event),
                
                // 3. 检查设备健康状态
                CheckDeviceHealthAsync(@event)
            };
            
            await Task.WhenAll(tasks);
            
            _logger.LogDebug(
                "Successfully processed device status change for device {DeviceId}", 
                @event.DeviceId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, 
                "Failed to process device status change for device {DeviceId}", 
                @event.DeviceId);
            throw;
        }
    }
    
    private async Task CheckDeviceHealthAsync(DeviceStatusChangedEvent @event)
    {
        // 检查设备健康状态
        if (@event.Status == "error")
        {
            // 发送设备错误通知
            await SendDeviceAlertAsync(@event);
        }
    }
    
    private Task SendDeviceAlertAsync(DeviceStatusChangedEvent @event)
    {
        // 发送设备告警
        return Task.CompletedTask;
    }
}

// 消息总线使用示例
public class DeviceService
{
    private readonly IMessageBus _messageBus;
    private readonly ILogger<DeviceService> _logger;
    
    public DeviceService(IMessageBus messageBus, ILogger<DeviceService> logger)
    {
        _messageBus = messageBus;
        _logger = logger;
    }
    
    public async Task UpdateDeviceStatusAsync(string deviceId, string status, 
        Dictionary<string, object> attributes)
    {
        // 更新设备状态
        // ...
        
        // 发布设备状态变更事件
        var @event = new DeviceStatusChangedEvent(deviceId, status, attributes);
        
        try
        {
            await _messageBus.PublishAsync(@event);
            _logger.LogInformation(
                "Published device status changed event for device {DeviceId}", deviceId);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, 
                "Failed to publish device status changed event for device {DeviceId}", 
                deviceId);
            throw;
        }
    }
}

// 消息总线配置
public static class MessageBusExtensions
{
    public static IServiceCollection AddMessageBus(this IServiceCollection services, 
        IConfiguration configuration)
    {
        services.AddSingleton<IMessageBus>(sp =>
        {
            var hostName = configuration["MessageBus:HostName"];
            var exchangeName = configuration["MessageBus:ExchangeName"];
            var logger = sp.GetRequiredService<ILogger<RabbitMQMessageBus>>();
            
            return new RabbitMQMessageBus(hostName, exchangeName, sp, logger);
        });
        
        // 注册事件处理器
        services.AddScoped<IIntegrationEventHandler<DeviceStatusChangedEvent>, 
            DeviceStatusChangedEventHandler>();
        services.AddScoped<IIntegrationEventHandler<SceneTriggeredEvent>, 
            SceneTriggeredEventHandler>();
        
        return services;
    }
    
    public static IApplicationBuilder UseMessageBus(this IApplicationBuilder app)
    {
        var messageBus = app.ApplicationServices.GetRequiredService<IMessageBus>();
        
        // 订阅事件
        messageBus.SubscribeAsync<DeviceStatusChangedEvent, DeviceStatusChangedEventHandler>(
            "device-service").GetAwaiter().GetResult();
        
        messageBus.SubscribeAsync<SceneTriggeredEvent, SceneTriggeredEventHandler>(
            "notification-service").GetAwaiter().GetResult();
        
        return app;
    }
}

4.2 事件溯源实现(Java + Axon Framework)

// Device Aggregate - 聚合根
@Aggregate
@AggregateRoot
public class DeviceAggregate {
    
    @AggregateIdentifier
    private String deviceId;
    
    private String name;
    private String type;
    private DeviceStatus status;
    private Map<String, String> attributes;
    private LocalDateTime lastUpdated;
    
    private List<DeviceCapability> capabilities;
    
    // 必需的空构造函数
    protected DeviceAggregate() {
    }
    
    // 创建设备的命令
    @CommandHandler
    public DeviceAggregate(CreateDeviceCommand command) {
        // 验证命令
        validateCreateCommand(command);
        
        // 发布设备创建事件
        apply(new DeviceCreatedEvent(
            command.getDeviceId(),
            command.getName(),
            command.getType(),
            command.getManufacturer(),
            command.getModel(),
            command.getCapabilities(),
            command.getAttributes()
        ));
    }
    
    // 更新设备状态的命令
    @CommandHandler
    public void handle(UpdateDeviceStatusCommand command) {
        // 验证状态转换
        if (!isValidStatusTransition(command.getNewStatus())) {
            throw new InvalidStatusTransitionException(
                deviceId, status, command.getNewStatus()
            );
        }
        
        // 发布状态更新事件
        apply(new DeviceStatusUpdatedEvent(
            deviceId,
            status,
            command.getNewStatus(),
            command.getAttributes(),
            LocalDateTime.now()
        ));
    }
    
    // 执行设备命令
    @CommandHandler
    public CommandResult handle(ExecuteDeviceCommand command) {
        // 验证设备是否在线
        if (status != DeviceStatus.ONLINE) {
            throw new DeviceOfflineException(deviceId);
        }
        
        // 验证命令是否支持
        if (!supportsCommand(command.getCommand())) {
            throw new UnsupportedCommandException(deviceId, command.getCommand());
        }
        
        // 发布命令执行事件
        apply(new DeviceCommandExecutedEvent(
            deviceId,
            command.getCommand(),
            command.getParameters(),
            LocalDateTime.now()
        ));
        
        // 返回命令结果
        return new CommandResult(true, "Command executed successfully");
    }
    
    // 事件处理器 - 设备创建
    @EventSourcingHandler
    public void on(DeviceCreatedEvent event) {
        this.deviceId = event.getDeviceId();
        this.name = event.getName();
        this.type = event.getType();
        this.status = DeviceStatus.REGISTERED;
        this.attributes = new HashMap<>(event.getAttributes());
        this.capabilities = new ArrayList<>(event.getCapabilities());
        this.lastUpdated = LocalDateTime.now();
    }
    
    // 事件处理器 - 状态更新
    @EventSourcingHandler
    public void on(DeviceStatusUpdatedEvent event) {
        this.status = event.getNewStatus();
        this.attributes.putAll(event.getAttributes());
        this.lastUpdated = event.getTimestamp();
    }
    
    // 事件处理器 - 命令执行
    @EventSourcingHandler
    public void on(DeviceCommandExecutedEvent event) {
        // 更新属性(如果命令改变了设备属性)
        if (event.getParameters() != null) {
            this.attributes.putAll(event.getParameters());
        }
        this.lastUpdated = event.getTimestamp();
    }
    
    // 查询处理器
    @QueryHandler
    public DeviceSummary handle(GetDeviceQuery query) {
        return new DeviceSummary(
            deviceId,
            name,
            type,
            status,
            attributes,
            capabilities,
            lastUpdated
        );
    }
    
    private void validateCreateCommand(CreateDeviceCommand command) {
        if (command.getDeviceId() == null || command.getDeviceId().trim().isEmpty()) {
            throw new IllegalArgumentException("Device ID is required");
        }
        if (command.getName() == null || command.getName().trim().isEmpty()) {
            throw new IllegalArgumentException("Device name is required");
        }
    }
    
    private boolean isValidStatusTransition(DeviceStatus newStatus) {
        // 定义允许的状态转换
        Map<DeviceStatus, Set<DeviceStatus>> allowedTransitions = Map.of(
            DeviceStatus.REGISTERED, Set.of(DeviceStatus.OFFLINE, DeviceStatus.ONLINE),
            DeviceStatus.OFFLINE, Set.of(DeviceStatus.ONLINE, DeviceStatus.ERROR),
            DeviceStatus.ONLINE, Set.of(DeviceStatus.OFFLINE, DeviceStatus.ERROR, DeviceStatus.UPDATING),
            DeviceStatus.ERROR, Set.of(DeviceStatus.OFFLINE, DeviceStatus.ONLINE),
            DeviceStatus.UPDATING, Set.of(DeviceStatus.ONLINE, DeviceStatus.ERROR)
        );
        
        return allowedTransitions.getOrDefault(status, Set.of())
            .contains(newStatus);
    }
    
    private boolean supportsCommand(String command) {
        return capabilities.stream()
            .anyMatch(capability -> capability.getCommands().contains(command));
    }
}

// Command Gateway - 命令网关
@Component
public class DeviceCommandGateway {
    
    private final CommandGateway commandGateway;
    private final QueryGateway queryGateway;
    private final EventStore eventStore;
    
    @Autowired
    public DeviceCommandGateway(CommandGateway commandGateway, 
                               QueryGateway queryGateway,
                               EventStore eventStore) {
        this.commandGateway = commandGateway;
        this.queryGateway = queryGateway;
        this.eventStore = eventStore;
    }
    
    public String createDevice(CreateDeviceRequest request) {
        CreateDeviceCommand command = new CreateDeviceCommand(
            UUID.randomUUID().toString(),
            request.getName(),
            request.getType(),
            request.getManufacturer(),
            request.getModel(),
            request.getCapabilities(),
            request.getAttributes()
        );
        
        return commandGateway.sendAndWait(command);
    }
    
    public CommandResult executeCommand(String deviceId, DeviceCommandRequest request) {
        ExecuteDeviceCommand command = new ExecuteDeviceCommand(
            deviceId,
            request.getCommand(),
            request.getParameters()
        );
        
        return commandGateway.sendAndWait(command);
    }
    
    public DeviceSummary getDevice(String deviceId) {
        return queryGateway.query(
            new GetDeviceQuery(deviceId),
            ResponseTypes.instanceOf(DeviceSummary.class)
        ).join();
    }
    
    public List<DomainEventMessage<?>> getDeviceEvents(String deviceId) {
        // 读取设备的所有事件
        Stream<? extends DomainEventMessage<?>> events = eventStore.readEvents(deviceId);
        return events.collect(Collectors.toList());
    }
    
    public DeviceSummary recreateDeviceFromEvents(String deviceId) {
        // 从事件重建设备状态
        List<DomainEventMessage<?>> events = getDeviceEvents(deviceId);
        
        DeviceAggregate aggregate = new DeviceAggregate();
        events.forEach(event -> {
            // 应用事件到聚合
            // 注意:这仅用于查询,不改变实际聚合状态
        });
        
        return new DeviceSummary(
            aggregate.getDeviceId(),
            aggregate.getName(),
            aggregate.getType(),
            aggregate.getStatus(),
            aggregate.getAttributes(),
            aggregate.getCapabilities(),
            aggregate.getLastUpdated()
        );
    }
}

// Event Processor - 事件处理器
@Component
public class DeviceEventProcessor {
    
    private static final Logger log = LoggerFactory.getLogger(DeviceEventProcessor.class);
    
    private final EventProcessingConfiguration eventProcessingConfig;
    private final KafkaTemplate<String, Object> kafkaTemplate;
    private final MongoTemplate mongoTemplate;
    
    @Autowired
    public DeviceEventProcessor(EventProcessingConfiguration eventProcessingConfig,
                               KafkaTemplate<String, Object> kafkaTemplate,
                               MongoTemplate mongoTemplate) {
        this.eventProcessingConfig = eventProcessingConfig;
        this.kafkaTemplate = kafkaTemplate;
        this.mongoTemplate = mongoTemplate;
    }
    
    // 处理设备创建事件
    @EventHandler
    public void on(DeviceCreatedEvent event) {
        log.info("Processing device created event: {}", event.getDeviceId());
        
        // 1. 更新读模型(MongoDB)
        updateDeviceReadModel(event);
        
        // 2. 发送到Kafka供其他服务消费
        sendToKafka("device.created", event);
        
        // 3. 初始化设备监控
        initializeDeviceMonitoring(event);
    }
    
    // 处理设备状态更新事件
    @EventHandler
    public void on(DeviceStatusUpdatedEvent event) {
        log.info("Processing device status updated event: {}", event.getDeviceId());
        
        // 1. 更新读模型
        updateDeviceStatusInReadModel(event);
        
        // 2. 发送到Kafka
        sendToKafka("device.status.updated", event);
        
        // 3. 触发相关场景
        triggerRelatedScenes(event);
        
        // 4. 记录状态历史
        recordStatusHistory(event);
    }
    
    // 处理设备命令执行事件
    @EventHandler
    public void on(DeviceCommandExecutedEvent event) {
        log.info("Processing device command executed event: {}", event.getDeviceId());
        
        // 1. 记录命令执行日志
        recordCommandExecution(event);
        
        // 2. 发送到Kafka
        sendToKafka("device.command.executed", event);
        
        // 3. 更新设备统计数据
        updateDeviceStatistics(event);
    }
    
    // Saga - 处理复杂的业务流程
    @Saga
    public class DeviceRegistrationSaga {
        
        @SagaEventHandler(associationProperty = "deviceId")
        public void handle(DeviceCreatedEvent event) {
            // 启动设备配置流程
            // 1. 验证设备信息
            // 2. 分配设备到网络
            // 3. 初始化设备固件
            // 4. 发送欢迎通知
        }
        
        @SagaEventHandler(associationProperty = "deviceId")
        public void handle(DeviceConfigurationCompletedEvent event) {
            // 设备配置完成,更新状态为在线
            commandGateway.send(new UpdateDeviceStatusCommand(
                event.getDeviceId(),
                DeviceStatus.ONLINE,
                Map.of("configured", "true")
            ));
        }
        
        @EndSaga
        @SagaEventHandler(associationProperty = "deviceId")
        public void handle(DeviceStatusUpdatedEvent event) {
            if (event.getNewStatus() == DeviceStatus.ONLINE) {
                // 设备成功上线,Saga结束
                log.info("Device registration saga completed for device: {}", 
                    event.getDeviceId());
            }
        }
    }
    
    // 投影(Projection) - 维护读模型
    @ProcessingGroup("device-projections")
    @Component
    public class DeviceProjection {
        
        private final MongoTemplate mongoTemplate;
        
        public DeviceProjection(MongoTemplate mongoTemplate) {
            this.mongoTemplate = mongoTemplate;
        }
        
        @EventHandler
        public void on(DeviceCreatedEvent event) {
            DeviceDocument document = new DeviceDocument();
            document.setDeviceId(event.getDeviceId());
            document.setName(event.getName());
            document.setType(event.getType());
            document.setStatus("REGISTERED");
            document.setAttributes(event.getAttributes());
            document.setCapabilities(event.getCapabilities());
            document.setCreatedAt(LocalDateTime.now());
            document.setUpdatedAt(LocalDateTime.now());
            
            mongoTemplate.save(document, "devices");
        }
        
        @EventHandler
        public void on(DeviceStatusUpdatedEvent event) {
            Query query = new Query(Criteria.where("deviceId").is(event.getDeviceId()));
            Update update = new Update()
                .set("status", event.getNewStatus().name())
                .set("attributes", event.getAttributes())
                .set("updatedAt", event.getTimestamp());
            
            mongoTemplate.updateFirst(query, update, DeviceDocument.class, "devices");
        }
        
        @EventHandler
        public void on(DeviceCommandExecutedEvent event) {
            // 更新设备最后活动时间
            Query query = new Query(Criteria.where("deviceId").is(event.getDeviceId()));
            Update update = new Update()
                .set("lastActivityAt", event.getTimestamp());
            
            mongoTemplate.updateFirst(query, update, DeviceDocument.class, "devices");
            
            // 记录命令历史
            CommandHistory history = new CommandHistory(
                event.getDeviceId(),
                event.getCommand(),
                event.getParameters(),
                event.getTimestamp()
            );
            
            mongoTemplate.save(history, "command_history");
        }
    }
    
    private void updateDeviceReadModel(DeviceCreatedEvent event) {
        // 更新MongoDB读模型
    }
    
    private void sendToKafka(String topic, Object event) {
        kafkaTemplate.send(topic, event.getDeviceId(), event);
    }
    
    private void initializeDeviceMonitoring(DeviceCreatedEvent event) {
        // 初始化设备监控
    }
    
    private void updateDeviceStatusInReadModel(DeviceStatusUpdatedEvent event) {
        // 更新设备状态
    }
    
    private void triggerRelatedScenes(DeviceStatusUpdatedEvent event) {
        // 触发相关场景
    }
    
    private void recordStatusHistory(DeviceStatusUpdatedEvent event) {
        // 记录状态历史
    }
    
    private void recordCommandExecution(DeviceCommandExecutedEvent event) {
        // 记录命令执行
    }
    
    private void updateDeviceStatistics(DeviceCommandExecutedEvent event) {
        // 更新设备统计
    }
}

// Axon配置
@Configuration
public class AxonConfig {
    
    @Bean
    public EventStore eventStore(Serializer serializer, 
                                PersistenceExceptionResolver persistenceExceptionResolver,
                                @Qualifier("eventStorageEngine") StorageEngine storageEngine) {
        return EmbeddedEventStore.builder()
            .storageEngine(storageEngine)
            .build();
    }
    
    @Bean
    public StorageEngine eventStorageEngine(MongoClient mongoClient) {
        return MongoEventStorageEngine.builder()
            .mongoTemplate(DefaultMongoTemplate.builder()
                .mongoDatabase(mongoClient)
                .build())
            .build();
    }
    
    @Bean
    public SagaStore sagaStore(MongoClient mongoClient) {
        return MongoSagaStore.builder()
            .mongoTemplate(DefaultMongoTemplate.builder()
                .mongoDatabase(mongoClient)
                .sagasCollectionName("sagas")
                .build())
            .build();
    }
    
    @Bean
    public TokenStore tokenStore(MongoClient mongoClient) {
        return MongoTokenStore.builder()
            .mongoTemplate(DefaultMongoTemplate.builder()
                .mongoDatabase(mongoClient)
                .trackingTokensCollectionName("tokens")
                .build())
            .serializer(JacksonSerializer.defaultSerializer())
            .build();
    }
    
    @Bean
    public EventProcessingConfigurer eventProcessingConfigurer() {
        return configurer -> {
            configurer.usingSubscribingEventProcessors();
            configurer.registerTrackingEventProcessor("device-projections")
                .assignHandlerTypesMatching("device-projections", 
                    clazz -> clazz.getPackage().getName().contains("projection"));
        };
    }
    
    @Bean
    public QueryUpdateEmitter queryUpdateEmitter() {
        return SimpleQueryUpdateEmitter.builder().build();
    }
}

五、共享存储实现示例

5.1 Redis共享缓存(Python + Redis)

# shared_cache.py
import json
import pickle
import asyncio
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Union
from enum import Enum
import redis.asyncio as redis
from redis.asyncio import Redis
import logging

logger = logging.getLogger(__name__)

class CacheStrategy(Enum):
    """缓存策略"""
    WRITE_THROUGH = "write_through"    # 直写
    WRITE_BACK = "write_back"          # 回写
    WRITE_AROUND = "write_around"      # 绕写
    CACHE_ASIDE = "cache_aside"        # 旁路缓存

class CacheKey:
    """缓存键生成器"""
    
    @staticmethod
    def device_status(device_id: str) -> str:
        return f"device:status:{device_id}"
    
    @staticmethod
    def device_attributes(device_id: str) -> str:
        return f"device:attributes:{device_id}"
    
    @staticmethod
    def user_session(user_id: str) -> str:
        return f"user:session:{user_id}"
    
    @staticmethod
    def scene_state(scene_id: str) -> str:
        return f"scene:state:{scene_id}"
    
    @staticmethod
    def lock(resource: str) -> str:
        return f"lock:{resource}"
    
    @staticmethod
    def rate_limit(key: str, window: str) -> str:
        return f"ratelimit:{key}:{window}"

class DistributedCache:
    """分布式缓存服务"""
    
    def __init__(self, redis_client: Redis, strategy: CacheStrategy = CacheStrategy.CACHE_ASIDE):
        self.redis = redis_client
        self.strategy = strategy
        self._local_cache = {}  # 本地缓存(减少Redis访问)
        self._lock = asyncio.Lock()
        
    async def get_device_status(self, device_id: str) -> Optional[Dict[str, Any]]:
        """获取设备状态"""
        cache_key = CacheKey.device_status(device_id)
        
        # 先检查本地缓存
        if device_id in self._local_cache:
            cached_data = self._local_cache[device_id]
            if datetime.now() - cached_data['cached_at'] < timedelta(seconds=5):
                return cached_data['status']
        
        # 从Redis获取
        try:
            data = await self.redis.get(cache_key)
            if data:
                status = json.loads(data)
                
                # 更新本地缓存
                self._local_cache[device_id] = {
                    'status': status,
                    'cached_at': datetime.now()
                }
                
                return status
        except Exception as e:
            logger.error(f"Error getting device status from cache: {e}")
        
        return None
    
    async def set_device_status(self, device_id: str, status: Dict[str, Any], 
                               ttl: int = 300) -> bool:
        """设置设备状态"""
        cache_key = CacheKey.device_status(device_id)
        
        try:
            # 根据策略处理
            if self.strategy == CacheStrategy.WRITE_THROUGH:
                # 直写:先写数据库,再写缓存
                success = await self._write_to_database(device_id, status)
                if success:
                    await self._write_to_cache(cache_key, status, ttl)
            elif self.strategy == CacheStrategy.WRITE_BACK:
                # 回写:先写缓存,异步写数据库
                await self._write_to_cache(cache_key, status, ttl)
                asyncio.create_task(self._write_to_database(device_id, status))
            else:  # CACHE_ASIDE
                # 旁路缓存:直接写缓存,由应用负责数据库更新
                await self._write_to_cache(cache_key, status, ttl)
            
            # 更新本地缓存
            self._local_cache[device_id] = {
                'status': status,
                'cached_at': datetime.now()
            }
            
            return True
        except Exception as e:
            logger.error(f"Error setting device status in cache: {e}")
            return False
    
    async def get_user_session(self, user_id: str) -> Optional[Dict[str, Any]]:
        """获取用户会话"""
        cache_key = CacheKey.user_session(user_id)
        
        try:
            data = await self.redis.get(cache_key)
            if data:
                return json.loads(data)
        except Exception as e:
            logger.error(f"Error getting user session from cache: {e}")
        
        return None
    
    async def set_user_session(self, user_id: str, session: Dict[str, Any], 
                              ttl: int = 3600) -> bool:
        """设置用户会话"""
        cache_key = CacheKey.user_session(user_id)
        
        try:
            await self.redis.setex(
                cache_key,
                ttl,
                json.dumps(session)
            )
            return True
        except Exception as e:
            logger.error(f"Error setting user session in cache: {e}")
            return False
    
    async def acquire_lock(self, resource: str, owner: str, 
                          timeout: int = 30) -> bool:
        """获取分布式锁"""
        cache_key = CacheKey.lock(resource)
        
        try:
            # 使用SET命令的NX和EX选项实现分布式锁
            result = await self.redis.set(
                cache_key,
                owner,
                ex=timeout,
                nx=True  # 只在键不存在时设置
            )
            
            return result is True
        except Exception as e:
            logger.error(f"Error acquiring lock: {e}")
            return False
    
    async def release_lock(self, resource: str, owner: str) -> bool:
        """释放分布式锁"""
        cache_key = CacheKey.lock(resource)
        
        try:
            # 使用Lua脚本确保原子性
            lua_script = """
                if redis.call("GET", KEYS[1]) == ARGV[1] then
                    return redis.call("DEL", KEYS[1])
                else
                    return 0
                end
            """
            
            result = await self.redis.eval(
                lua_script,
                1,
                cache_key,
                owner
            )
            
            return result == 1
        except Exception as e:
            logger.error(f"Error releasing lock: {e}")
            return False
    
    async def check_rate_limit(self, key: str, limit: int, 
                              window_seconds: int = 60) -> Dict[str, Any]:
        """检查速率限制"""
        cache_key = CacheKey.rate_limit(key, str(window_seconds))
        current_time = int(datetime.now().timestamp())
        window_start = current_time - window_seconds
        
        try:
            # 使用Redis管道提高性能
            async with self.redis.pipeline() as pipe:
                # 移除窗口外的记录
                await pipe.zremrangebyscore(cache_key, 0, window_start)
                
                # 获取当前窗口内的请求数
                await pipe.zcard(cache_key)
                
                # 获取最早的时间戳(用于计算重置时间)
                await pipe.zrange(cache_key, 0, 0, withscores=True)
                
                results = await pipe.execute()
                
            current_count = results[1]
            earliest_entry = results[2]
            
            reset_time = window_start + window_seconds
            if earliest_entry:
                reset_time = int(earliest_entry[0][1]) + window_seconds
            
            if current_count < limit:
                # 添加当前请求
                await self.redis.zadd(cache_key, {str(current_time): current_time})
                await self.redis.expire(cache_key, window_seconds)
                
                remaining = limit - current_count - 1
                return {
                    "allowed": True,
                    "remaining": remaining,
                    "limit": limit,
                    "reset": reset_time
                }
            else:
                return {
                    "allowed": False,
                    "remaining": 0,
                    "limit": limit,
                    "reset": reset_time
                }
                
        except Exception as e:
            logger.error(f"Error checking rate limit: {e}")
            # 出错时允许请求通过
            return {
                "allowed": True,
                "remaining": limit,
                "limit": limit,
                "reset": current_time + window_seconds
            }
    
    async def publish_event(self, channel: str, event: Dict[str, Any]) -> bool:
        """发布事件到频道"""
        try:
            await self.redis.publish(
                channel,
                json.dumps(event)
            )
            return True
        except Exception as e:
            logger.error(f"Error publishing event: {e}")
            return False
    
    async def subscribe_events(self, channels: List[str], 
                              message_handler) -> None:
        """订阅事件频道"""
        pubsub = self.redis.pubsub()
        
        try:
            await pubsub.subscribe(*channels)
            
            async for message in pubsub.listen():
                if message['type'] == 'message':
                    try:
                        event = json.loads(message['data'])
                        await message_handler(
                            message['channel'].decode(),
                            event
                        )
                    except Exception as e:
                        logger.error(f"Error handling pubsub message: {e}")
                        
        except Exception as e:
            logger.error(f"Error in pubsub subscription: {e}")
        finally:
            await pubsub.unsubscribe()
            await pubsub.close()
    
    async def get_or_set(self, key: str, ttl: int, 
                        value_factory) -> Any:
        """获取或设置缓存值(缓存穿透保护)"""
        try:
            # 尝试从缓存获取
            cached_value = await self.redis.get(key)
            if cached_value is not None:
                return json.loads(cached_value)
            
            # 获取分布式锁,防止缓存击穿
            lock_key = f"{key}:lock"
            lock_acquired = await self.acquire_lock(lock_key, "cache_loader", 10)
            
            if lock_acquired:
                try:
                    # 再次检查缓存(双检锁)
                    cached_value = await self.redis.get(key)
                    if cached_value is not None:
                        return json.loads(cached_value)
                    
                    # 从数据源加载
                    value = await value_factory()
                    
                    # 设置缓存
                    await self.redis.setex(
                        key,
                        ttl,
                        json.dumps(value)
                    )
                    
                    return value
                finally:
                    await self.release_lock(lock_key, "cache_loader")
            else:
                # 等待其他线程/进程加载缓存
                await asyncio.sleep(0.1)
                
                # 重试获取缓存
                for _ in range(10):
                    cached_value = await self.redis.get(key)
                    if cached_value is not None:
                        return json.loads(cached_value)
                    await asyncio.sleep(0.1)
                
                # 降级:直接调用数据源
                return await value_factory()
                
        except Exception as e:
            logger.error(f"Error in get_or_set: {e}")
            # 降级:直接调用数据源
            return await value_factory()
    
    async def batch_get(self, keys: List[str]) -> Dict[str, Any]:
        """批量获取缓存值"""
        try:
            values = await self.redis.mget(keys)
            
            result = {}
            for key, value in zip(keys, values):
                if value is not None:
                    result[key] = json.loads(value)
                else:
                    result[key] = None
            
            return result
        except Exception as e:
            logger.error(f"Error in batch get: {e}")
            return {key: None for key in keys}
    
    async def batch_set(self, items: Dict[str, Any], ttl: int = 300) -> bool:
        """批量设置缓存值"""
        try:
            async with self.redis.pipeline() as pipe:
                for key, value in items.items():
                    await pipe.setex(
                        key,
                        ttl,
                        json.dumps(value)
                    )
                
                await pipe.execute()
                return True
        except Exception as e:
            logger.error(f"Error in batch set: {e}")
            return False
    
    async def invalidate_pattern(self, pattern: str) -> int:
        """根据模式删除缓存键"""
        try:
            keys = []
            async for key in self.redis.scan_iter(match=pattern):
                keys.append(key)
            
            if keys:
                return await self.redis.delete(*keys)
            return 0
        except Exception as e:
            logger.error(f"Error invalidating pattern {pattern}: {e}")
            return 0
    
    async def _write_to_cache(self, key: str, value: Any, ttl: int) -> None:
        """写入缓存"""
        await self.redis.setex(
            key,
            ttl,
            json.dumps(value)
        )
    
    async def _write_to_database(self, device_id: str, status: Dict[str, Any]) -> bool:
        """写入数据库(模拟)"""
        # 实际项目中这里会调用数据库服务
        await asyncio.sleep(0.01)
        return True

# 使用示例
async def main():
    # 创建Redis连接
    redis_client = redis.Redis(
        host='localhost',
        port=6379,
        decode_responses=True
    )
    
    # 创建缓存服务
    cache = DistributedCache(redis_client, CacheStrategy.WRITE_THROUGH)
    
    # 设备状态缓存示例
    device_id = "light_001"
    
    # 设置设备状态
    status = {
        "power": "on",
        "brightness": 80,
        "color": "warm",
        "online": True,
        "last_seen": datetime.now().isoformat()
    }
    
    await cache.set_device_status(device_id, status, ttl=300)
    
    # 获取设备状态
    cached_status = await cache.get_device_status(device_id)
    print(f"Device status: {cached_status}")
    
    # 分布式锁示例
    resource = "device:config:light_001"
    lock_owner = "scene_engine_001"
    
    if await cache.acquire_lock(resource, lock_owner, timeout=30):
        try:
            # 执行需要互斥的操作
            print("Lock acquired, performing exclusive operation...")
            await asyncio.sleep(5)
        finally:
            await cache.release_lock(resource, lock_owner)
            print("Lock released")
    else:
        print("Failed to acquire lock")
    
    # 速率限制示例
    user_id = "user_123"
    rate_limit_key = f"user:{user_id}:api"
    
    for i in range(15):
        result = await cache.check_rate_limit(rate_limit_key, limit=10, window_seconds=60)
        print(f"Request {i+1}: Allowed={result['allowed']}, Remaining={result['remaining']}")
        await asyncio.sleep(0.1)
    
    # 发布订阅示例
    async def handle_device_event(channel: str, event: Dict[str, Any]):
        print(f"Received event on {channel}: {event}")
    
    # 在后台订阅事件
    asyncio.create_task(cache.subscribe_events(
        ["device:events", "scene:events"],
        handle_device_event
    ))
    
    # 发布事件
    await cache.publish_event("device:events", {
        "type": "status_changed",
        "device_id": device_id,
        "status": "offline",
        "timestamp": datetime.now().isoformat()
    })
    
    await asyncio.sleep(1)
    
    # 关闭连接
    await redis_client.close()

if __name__ == "__main__":
    asyncio.run(main())

六、交互数据流与控制流示例

6.1 完整交互时序图

@startuml SmartHomeInteractionSequence
title 智能家居系统组件交互时序图

participant "移动App" as App
participant "API网关" as Gateway
participant "设备服务" as DeviceService
participant "场景引擎" as SceneEngine
participant "消息队列" as MessageQueue
participant "Zigbee适配器" as ZigbeeAdapter
participant "设备缓存" as Cache
participant "设备数据库" as Database

group 场景1:用户控制设备 [同步调用]
    App -> Gateway: 1. HTTP POST /api/devices/{id}/commands
    Gateway -> DeviceService: 2. 转发请求(负载均衡)
    
    DeviceService -> Cache: 3. 检查设备状态缓存
    Cache --> DeviceService: 4. 返回缓存状态
    
    alt 缓存命中
        DeviceService -> DeviceService: 5. 使用缓存状态
    else 缓存未命中
        DeviceService -> Database: 5. 查询设备信息
        Database --> DeviceService: 6. 返回设备信息
        DeviceService -> Cache: 7. 更新设备缓存
    end
    
    DeviceService -> ZigbeeAdapter: 8. 发送控制命令
    ZigbeeAdapter -> DeviceService: 9. 返回命令结果
    
    DeviceService -> Cache: 10. 更新设备状态缓存
    DeviceService -> MessageQueue: 11. 发布设备状态事件
    
    DeviceService --> Gateway: 12. 返回命令执行结果
    Gateway --> App: 13. 返回HTTP响应
end

group 场景2:自动化场景触发 [异步事件]
    ZigbeeAdapter -> MessageQueue: 14. 发布设备状态变化事件
    
    MessageQueue -> SceneEngine: 15. 推送设备事件
    SceneEngine -> SceneEngine: 16. 评估场景规则
    
    alt 场景条件满足
        SceneEngine -> DeviceService: 17. 调用设备控制命令
        DeviceService -> ZigbeeAdapter: 18. 执行场景动作
        ZigbeeAdapter --> DeviceService: 19. 返回执行结果
        DeviceService -> MessageQueue: 20. 发布场景执行事件
    end
end

group 场景3:设备状态同步 [共享存储]
    Note over ZigbeeAdapter, Cache: 设备状态实时更新
    
    ZigbeeAdapter -> Cache: 21. 更新设备状态缓存
    Cache -> Cache: 22. 发布状态变更通知
    
    Note over Cache: 其他服务订阅缓存变更
    
    DeviceService -> Cache: 23. 监听设备状态变更
    SceneEngine -> Cache: 24. 监听设备状态变更
end

@enduml

6.2 数据流图

@startuml SmartHomeDataFlow
title 智能家居系统数据流图

database "设备数据库" as DB {
    folder "设备元数据" as DeviceMeta
    folder "设备状态历史" as StatusHistory
    folder "命令执行日志" as CommandLog
}

cloud "消息队列" as MQ {
    queue "设备事件" as DeviceEvents
    queue "场景事件" as SceneEvents
    queue "系统事件" as SystemEvents
}

queue "设备状态缓存" as Cache {
    folder "实时状态" as RealTimeStatus
    folder "会话信息" as SessionInfo
    folder "分布式锁" as DistributedLocks
}

node "API网关" as Gateway {
    [HTTP/WebSocket] as API
    [负载均衡] as LoadBalancer
    [认证授权] as Auth
}

node "业务服务" as Services {
    [设备管理服务] as DeviceService
    [场景引擎服务] as SceneService
    [用户管理服务] as UserService
    [能源管理服务] as EnergyService
}

node "设备适配器" as Adapters {
    [Zigbee网关] as Zigbee
    [WiFi适配器] as WiFi
    [蓝牙适配器] as Bluetooth
}

node "客户端" as Clients {
    [Web应用] as Web
    [移动应用] as Mobile
    [语音助手] as Voice
}

' 数据流
Clients --> Gateway: 用户请求/控制命令
Gateway --> Services: 认证后的请求

DeviceService --> DB: 读写设备元数据
DeviceService --> Cache: 缓存设备状态
DeviceService --> MQ: 发布设备事件
DeviceService --> Adapters: 发送控制命令

Adapters --> DeviceService: 设备状态更新
Adapters --> Cache: 实时状态推送
Adapters --> MQ: 原始设备事件

SceneService --> MQ: 订阅设备事件
SceneService --> DeviceService: 执行场景动作
SceneService --> DB: 记录场景执行历史

UserService --> Cache: 管理用户会话
UserService --> DB: 存储用户数据

EnergyService --> MQ: 订阅能耗事件
EnergyService --> DB: 存储能耗数据

Cache --> Services: 状态变更通知
MQ --> Services: 事件驱动处理

' 控制流
note on link
    **控制流方向:**
    1. 用户请求 → 网关 → 服务 → 适配器 → 设备
    2. 设备事件 → 适配器 → 缓存/消息队列 → 服务
    3. 服务间通过消息队列异步通信
    4. 实时状态通过缓存共享
end note

@enduml

七、核心机制与原理总结

7.1 交互模式选择指南

模式选择指南:
  同步调用 (REST/gRPC):
    适用: 
      - 需要立即响应的操作
      - 命令与控制场景
      - 实时查询请求
    实现要点:
      - 定义清晰的API契约
      - 实现重试和熔断机制
      - 添加分布式追踪
      - 设置合理的超时时间
    
  异步消息 (消息队列):
    适用:
      - 后台处理任务
      - 事件通知广播
      - 系统解耦集成
    实现要点:
      - 保证消息的可靠投递
      - 处理消息顺序和幂等性
      - 实现死信队列机制
      - 监控消息积压情况
    
  事件驱动 (事件溯源):
    适用:
      - 状态变化跟踪
      - 复杂业务流程
      - 审计和追溯需求
    实现要点:
      - 设计不可变的事件模型
      - 实现事件的持久化和重放
      - 分离命令和查询责任(CQRS)
      - 保证事件的全局顺序
    
  共享存储 (缓存/数据库):
    适用:
      - 数据共享和状态同步
      - 高性能读操作
      - 分布式协调
    实现要点:
      - 选择合适的缓存策略
      - 处理缓存一致性
      - 实现分布式锁和限流
      - 监控缓存命中率和性能

7.2 最佳实践总结

  1. 接口设计原则:

    • 保持接口的稳定性和向后兼容
    • 使用标准的协议和格式
    • 提供完整的API文档
    • 实现版本管理策略
  2. 可靠性保证:

    • 实现重试机制和指数退避
    • 添加熔断器和降级策略
    • 保证消息的至少一次投递
    • 实现数据的一致性检查
  3. 性能优化:

    • 使用连接池和连接复用
    • 实现批处理和异步操作
    • 添加多级缓存策略
    • 监控和优化网络延迟
  4. 可观测性:

    • 添加分布式追踪
    • 记录完整的请求链路
    • 监控交互性能和错误率
    • 实现日志聚合和分析
  5. 安全性考虑:

    • 实现认证和授权机制
    • 加密敏感数据传输
    • 验证输入参数和消息
    • 实现速率限制和防重放

通过合理选择和应用这些交互模式,可以构建出高可用、高性能、易维护的分布式系统架构。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千江明月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值