嵌入式微服务架构:从单体固件到模块化服务的设计演进——服务边界与RPC轻量实现

每日一句正能量
真正的难不是事情本身,而是说服自己开始。
事情往往没想象中复杂,但启动时的犹豫、完美主义、恐惧会无限放大难度。“说服自己开始”是克服惰性与心魔的过程,一旦迈出第一步,事情本身反而会推着你走。
一、前言
在嵌入式系统发展的早期阶段,单体固件(Monolithic Firmware)是主流开发模式——所有功能模块编译链接为一个二进制文件,共享全局地址空间,通过函数直接调用实现模块间通信。这种模式在功能简单、资源充裕的场景下运行良好,但随着物联网设备的智能化需求爆发,其固有的耦合度高、扩展困难、维护成本大等问题日益凸显。
微服务架构在云端和移动端已证明其价值,但在资源受限的嵌入式环境中落地面临独特挑战:KB级内存、MHz级主频、无MMU(内存管理单元)的约束使得传统微服务方案(如gRPC + Kubernetes)完全不可行。本文将探讨如何在嵌入式环境中实现轻量级微服务架构,重点解决服务边界划分和RPC轻量实现两大核心问题,并结合鸿蒙生态(HarmonyOS/OpenHarmony)提供完整的工程实践方案。
二、架构演进路径

图1:从单体固件到模块化服务的演进路径
2.1 四个演进阶段
| 阶段 | 特征 | 优点 | 缺点 |
|---|---|---|---|
| 单体固件 | 所有代码编译为一个.bin | 简单直接 | 耦合严重,修改影响全局 |
| 分层架构 | HAL/BSP/APP分层 | 职责分离 | 仍静态链接,同地址空间 |
| 模块化组件 | 独立编译单元,显式接口 | 可替换,可测试 | 共享内存,无故障隔离 |
| 微服务架构 | 独立地址空间,RPC通信 | 故障隔离,独立升级 | 通信开销,实现复杂 |
2.2 为什么嵌入式需要微服务?
传统观点认为微服务是"重量级"架构,与嵌入式"轻量级"需求矛盾。但实际上,嵌入式微服务是概念借鉴而非照搬:
- 故障隔离:传感器驱动崩溃不应导致网络通信中断
- 独立升级:OTA时仅需更新单个服务,降低风险
- 团队并行:不同服务可由不同团队独立开发测试
- 技术异构:核心服务用C,AI推理服务可用C++/Rust
三、服务边界划分原则

图2:服务边界划分原则与示例
3.1 领域驱动设计(DDD)在嵌入式中的应用
借鉴云原生领域的领域驱动设计,将嵌入式系统划分为三类边界:
3.1.1 核心域(Core Domain)
承载系统核心价值的功能,变更频率最高,需要最严格的测试覆盖:
/* 核心域:温度控制服务接口 */
#ifndef TEMP_CTRL_SERVICE_H
#define TEMP_CTRL_SERVICE_H
#include <stdint.h>
/* 服务ID:全局唯一标识 */
#define SVC_ID_TEMP_CTRL 0x01
/* 方法ID */
#define METHOD_SET_TARGET 0x01
#define METHOD_GET_STATUS 0x02
#define METHOD_EMERGENCY_STOP 0x03
typedef struct {
float target_temp; /* 目标温度 */
uint16_t pwm_duty; /* 当前PWM占空比 */
uint8_t mode; /* 工作模式 */
} TempCtrlStatus;
/* RPC接口定义 */
int32_t TempCtrl_SetTarget(float target);
int32_t TempCtrl_GetStatus(TempCtrlStatus *status);
int32_t TempCtrl_EmergencyStop(void);
#endif
3.1.2 支撑域(Supporting Domain)
为核心业务提供技术支撑,相对稳定:
- 网络通信服务(MQTT/CoAP协议栈)
- 数据持久化服务(Flash/SD卡存储)
- 日志记录服务(分级日志、环形缓冲)
3.1.3 通用域(Generic Domain)
行业通用功能,可复用、可替换:
- 设备管理服务(设备信息、序列号)
- 固件升级服务(OTA下载、验签、刷写)
- 安全认证服务(TLS握手、证书管理)
3.2 服务边界划分六原则
| 原则 | 说明 | 嵌入式实践 |
|---|---|---|
| 单一职责 | 一个服务只做一件事 | 温度采集 ≠ 温度控制,拆分为两个服务 |
| 高内聚 | 内部功能紧密相关 | PID算法、PWM输出、温度读取同属控制服务 |
| 低耦合 | 最小化服务间依赖 | 通过RPC而非直接调用,消除编译期依赖 |
| 独立部署 | 可独立编译烧录 | 每个服务生成独立的.bin分段 |
| 故障隔离 | 单点故障不影响全局 | Watchdog分服务监控,异常时重启单个服务 |
| 资源配额 | 限制CPU/内存使用 | 为每个服务分配固定堆栈和消息队列 |
3.3 反模式:避免过度拆分
嵌入式微服务不是"拆得越细越好",需警惕以下反模式:
/* ❌ 反模式:过度拆分 */
#define SVC_ID_ADC_READ 0x10
#define SVC_ID_ADC_CALIBRATE 0x11
#define SVC_ID_ADC_CONFIG 0x12
/* 三个服务只做一件事,RPC开销远超计算本身 */
/* ✅ 正确做法:内聚合并 */
#define SVC_ID_ADC_SERVICE 0x10
#define METHOD_READ 0x01
#define METHOD_CALIBRATE 0x02
#define METHOD_CONFIG 0x03
/* 一个ADC服务提供三个方法 */
拆分粒度判断标准:如果两个功能总是同时变更、同时测试、同时部署,它们应该属于同一个服务。
四、轻量级RPC实现
4.1 RPC架构设计

