2. 自适应应用的生命周期管理
任务说明
本案例目标是在AUTOSAR AP中间件框架下,基于ara::com通信模型实现一个服务发布(Service Provider)与订阅(Service Subscriber)的最小可运行闭环。服务端发布一个计算两数之和的服务接口,客户端通过服务发现机制找到该服务并远程调用,最终在客户端侧获得计算结果。
实现方案
采用AUTOSAR AP标准中ara::com的Skeleton(服务端)与Proxy(客户端)模式。服务接口使用IDL定义,通过aracom代码生成器生成骨架代码。本案例直接提供生成后的C++实现代码,并配套JSON格式的服务清单(Service Manifest)用于服务发现配置。通信中间件基于SOME/IP协议,通过本地回环地址(127.0.0.1)完成进程间通信。
代码实现
1. 服务接口定义(CalculatorInterface.idl)
// 服务接口IDL定义
interface CalculatorService {
method uint32 Add(uint32 a, uint32 b);
};
2. 服务端实现(service_provider.cpp)
#include <ara/com/skeleton/ServiceSkeletonImpl.h>
#include <ara/com/runtime.h>
#include <memory>
#include <thread>
#include <chrono>
#include <iostream>
// 生成代码头文件(由aracom工具从IDL生成)
#include "gen/CalculatorServiceSkeleton.h"
using namespace ara::com;
// 服务端Skeleton实现类
class CalculatorServiceImpl : public CalculatorServiceSkeleton {
public:
explicit CalculatorServiceImpl(ara::core::InstanceSpecifier instance)
: CalculatorServiceSkeleton(instance) {}
// 实现Add方法
ara::core::Future<uint32_t> Add(uint32_t a, uint32_t b) override {
ara::core::Promise<uint32_t> promise;
promise.set_value(a + b);
return promise.get_future();
}
};
int main() {
// 初始化运行时
ara::com::Runtime::GetInstance().Initialize();
// 服务实例标识(需与Manifest中一致)
ara::core::InstanceSpecifier specifier("provider/root/CalculatorService");
// 创建并注册服务
auto service = std::make_shared<CalculatorServiceImpl>(specifier);
auto offerHandle = service->OfferService();
std::cout << "[Provider] Service offered. Waiting for requests..." << std::endl;
// 保持进程运行
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
3. 客户端实现(service_subscriber.cpp)
#include <ara/com/runtime.h>
#include <ara/com/proxy/ServiceProxyImpl.h>
#include <memory>
#include <iostream>
#include <thread>
#include <chrono>
// 生成代码头文件
#include "gen/CalculatorServiceProxy.h"
using namespace ara::com;
int main() {
// 初始化运行时
ara::com::Runtime::GetInstance().Initialize();
// 服务实例标识(需与Provider一致)
ara::core::InstanceSpecifier specifier("provider/root/CalculatorService");
// 创建Proxy并查找服务
auto proxy = std::make_shared<CalculatorServiceProxy>(specifier);
// 等待服务发现完成(最多等待5秒)
bool found = false;
for (int i = 0; i < 50; ++i) {
auto state = proxy->GetServiceHandle().GetState();
if (state == ServiceHandle::State::kAvailable) {
found = true;
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (!found) {
std::cerr << "[Client] Service not found after timeout." << std::endl;
return -1;
}
std::cout << "[Client] Service discovered. Calling Add(3, 5)..." << std::endl;
// 调用远程方法
auto future = proxy->Add(3, 5);
auto result = future.get();
std::cout << "[Client] Add(3, 5) = " << result << std::endl;
return 0;
}
4. 服务清单配置(manifest.json)
{
"serviceInterfaces": [
{
"name": "CalculatorService",
"methods": [
{
"name": "Add",
"parameters": [
{"name": "a", "type": "uint32"},
{"name": "b", "type": "uint32"}
],
"return": {"type": "uint32"}
}
]
}
],
"serviceInstances": [
{
"name": "provider/root/CalculatorService",
"interface": "CalculatorService",
"communication": {
"kind": "someip",
"network": "local",
"port": 30509
}
}
]
}
构建与运行
# 1. 使用aracom工具从IDL生成骨架代码
aracom --idl CalculatorInterface.idl --output-dir gen
# 2. 编译服务端
g++ -std=c++17 -I. -Igen service_provider.cpp gen/CalculatorServiceSkeleton.cpp \
-L/usr/local/lib -lara_com -lsomeip -o provider
# 3. 编译客户端
g++ -std=c++17 -I. -Igen service_subscriber.cpp gen/CalculatorServiceProxy.cpp \
-L/usr/local/lib -lara_com -lsomeip -o subscriber
# 4. 启动服务端(终端1)
./provider
# 5. 启动客户端(终端2)
./subscriber
验证方法
在终端1中启动provider后,观察输出显示服务已注册。在终端2中启动subscriber,若客户端输出[Client] Add(3, 5) = 8,则说明服务发布、服务发现、远程调用全链路工作正常。判定标准:客户端成功获取到计算结果8,且服务端无异常退出。
关键点说明
- 服务标识一致性:Provider和Proxy必须使用相同的
InstanceSpecifier字符串,且与manifest.json中的服务实例名称完全匹配,否则服务发现会失败。 - 服务发现机制:客户端通过Proxy的
GetServiceHandle().GetState()轮询服务状态,实际项目中可注册状态变更回调实现异步通知。 - 通信配置:本案例使用本地回环地址和固定端口30509,实际部署时需根据网络环境调整manifest中的通信参数。