赵明芳 刘军 杨青 赵世伟
【摘要】基于gRPC框架设计实现电磁频谱监测系统中间件,主要包括:定义gRPC服务、实现客户端与服务端功能。实践表明该方法通用性好,适用于架构分布式测试系统,能够满足自动测试方向的需求。
【关键词】电磁频谱监测系统;中间件;远程过程调用;gRPC
中图分类号:TN92 文献标识码:A 文章编号:1673-0348(2020)018-084-03
Abstract: Based on the gRPC framework, a design and realization method of middleware in electromagnetic spectrum monitoring system including gRPC service defining, realizing client and server functions is presented in this paper. Good testing result shows that this method has good versatility, is suitable for the architecture of distributed test system, and can meet the needs of automatic testing.
Key words: Electromagnetic Spectrum Monitoring System; middleware; Remote Procedure Call; gRPC
1.引言
隨着计算机技术和网络通信技术的发展,分布式技术在计算机的工程应用领域,例如:数据信息管理、自动化等方面取得快速发展,并应用于自动测试系统的分布式部署中,即基于局域网与互联网,把分散在不同地点、不同测试能力的计算机、设备组合在一起,实现远程自动化测试与测试资源共享。电磁频谱监测系统属于分布式测试系统,它具备的一个重要能力是远程过程控制功能,中间件技术为这种分布式架构方法提供了有力保障,使用该技术可独立于平台与语言实现远程过程调用、数据库访问、消息传递等服务,从而实现电磁频谱监测系统中不同监测角色(如:客户端、服务器、设备)的灵活组态、远程测试、以及资源共享与管理。
分布式测试系统中,各种应用不是部署在一个进程(/主机)中,通常基于RPC(Remote Procedure Call,远程过程调用)协议实现对远程计算机服务的调用。RPC遵从server/client模型,实际使用时,客户端调用服务端提供的接口就如同本地调用,且不需要开发网络通信和协议层的功能,只需关心业务相关的服务。目前有多种RPC框架用于开发实现网络进程间通信,例如:Dubbox 、thrift ,gRPC等。其中gRPC 框架是一个由谷歌开发的语言中立、平台中立、开源的 RPC 框架,它面向 HTTP/2 设计、使用 protobuf 作为数据序列化协议,并且具有解析速度快,序列化数据体积小,可扩展性高,使用简单等特性,相比其他RPC框架而言,发展空间更大。
2. 电磁频谱监测系统中间件设计与实现
2.1 整体框架设计
实际的测试场景中,监测系统的客户端与服务端物理位置分离,两端通过网络连接,中间件位于客户端与服务端中间,实现了两者之间的远程应用程序调用、数据序列化与数据传输功能。客户端是用户业务的入口,接收用户的监测意图,即服务消费方,通过中间件调用服务端提供的对应服务。该服务执行时,操作监测设备,获取测量数据,经服务端分析、处理后再经过中间件将测量结果返回客户端,从而实现客户端的业务功能。
远程过程调用中间件框架如图1所示:
2.2 gRPC安装与部署
基于gRPC框架开发中间件,需要预先在目标平台上安装gRPC库、配置 gRPC运行环境、安装 protocol buffer 以及gRPC插件来编译系统定义的服务。首先,确定目标平台和语言,这里选择Windows操作系统,目标语言为C++;接着,安装目标语言的IDE开发环境(Visual Studio 2015);最后,通过vcpkg包管理工具便捷地实现第三方开发库(gRPC库等)的管理以及与IDE的集成。
2.3 定义gRPC服务
首先,按照要求生成gRPC服务接口。gRPC通过 Protobuf(Google protocol buffers)定义服务以及生成客户端与服务端的接口执行代码。Protobuf 是谷歌提出的一种数据序列化协议,它的语言无关、平台无关、可扩展的特性,使得它十分适合用于gRPC框架实现数据传输。它最大的特点是能够根据用户自定义的远程调用服务文件(.proto文件)转换成目标语言的头文件与接口实现文件,从而用户可以方便地调用服务接口函数,实现客户端请求的服务功能。定义gRPC服务需要两步:
1) 编写proto文件
proto文件相当于待传输的消息模板,它定义了需要传输的数据本身,主要包括服务端与客户端的接口和消息。
·接口:是客户端与服务端远程过程调用的函数接口,该接口定义可表达四种类型RPC方法(例如:简单RPC、流式RPC)。接口定义需遵循规定的格式,即由service 关键字引导具体的服务接口名称,大括号内包含具体的RPC方法(服务接口函数)列表,格式如下:
service 服务接口名称
{
rpc 函数名(请求) returns (响应){ }
......
}
·消息:定义不同消息类型(例如:enum,message)包含的字段。格式如下:
消息类型关键字消息名称
{
消息字段1;
......
消息字段n;
}
2) 编译proto文件
由于proto文件不能直接使用,也不能直接传输,所以需要通过protobuf编译器(protoc.exe),将proto文件转换为目标语言的头文件和源文件(C++语言对应的是.h与.cc文件),生成的文件中包含了对上述proto文件中定义的消息字段的读写函数,以及服务端与客户端的接口调用函数。经过这一步就将语言中立的proto文件的信息转换为接口与消息的C++类(包含数据与方法),下一步就是在生成的目标语言代码的基础上,开发服务端与客户端的功能。
2.4 实现服务端
首先,VS2015新建server项目(控制台项目),并设置项目属性,主要包括:
1) 添加gRPC的宏定义:_WIN32_WINNT=0x0600;
2) 指定目标语言的头文件(.h)和源文件(.cc)所在目录,并将源文件添加到项目;
3) 添加windows socket库ws2_32.lib。
接着,编码实现服务端接口功能:按照上述proto文件定义的service服务接口,依次实现包含的服务接口函数功能,即从自动生成的接口类 Service(.grpc.pb.h 文件中,自动生成的服务接口文件。)派生自定义C++类,并重写该类的服务端接口虚函数。代码段示例:
//文件xx.grpc.pb.h中定义的server接口
class Service : public ::grpc::Service
{
public:
Service();
virtual ~Service();
virtual ::grpc::Status teamFile(::grpc::ServerContext* context,
const::DEPARTMENT::Identity* request, ::DEPARTMENT::Profile* response);
};
//类TeamService派生自类Service,需重写接口函数teamFile,实现服务端功能。
class TeamService final : public teamData::Service
{
public:
TeamService ();
virtual ~ TeamService ();
public:
Status teamFile(ServerContext* context, const Identity* request, Profile* response) override;
private:
void editTeam(const string& id, const string& name, Gender gender);
private:
map
};
最后,构建并启动server端服务,监听指定的地址和端口,等待接收来自客户端的服务请求。代码段示例:
int main(int argc, char** argv)
{
std::string server_address("127.0.0.1:50051"); //server端监听地址和端口
TeamService service; //服务类对象
ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr
cout << "Server listen on" << server_address << endl;
server->Wait();
return 0;
}
2.5 实现客户端
首先,新建client项目,并设置项目属性,方法同server端项目属性设置方法。
接着,编码实现client功能:按照proto文件中定义的接口,调用client端同名接口函数,从而测试 server端服务接口功能是否正确。开发客户端功能不必像实现server端功能那样编码实现具体的服务实现过程,而是委托Stub类对象调用客户端的接口函数即可。
最后,编译生成client项目,查错直至成功。
2.6 运行测试
基于gRPC框架实现的远程过程调用,以server/client模型实现。实际程序员做的工作就是在目标IDE中按照gRPC要求的接口、数据规范分别实现服务端与客户端的功能,而gRPC框架实现了两端的通信,所以服务端与客户端的程序编译生成成功后,可直接测试服务接口功能。
测试方法是:通过分别运行客户端与服务端程序,客户端向服务端发送服务请求,验证是否调用成功服务端接口函数,并获得预期结果。具体步骤如下:
step1.根据目标平台与版本,选择并打开client端与server端可执行程序所在目录;
step2.运行server端可执行程序,根据提示信息,确认服务端是否构建并运行成功,并进入监听状态;
step3.运行client端可执行程序:根据命令行提示输入请求命令,进行服务接口测试,查看server端的响应结果,并验证。
3. 结论
基于gRPC框架设计实现中间件,是将复杂的系统模块功能或业务拆分为多个服务功能,且每部分可独立并行开发、测试以及环境部署,实现了功能高内聚、接口低耦合。各服务进程独立,互相协作配合,实现用户业务功能。同时gRPC框架完成了网络数据传输与序列化,能够有效提升网络传输效率。该远程过程调用中间件设计实现方法已应用于某电磁频谱监测系统软件开发中,测试结果表明其平台适应性好,中间件可靠、稳定,传输数据体积小、速度快,能够满足电磁频谱监测系统分布式部署与测试需求。
参考文献:
[1] 刘龙,王伟平,刘远飞.自动测试系统的发展现状及前景[J].飞机设计, 2007(04):71-74.
[2] 马雄.基于微服务架构的系统设计与开发[D].南京:南京邮电大学,2017.
[3] 宋瑾.基于ProtocolBuffer协议的服务端-客戶端通信[J].电脑编程技巧与维护,2014(12):100-101.
[4] 刘宏,吴江.分布式对象中间件技术[J].现代电子技术,2003(08):91-94.