图3:轻量级RPC通信架构
在嵌入式环境中,RPC实现需满足以下约束:
| 约束 | 云端RPC | 嵌入式RPC |
|---|---|---|
| 传输层 | TCP/HTTP2 | UART/SPI/I2C/共享内存 |
| 序列化 | Protobuf/JSON | 自定义二进制(< 16字节头) |
| 服务发现 | ZooKeeper/Eureka | 静态注册表/预配置 |
| 并发模型 | 线程池 | 单线程事件循环 |
| 容错机制 | 熔断/限流 | Watchdog/看门狗重启 |
4.2 消息格式定义
/**
* @file rpc_protocol.h
* @brief 轻量级RPC协议定义
* @version 1.0.0
*/
#ifndef RPC_PROTOCOL_H
#define RPC_PROTOCOL_H
#include <stdint.h>
/* 协议魔数 */
#define RPC_MAGIC 0x55AA
/* 消息类型 */
#define MSG_TYPE_REQUEST 0x01
#define MSG_TYPE_RESPONSE 0x02
#define MSG_TYPE_NOTIFY 0x03
#define MSG_TYPE_HEARTBEAT 0x04
/* 错误码 */
#define RPC_OK 0x00
#define RPC_ERR_TIMEOUT 0x01
#define RPC_ERR_NO_SERVICE 0x02
#define RPC_ERR_NO_METHOD 0x03
#define RPC_ERR_INVALID_ARG 0x04
#define RPC_ERR_INTERNAL 0x05
/* 消息头:固定8字节 */
typedef struct __attribute__((packed)) {
uint16_t magic; /* 魔数 0x55AA */
uint8_t version; /* 协议版本 */
uint8_t msg_type; /* 消息类型 */
uint8_t service_id; /* 服务ID */
uint8_t method_id; /* 方法ID */
uint16_t payload_len; /* 载荷长度 */
} RpcHeader;
/* 请求消息 */
typedef struct {
RpcHeader header;
uint8_t payload[0]; /* 变长载荷 */
} RpcRequest;
/* 响应消息 */
typedef struct {
RpcHeader header;
uint8_t status; /* 状态码 */
uint8_t payload[0]; /* 变长载荷 */
} RpcResponse;
/* 最大消息大小 */
#define RPC_MAX_MSG_SIZE 256
#define RPC_MAX_PAYLOAD_SIZE (RPC_MAX_MSG_SIZE - sizeof(RpcHeader) - 1)
#endif
4.3 客户端Stub实现
/**
* @file rpc_client.c
* @brief RPC客户端实现
*/
#include "rpc_protocol.h"
#include "rpc_transport.h"
#include <string.h>
#include <stdio.h>
/* 请求上下文 */
typedef struct {
uint8_t service_id;
uint8_t method_id;
uint8_t req_buffer[RPC_MAX_MSG_SIZE];
uint16_t req_len;
uint8_t resp_buffer[RPC_MAX_MSG_SIZE];
uint16_t resp_len;
uint8_t status;
volatile bool completed;
uint32_t timeout_ms;
} RpcCallContext;
static RpcCallContext g_call_ctx;
static uint8_t g_seq_num = 0;
/**
* @brief 同步RPC调用
* @param service_id 目标服务ID
* @param method_id 目标方法ID
* @param req_data 请求数据
* @param req_len 请求数据长度
* @param resp_data 响应数据缓冲区
* @param resp_len 输入:缓冲区大小, 输出:实际响应长度
* @param timeout_ms 超时时间
* @return 0成功,<0失败
*/
int32_t RpcCall(uint8_t service_id, uint8_t method_id,
const uint8_t *req_data, uint16_t req_len,
uint8_t *resp_data, uint16_t *resp_len,
uint32_t timeout_ms) {
/* 构建请求消息 */
RpcRequest *req = (RpcRequest*)g_call_ctx.req_buffer;
req->header.magic = RPC_MAGIC;
req->header.version = 0x01;
req->header.msg_type = MSG_TYPE_REQUEST;
req->header.service_id = service_id;
req->header.method_id = method_id;
req->header.payload_len = req_len;
if (req_len > 0 && req_data != NULL) {
memcpy(req->payload, req_data, req_len);
}
uint16_t total_len = sizeof(RpcHeader) + req_len;
/* 发送请求 */
printf("[RPC] 调用服务0x%02X 方法0x%02X, 载荷%d字节\n",
service_id, method_id, req_len);
if (RpcTransport_Send(g_call_ctx.req_buffer, total_len) < 0) {
printf("[RPC] 发送失败\n");
return -1;
}
/* 等待响应 */
g_call_ctx.completed = false;
g_call_ctx.timeout_ms = timeout_ms;
uint32_t start_tick = RpcGetTick();
while (!g_call_ctx.completed) {
/* 轮询接收 */
int32_t recv_len = RpcTransport_Recv(g_call_ctx.resp_buffer,
RPC_MAX_MSG_SIZE, 10);
if (recv_len > 0) {
RpcResponse *resp = (RpcResponse*)g_call_ctx.resp_buffer;
/* 校验魔数和类型 */
if (resp->header.magic != RPC_MAGIC ||
resp->header.msg_type != MSG_TYPE_RESPONSE) {
continue;
}
/* 匹配服务和方法 */
if (resp->header.service_id == service_id &&
resp->header.method_id == method_id) {
g_call_ctx.status = resp->status;
g_call_ctx.resp_len = resp->header.payload_len;
/* 拷贝响应数据 */
uint16_t copy_len = resp->header.payload_len;
if (copy_len > *resp_len) copy_len = *resp_len;
memcpy(resp_data, resp->payload, copy_len);
*resp_len = copy_len;
g_call_ctx.completed = true;
printf("[RPC] 收到响应, 状态=0x%02X, 载荷=%d字节\n",
resp->status, resp->header.payload_len);
return (resp->status == RPC_OK) ? 0 : -resp->status;
}
}
/* 超时检查 */
if (RpcGetTick() - start_tick > timeout_ms) {
printf("[RPC] 调用超时\n");
return -RPC_ERR_TIMEOUT;
}
}
return 0;
}
/* 便捷封装:无参数调用 */
int32_t RpcCallSimple(uint8_t service_id, uint8_t method_id, uint32_t timeout_ms) {
uint16_t resp_len = 0;
return RpcCall(service_id, method_id, NULL, 0, NULL, &resp_len, timeout_ms);
}
4.4 服务端Skeleton实现
/**
* @file rpc_server.c
* @brief RPC服务端实现
*/
#include "rpc_protocol.h"
#include "rpc_transport.h"
#include <string.h>
#include <stdio.h>
/* 服务方法原型 */
typedef int32_t (*RpcMethodHandler)(const uint8_t *req, uint16_t req_len,
uint8_t *resp, uint16_t *resp_len);
/* 服务方法表 */
typedef struct {
uint8_t method_id;
RpcMethodHandler handler;
const char *name;
} RpcMethodEntry;
/* 服务表 */
typedef struct {
uint8_t service_id;
const char *name;
RpcMethodEntry *methods;
uint8_t method_count;
} RpcServiceEntry;
#define MAX_SERVICES 16
static RpcServiceEntry *g_service_table[MAX_SERVICES] = {NULL};
static uint8_t g_service_count = 0;
/**
* @brief 注册服务
*/
int32_t RpcServer_RegisterService(RpcServiceEntry *service) {
if (g_service_count >= MAX_SERVICES) {
printf("[RPC-Server] 服务表已满\n");
return -1;
}
/* 检查服务ID冲突 */
for (int i = 0; i < g_service_count; i++) {
if (g_service_table[i]->service_id == service->service_id) {
printf("[RPC-Server] 服务ID 0x%02X 已存在\n", service->service_id);
return -1;
}
}
g_service_table[g_service_count++] = service;
printf("[RPC-Server] 注册服务: %s (ID=0x%02X, 方法数=%d)\n",
service->name, service->service_id, service->method_count);
return 0;
}
/**
* @brief 分发请求到对应服务方法
*/
static int32_t RpcServer_Dispatch(const RpcRequest *req,
uint8_t *resp_buffer, uint16_t *resp_len) {
/* 查找服务 */
RpcServiceEntry *service = NULL;
for (int i = 0; i < g_service_count; i++) {
if (g_service_table[i]->service_id == req->header.service_id) {
service = g_service_table[i];
break;
}
}
if (!service) {
printf("[RPC-Server] 未知服务: 0x%02X\n", req->header.service_id);
return -RPC_ERR_NO_SERVICE;
}
/* 查找方法 */
RpcMethodEntry *method = NULL;
for (int i = 0; i < service->method_count; i++) {
if (service->methods[i].method_id == req->header.method_id) {
method = &service->methods[i];
break;
}
}
if (!method) {
printf("[RPC-Server] 未知方法: 0x%02X\n", req->header.method_id);
return -RPC_ERR_NO_METHOD;
}
printf("[RPC-Server] 分发: %s.%s\n", service->name, method->name);
/* 调用方法处理函数 */
uint16_t payload_resp_len = RPC_MAX_PAYLOAD_SIZE;
int32_t ret = method->handler(req->payload, req->header.payload_len,
resp_buffer + sizeof(RpcHeader) + 1,
&payload_resp_len);
/* 构建响应头 */
RpcResponse *resp = (RpcResponse*)resp_buffer;
resp->header.magic = RPC_MAGIC;
resp->header.version = 0x01;
resp->header.msg_type = MSG_TYPE_RESPONSE;
resp->header.service_id = req->header.service_id;
resp->header.method_id = req->header.method_id;
resp->header.payload_len = payload_resp_len;
resp->status = (ret == 0) ? RPC_OK : RPC_ERR_INTERNAL;
*resp_len = sizeof(RpcHeader) + 1 + payload_resp_len;
return 0;
}
/**
* @brief 服务端主循环
*/
void RpcServer_Run(void) {
uint8_t rx_buffer[RPC_MAX_MSG_SIZE];
uint8_t tx_buffer[RPC_MAX_MSG_SIZE];
printf("[RPC-Server] 服务启动,监听请求...\n");
while (1) {
/* 接收请求 */
int32_t rx_len = RpcTransport_Recv(rx_buffer, RPC_MAX_MSG_SIZE, 100);
if (rx_len < (int32_t)sizeof(RpcHeader)) {
continue;
}
RpcRequest *req = (RpcRequest*)rx_buffer;
/* 校验 */
if (req->header.magic != RPC_MAGIC ||
req->header.msg_type != MSG_TYPE_REQUEST) {
continue;
}
printf("[RPC-Server] 收到请求: 服务0x%02X 方法0x%02X\n",
req->header.service_id, req->header.method_id);
/* 分发处理 */
uint16_t tx_len = 0;
RpcServer_Dispatch(req, tx_buffer, &tx_len);
/* 发送响应 */
RpcTransport_Send(tx_buffer, tx_len);
}
}
4.5 温度控制服务完整示例
/**
* @file svc_temp_control.c
* @brief 温度控制微服务实现
*/
#include "rpc_server.h"
#include "temp_sensor_hal.h"
#include "pwm_driver.h"
#include <string.h>
/* 服务状态 */
static float g_target_temp = 25.0f;
static float g_current_temp = 0.0f;
static uint8_t g_control_mode = 0; /* 0=手动, 1=自动 */
static uint16_t g_pwm_duty = 0;
/* 方法1: 设置目标温度 */
static int32_t Method_SetTarget(const uint8_t *req, uint16_t req_len,
uint8_t *resp, uint16_t *resp_len) {
if (req_len != sizeof(float)) {
return -RPC_ERR_INVALID_ARG;
}
memcpy(&g_target_temp, req, sizeof(float));
printf("[TempCtrl] 目标温度设置为 %.2f°C\n", g_target_temp);
*resp_len = 0;
return 0;
}
/* 方法2: 获取状态 */
static int32_t Method_GetStatus(const uint8_t *req, uint16_t req_len,
uint8_t *resp, uint16_t *resp_len) {
/* 读取当前温度 */
g_current_temp = TempSensor_Read();
/* 打包状态 */
typedef struct __attribute__((packed)) {
float current_temp;
float target_temp;
uint16_t pwm_duty;
uint8_t mode;
} StatusResp;
StatusResp *status = (StatusResp*)resp;
status->current_temp = g_current_temp;
status->target_temp = g_target_temp;
status->pwm_duty = g_pwm_duty;
status->mode = g_control_mode;
*resp_len = sizeof(StatusResp);
return 0;
}
/* 方法3: 紧急停止 */
static int32_t Method_EmergencyStop(const uint8_t *req, uint16_t req_len,
uint8_t *resp, uint16_t *resp_len) {
g_pwm_duty = 0;
PWM_SetDuty(0);
g_control_mode = 0;
printf("[TempCtrl] ⚠️ 紧急停止!\n");
*resp_len = 0;
return 0;
}
/* 方法表 */
static RpcMethodEntry g_temp_methods[] = {
{METHOD_SET_TARGET, Method_SetTarget, "SetTarget"},
{METHOD_GET_STATUS, Method_GetStatus, "GetStatus"},
{METHOD_EMERGENCY_STOP, Method_EmergencyStop, "EmergencyStop"},
};
/* 服务定义 */
static RpcServiceEntry g_temp_service = {
.service_id = SVC_ID_TEMP_CTRL,
.name = "TempControl",
.methods = g_temp_methods,
.method_count = sizeof(g_temp_methods) / sizeof(g_temp_methods[0]),
};
/* 控制循环(独立任务) */
void TempControl_Task(void) {
/* 注册服务 */
RpcServer_RegisterService(&g_temp_service);
while (1) {
if (g_control_mode == 1) { /* 自动模式 */
g_current_temp = TempSensor_Read();
/* 简单Bang-Bang控制 */
if (g_current_temp < g_target_temp - 0.5f) {
g_pwm_duty = 800; /* 80%加热 */
} else if (g_current_temp > g_target_temp + 0.5f) {
g_pwm_duty = 0; /* 停止加热 */
}
PWM_SetDuty(g_pwm_duty);
}
RpcDelayMs(100); /* 100ms控制周期 */
}
}
五、服务注册与发现

