Hadoop分布式文件系统(HDFS)是一个高度容错的分布式文件系统,而且运行在一般配置的服务器上就能够拥有很高的可靠性。HDFS上的数据通过流式读取,能够提供高吞吐量的数据访问,一般用来存储大文件,同时可以使用MapReduce对数据直接分析处理。
云平台使用HDFS的需求:我们在给客户远程处理时要求全程录像,这些录像客户可以随时查看,所以首先我们需要一个空间存放大量的录像文件,还要能够满足录像播放的吞吐量,同时我们还要对视频进行分析处理,解析出远程录像中执行过的所有命令,而且还能根据命令定位到录像位置,直接查看当时的操作步骤。
HDFS满足以上的所有需求,同时提供了非常方便的JAVA API,还可以方便的通过WEB、命令行监控管理。
后来为了统一,把文档、工具、图片、附件等都放在了HDFS中,统一的接口上传、读取、下载,目前稳定性、安全性、可靠性都表现不错。在功能实现中主要遇到如下几个典型问题,现分享出来,供大家参考。
1、playVideo如何实现
HDFS支持流式访问,那么浏览器可以边加载边播放,前端直接使用video/mp4标签,调用后台playVideo的接口,后台JAVA根据HttpServletRequest和HttpServletResponse两个封装类操作Http的Request和Response,实现录像播放、快进的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <source :src= "videoApi" type= "video/mp4" > this .videoApi = 'playVideo?videoPath=' + row.videoPath public void playVideo( @RequestParam ( "videoPath" ) String videoPath, HttpServletRequest req, HttpServletResponse resp) final long fileLength = fs.getFileStatus(path).getLen(); resp.setHeader( "Content-type" , "video/mp4" ); OutputStream out = resp.getOutputStream(); if (range == null ) { /* 从头播放 */ count = fileLength; } else {/* 快进 */ long start = Long.valueOf(range.substring(range.indexOf( "=" ) + 1 , range.indexOf( "-" ))); count = fileLength - start; } IOUtils.copyBytes(in, out, count, true ); |
2、前台如何显示HDFS中图片
由于HDFS文件前端无法直接显示,需要通过接口才能读取,要想实现前端直接使用IMG标签,就需要通过NGINX来对请求的URL进行重写,将所有/image/开头的全部重写指向HDFS上的文件读取地址,前端即可直接用IMG标签显示图片。
1 2 3 4 5 6 7 8 9 10 11 12 13 | <img src= "/image/cs.png" /> location /image/ { rewrite ^/image/(.*) /webhdfs/v1/image/$ 1 ?op=OPEN&namenoderpcaddress= 127.0 . 0.1 : 9000 &offset= 0 break ; proxy_pass http: //datanodes/; proxy_redirect off; #proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; add_header Content-Type "image/png" ; expires 30d; proxy_cache_valid 200 304 301 302 10d; proxy_cache_valid any 1d; proxy_cache_key $host$uri$is_args$args; } |
3、文件空格特殊字符乱码问题
如果文件中存在空格、括号等特殊字符,在HDFS中存储没有任何问题,但是下载的时候不同浏览器都会出现乱码、空格变成+的问题,在后台SERVICE层对文件名称和resp做了如下处理。
1 2 3 4 5 6 7 | if (userAgent.contains( "MSIE" )||userAgent.contains( "Trident" )) { fileName = URLEncoder.encode(fileName, "UTF-8" ); } else { //非IE浏览器的处理: fileName = new String(fileName.getBytes( "UTF-8" ), "ISO-8859-1" ); } resp.addHeader( "charset" , "utf-8" ); resp.setCharacterEncoding( "utf-8" ); |
关于远程处理录像分析、代码定位的功能还在研发中,敬请期待。
云平台: https://cs.enmotech.com/cloudPlatform