按照领导的要求,要改造一台仪器,添加点功能,将测量数据上传到服务器。仪器测量节拍大概是20s,数据量目前不大,每次测量大概不到2M左右,且都是浮点数据和整形数据。
起初想用TCP长连接实现的,但考虑到现场环境。典型的制造业车间,电磁环境复杂,网络信号不稳,所以不考虑TCP长连接实现。短连接也不在考虑范围内,以后仪器数量多了之后频繁的建立连接开销也很大,服务器有可能受不了(阿里云的乞丐版)。所以选择用restful提交,http的通信可以多线程调度。
仪器控制程序是C#开发的,所以客户端最好是c#。服务端我想用springboot,很方便。
考虑到新增的上传功能不能影响之前的测量节拍,所以要多线程实现。可惜我又很懒,不想考虑线程协调问题,最后选择消息队列实现。
考虑到节省流量(服务器是按流量收费的),文件要压缩,C#下要实现文件压缩功能。
从测量文件中读取数据,将参数存入数据库,测量原始数据打包放在文件服务器上。
最后的技术方案就是C#做客户端,java构建服务端restful API进行上传
整体架构如下图:
使用的技术如下:
C#的Restful客户端:RestSharp
java的Restful服务端:springboot
C#端消息队列:NetMQ
C#端zip操作组件:DotNetZip
java端zip操作组件:Apache Commons Compress
服务端采用springboot的restful,POST方式,非常简单。
传输文件采用MultipartFile方式,因为客户端的ResrSharp只能采用这种方式传递文件
@RestController
@RequestMapping(value = "upload")
public class FileRestController {
Logger logger = LogManager.getLogger(FileRestController.class);
@RequestMapping(value = "file", method = RequestMethod.POST)
public
@ResponseBody
RestResult getZipFile(@RequestParam("file") MultipartFile file) throws IOException, URISyntaxException {
RestResult result = new RestResult();
if (!file.getName().isEmpty()) {
InputStream stream = file.getInputStream();
// String directory = FileRestController.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
String directory = "/usr/local/haliang/files/";
try {
directory = URLDecoder.decode(directory, "utf-8");
} catch (java.io.UnsupportedEncodingException e) {
return null;
}
FileOutputStream fs = new FileOutputStream(directory + file.getOriginalFilename());
logger.info("文件所在的目录: " + directory + "/files/" + file.getOriginalFilename());
byte[] buffer = new byte[1024 * 1024];
int bytesum = 0;
int byteread = 0;
while ((byteread = stream.read(buffer)) != -1) {
bytesum += byteread;
fs.write(buffer, 0, byteread);
fs.flush();
}
fs.close();
stream.close();
logger.info("成功接收文件: " + directory + file.getOriginalFilename());
}
return result;
}
}
客户端架构如下图:
NetMQ 是 ZeroMQ的C#移植版本。
NetMQ (ZeroMQ to .Net),ZMQ号称史上最快中间件。
它对socket通信进行了封装,使得我们不需要写socket函数调用就能完成复杂的网络通信。
它跟Socket的区别是:普通的socket是端到端的(1:1的关系),而ZMQ却是可以N:M的关系,人们对BSD套接字的了解较多的是点对点的连接,点对点连接需要显式地建立连接、销毁连接、选择协议(TCP/UDP)和处理错误等,而ZMQ屏蔽了这些细节,让你的网络编程更为简单。
它是一个消息处理队列库,可在多个线程、内核和主机盒之间弹性伸缩。和一般意义上的消息队列产品不同的是,它没有消息队列服务器,而更像是一个网络通信库。从网络通信的角度看,它处于会话层之上,应用层之下,属于传输层。
zeromq将消息通信分为4种模型,分别是一对一结对模型(Exclusive-Pair)、请求回应模型(Request-Reply)、发布订阅模型(Publish-Subscribe)、推拉模型(Push-Pull)。这4种模型总结出了通用的网络通信模型,在实际中可以根据应用需要,组合其中的2种或多种模型来形成自己的解决方案。
最简单的1:1消息通信模型,用来支持传统的 TCP socket模型,主要用于进程内部线程间通信。可以认为是一个TCP Connection,但是TCP Server只能接受一个连接。采用了lock free实现,速度很快。数据可以双向流动,这点不同于后面的请求响应模型。(不