图4:服务注册与发现机制
点击下载高清图
5.1 嵌入式服务注册表
在资源受限环境中,使用静态注册表替代动态服务发现:
/**
* @file service_registry.h
* @brief 嵌入式服务注册表
*/
#ifndef SERVICE_REGISTRY_H
#define SERVICE_REGISTRY_H
#include <stdint.h>
#include <stdbool.h>
#define MAX_REGISTERED_SERVICES 16
#define SERVICE_NAME_MAX_LEN 16
/* 服务信息 */
typedef struct {
uint8_t service_id;
char name[SERVICE_NAME_MAX_LEN];
uint8_t version_major;
uint8_t version_minor;
uint8_t version_patch;
bool is_active;
uint32_t last_heartbeat; /* 最后心跳时间戳 */
uint16_t call_count; /* 调用计数 */
} ServiceInfo;
/* 注册表操作 */
int32_t Registry_Init(void);
int32_t Registry_Register(const ServiceInfo *info);
int32_t Registry_Unregister(uint8_t service_id);
int32_t Registry_UpdateHeartbeat(uint8_t service_id);
const ServiceInfo* Registry_Query(uint8_t service_id);
const ServiceInfo* Registry_QueryByName(const char *name);
int32_t Registry_GetAll(ServiceInfo *list, uint8_t *count);
#endif
/**
* @file service_registry.c
*/
#include "service_registry.h"
#include <string.h>
#include <stdio.h>
static ServiceInfo g_registry[MAX_REGISTERED_SERVICES];
static uint8_t g_reg_count = 0;
int32_t Registry_Init(void) {
memset(g_registry, 0, sizeof(g_registry));
g_reg_count = 0;
printf("[Registry] 注册表初始化完成\n");
return 0;
}
int32_t Registry_Register(const ServiceInfo *info) {
if (g_reg_count >= MAX_REGISTERED_SERVICES) {
return -1;
}
/* 检查重复 */
for (int i = 0; i < g_reg_count; i++) {
if (g_registry[i].service_id == info->service_id) {
printf("[Registry] 服务 0x%02X 已存在,更新信息\n", info->service_id);
memcpy(&g_registry[i], info, sizeof(ServiceInfo));
return 0;
}
}
memcpy(&g_registry[g_reg_count], info, sizeof(ServiceInfo));
g_reg_count++;
printf("[Registry] 注册服务: %s (ID=0x%02X, v%d.%d.%d)\n",
info->name, info->service_id,
info->version_major, info->version_minor, info->version_patch);
return 0;
}
int32_t Registry_UpdateHeartbeat(uint8_t service_id) {
for (int i = 0; i < g_reg_count; i++) {
if (g_registry[i].service_id == service_id) {
g_registry[i].last_heartbeat = GetSystemTick();
g_registry[i].is_active = true;
return 0;
}
}
return -1;
}
const ServiceInfo* Registry_Query(uint8_t service_id) {
for (int i = 0; i < g_reg_count; i++) {
if (g_registry[i].service_id == service_id) {
return &g_registry[i];
}
}
return NULL;
}
/* 心跳检查任务 */
void Registry_HeartbeatCheckTask(void) {
uint32_t now = GetSystemTick();
for (int i = 0; i < g_reg_count; i++) {
if (g_registry[i].is_active &&
(now - g_registry[i].last_heartbeat) > 30000) { /* 30秒超时 */
g_registry[i].is_active = false;
printf("[Registry] 服务 %s 心跳超时,标记为离线\n",
g_registry[i].name);
}
}
}
六、架构演进性能对比

