Ticket #66 (new Bug) — at Version 1
mongo硬缓存GZIP数据存取异常
| Reported by: | huangxianduan | Owned by: | huangxianduan |
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | 报价库 | Version: | 报价库4.0 |
| Keywords: | GZIP | Cc: | |
| Due Date: | 15/11/2011 |
Description (last modified by huangxianduan) (diff)
异常信息
[08-30 10:38:42.841] 2011-08-30 10:38:42,841 [http-app-a-8081-5887$1521484495] ERROR cn.com.pconline.core.r.MongoRClientHelper - [M
ongoRClientHelper] get cache:http://pdlib.pconline.com.cn/product/service2011/product_forum.jsp?pid=431809&style=1&time=7200 fail,me
ssage:java.io.IOException: Not in GZIP format
定位是R存/取mongo硬缓存时对较长的数据做GZIP压缩/解压有问题
排查及解决
- 测试R写硬缓存数据GZIP压缩是否有问题(报价前台是要求内容超过1024个字),测试GZIP压缩是没有问题的。
- 测试R读取硬缓存GZIP数据解压是否有问题(mongo中保存了内容有保存了是否是压缩状态),测试如果数据标识了是GZIP的,读取解压也正常。
- 怀疑是不是GZIP的API有bug呢,连续的用1做GZIP压缩写到mongo中,再用2解压读取出来,也是没有问题的。
- 对单条数据进行多次的压缩和解压测试,每次内容不一样,有时长有时短,这个偶尔会重现异常,有些眉目了,怀疑是特殊字符的问题,但用报错的内容重新压缩再读取又没问题了,还是悲剧,不能定位到问题在哪。
- 实在没办法,还是返回头仔细检查代码的写入和读取的判断是否一致,最后在代码上发现了写的判断有问题,代码如下:
public void setContent(byte[] content) { if (content != null){ if(content.length > ZIP_SIZE) {//内容长度大于1024,请注意并没有else ByteArrayOutputStream bos = null; GZIPOutputStream gzip = null; try { bos = new ByteArrayOutputStream(); gzip = new GZIPOutputStream(bos); gzip.write(content); gzip.flush(); gzip.finish(); gzip.close(); bos.flush(); content = bos.toByteArray(); this.zip = true;//压缩,保存到数据库做标记 } catch (IOException e) { e.printStackTrace(); this.zip = false; } finally { try { if (bos != null) { bos.close(); } } catch (IOException e) { } } }//为什么没有else呢??? this.size = content.length; } this.content = content; } 再来看看读取的方法 public byte[] getContent() { if (!zip) { return content; } else {//只要数据库标识是GZIP的就用GZIP解压读取 byte[] result = null; ByteArrayInputStream bis = null; GZIPInputStream gzip = null; ByteArrayOutputStream baos = null; try { bis = new ByteArrayInputStream(content); gzip = new GZIPInputStream(bis); byte[] buf = new byte[1024]; int num = -1; baos = new ByteArrayOutputStream(); while ((num = gzip.read(buf, 0, buf.length)) != -1) { baos.write(buf, 0, num); } baos.flush(); result = baos.toByteArray(); } catch (Exception ex) { throw new RuntimeException(ex); } finally { try { if (gzip != null) { gzip.close(); } if (bis != null) { bis.close(); } if (baos != null) { baos.close(); } } catch (Exception e) { } } return result; } }
- 问题很明显了,当第一次写入的数据长度大于1024的以GZIP格式写入,但第二次再更新写入是数据长度小于1024是却没有改变GZIP的状态,这样导致读取是还是当做GZIP格式来解压读取,肯定是会报格式不对的异常的。
Note: See
TracTickets for help on using
tickets.
![(please configure the [header_logo] section in trac.ini)](http://www1.pconline.com.cn/hr/2009/global/images/logo.gif)