图5:架构演进性能对比
6.1 测试环境
| 参数 | 配置 |
|---|---|
| 平台 | STM32H743 (480MHz Cortex-M7) |
| 内存 | 512KB SRAM + 2MB Flash |
| RTOS | FreeRTOS 10.4 |
| 测试工具 | DWT Cycle Counter |
6.2 关键数据解读
| 指标 | 单体固件 | 分层架构 | 模块化组件 | 微服务(同进程) | 微服务(独立进程) |
|---|---|---|---|---|---|
| 代码体积 | 128KB | 132KB | 138KB | 145KB | 168KB |
| 运行时内存 | 32KB | 34KB | 36KB | 42KB | 58KB |
| 启动时间 | 120ms | 125ms | 130ms | 145ms | 180ms |
| 故障隔离度 | 10 | 25 | 45 | 75 | 95 |
| 单次RPC延迟 | N/A | N/A | N/A | 15μs | 45μs |
6.3 权衡分析
微服务架构的代价:
- 代码体积增加 31%(128KB → 168KB)
- 内存占用增加 81%(32KB → 58KB)
- 启动时间增加 50%(120ms → 180ms)
微服务架构的收益:
- 故障隔离度提升 9.5倍(10 → 95)
- 支持独立OTA升级
- 团队可并行开发不同服务
推荐策略:在同进程微服务和独立进程微服务之间选择:
- 同进程微服务:通过函数指针表实现RPC,延迟仅15μs,适合大多数场景
- 独立进程微服务:需要MMU支持,适合高安全等级应用(汽车电子、医疗设备)
七、鸿蒙生态集成
7.1 OpenHarmony 服务化架构
OpenHarmony的分布式软总线天然支持微服务通信模式:
/* 基于HDF的传感器服务 */
#include "hdf_device_desc.h"
#include "hdf_sbuf.h"
#define SENSOR_SERVICE_NAME "sensor_service"
/* 服务接口定义 */
struct ISensorService {
struct IDeviceIoService ioService; /* 继承HDF基础服务 */
int32_t (*Read)(struct ISensorService *self, float *temp, float *hum);
int32_t (*Config)(struct ISensorService *self, uint32_t sample_rate);
int32_t (*Calibrate)(struct ISensorService *self);
};
/* 客户端调用 */
int32_t SensorClient_Read(float *temp, float *hum) {
struct HdfIoService *service = HdfIoServiceBind(SENSOR_SERVICE_NAME);
if (service == NULL) {
return HDF_FAILURE;
}
struct HdfSBuf *data = HdfSbufObtainDefaultSize();
struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
/* 发送RPC调用 */
int32_t ret = service->dispatcher->Dispatch(&service->object,
SENSOR_CMD_READ,
data, reply);
if (ret == HDF_SUCCESS) {
HdfSbufReadFloat(reply, temp);
HdfSbufReadFloat(reply, hum);
}
HdfSbufRecycle(data);
HdfSbufRecycle(reply);
HdfIoServiceRecycle(service);
return ret;
}
7.2 分布式能力扩展
利用HarmonyOS的分布式数据管理,微服务可跨设备协同:
/* 分布式温度监控:设备A采集,设备B显示 */
#include "distributed_kv_store.h"
/* 设备A:发布温度数据 */
void PublishTempToDistributedStore(float temp) {
KVStore *store = GetDistributedKVStore("temp_monitor");
Value value = {
.type = VALUE_TYPE_FLOAT,
.data.f = temp
};
Put(store, "living_room_temp", &value);
}
/* 设备B:订阅温度数据 */
void SubscribeTempFromDistributedStore(void) {
KVStore *store = GetDistributedKVStore("temp_monitor");
Subscribe(store, "living_room_temp", OnTempChanged);
}
static void OnTempChanged(const char *key, const Value *value) {
if (value->type == VALUE_TYPE_FLOAT) {
printf("远程温度更新: %.2f°C\n", value->data.f);
UI_UpdateTemperature(value->data.f);
}
}
八、常见问题与解决方案
| 问题 | 根因 | 解决方案 |
|---|---|---|
| RPC调用超时 | 服务端处理阻塞 | 设置异步回调,避免同步等待 |
| 服务循环依赖 | A调用B,B调用A | 引入事件总线,改为发布订阅模式 |
| 消息队列溢出 | 生产速度 > 消费速度 | 背压机制,丢弃或合并旧消息 |
| 版本兼容性 | 服务升级后接口变更 | 协议版本号,向后兼容设计 |
| 调试困难 | 分布式调用链难追踪 | 注入Trace ID,全链路日志 |
九、总结
本文系统阐述了嵌入式微服务架构的设计演进路径,核心要点如下:
- 服务边界划分遵循DDD思想,按核心域/支撑域/通用域划分,遵循单一职责、高内聚低耦合原则
- 轻量级RPC采用自定义二进制协议(8字节头 + 变长载荷),单次调用延迟可控制在15μs以内
- 服务注册发现使用静态注册表 + 心跳机制,避免引入重量级中间件
- 架构权衡需根据资源约束选择同进程或独立进程微服务,避免过度设计
在鸿蒙生态中,可结合HDF服务框架和分布式软总线,构建跨设备的微服务协同网络,真正实现"一次开发,多端部署"的万物互联愿景。
转载自:https://blog.csdn.net/u014727709/article/details/162623118
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐



所有评论(0)