jackey3316 2008-06-25 23:27
浏览 361
已采纳

关于blob对象(图片)的缓存和提取问题

前段时间给客户做了一个会议签到系统
系统中涉及到这么一个问题:
用户签到的时候有一个页面显示当前签到人的照片和最近签到的6个人的照片,
照片数据都以blob对象存储在数据库中的,
为了在页面上显示照片,我直接写了一个servlet来处理照片的请求,
servlet中直接把blob二进制流输出给jsp界面。
jsp以的形式向servlet发送请求来获取照片
servlet中以
ServletOutputStream out = res.getOutputStream();
Blob temp = photo.getPhoto();
InputStream is = temp.getBinaryStream();
byte buffer[] = new byte[256];
while (is.read(buffer, 0, 256) != -1) {

out.write(buffer);
}

out.flush();
的形式响应。

每当有人签到,jsp页面就自动刷新一次来获取新的6张照片

这样设计有几个瓶颈
1、照片本身大小比较大,每张都是200+k,每次刷新所有的照片都要重新到后台去获取,对网络的要求比较高,而且如果多个人同时使用这个页面刷新的话,更是问题
2、每次请求的blob数据都需要到后台数据库中取数据,而且都是 并发的请求,对数据库的连接和数据库都有很大的压力,容易使服务down了

试着改进过,因为每次请求的6张照片中正常情况有5张是重复的,所以我想用hashmap把查出来的结果缓存起来,下次有请求来了,如果在缓存中有了,就直接在缓存中取。没有再到数据库中取,缓存中到了一定数量,再把缓存全部清了,否则肯定会占用大量内存。

但是这样又有问题,java的回收机制自动把我hashmap中的blob对象给清掉了。每次取到的persistence是有的可是到persistence中取blob却是空的了。所以jsp界面显示的照片都是空的。

不知道有没有高人能提出一个好的解决方案。探讨探讨,如何改进。或者重新设计。

不胜感激!

[b]问题补充:[/b]
HashMap问题blob对象被清 是这样的
HashMap本来就是放在单子实例中的,肯定也是static

public class AnalyseDAO extends BasicDAO {
private static AnalyseDAO _instance= new AnalyseDAO();;
public static AnalyseDAO getInstance() {
if (_instance == null) {
_instance = new AnalyseDAO();
}
return _instance;
}
private static HashMap photohash = new HashMap();

public TCifPhoto getCifPhoto(String stuempNo){
if(photohash.size()>=50){
photohash.clear();
}
if(photohash!=null && photohash.get(stuempNo)!=null){
TCifPhoto tmp= (TCifPhoto)photohash.get(stuempNo);
if(tmp.getPhoto()==null){
System.out.println("omg that's it lob is empty");
}
return tmp;
}else{
Session s = getSession();
String sql = " from TCifPhoto cif where cif.stuempNo= '"+stuempNo+"'";
try {
Query q = s.createQuery(sql);
List list = q.list();
if(list!=null&&list.size()>0){
return (TCifPhoto)list.get(0);
}else{
return null;
}
} catch (HibernateException he) {
throw he;
}
}

}

这样的设计在tomcat上跑一点问题都没有 HashMap中的数据也能取到,可是一但到websphere上HashMap中存储的TCifPhoto 这个persistence还在,就是persistence里面的二进制lob对象没有了,从代码里看出系统输出了“omg that's it lob is empty”就很明显知道问题的状况。可以判定websphere把lob字段给清了。

或者另一种架设是websphere用到了对lob字段的lazyload的方式或者别的。没有找到相应的文档资料。
[b]问题补充:[/b]
又补充讨论一下:
现在看来armorking说的应该是对的,blob的操作是逻辑指针,数据库连接释放后就不能取到值了。而tomcat和websphere数据库连接的管理方式又别,所以同样的代码,tomcat能正常运行,websphere就不行。(这有待继续挖掘区别,o(∩_∩)o...)。

其实把blob缓存,我觉得不是最好的方案吧,即时做成byte[]缓存解决了原先的问题,但是,每张图片有300k,在签到峰值时期,每个用户客户端与服务器的网络流量将达到很高的程度,假设刷新为2s一次 300K*6=1.8M ,接近1M/s。再加上如果有多个客户端在刷。服务器流量将受到考验。

所以我考虑是不是可以把照片缓存到每个客户端ie缓存中。首先把第一次请求的照片数据从数据库中取出缓存到服务器硬盘上。而客户端直接通过url来存取服务器上的照片。每次刷新后,相同的照片ie会自动取ie缓存中的照片,而不会再到服务器上取,这样就能解决原来的两个问题了。

不知道大家有什么建议?

  • 写回答

7条回答 默认 最新

  • т 2008-06-27 09:22
    关注

    从lz提供的source来看
    blob数据检索出来以后,并没有被放到photohash中

    另外,根据sql的Blob的文档
    [quote]
    默认情况下,驱动程序使用 SQL locator(BLOB) 实现 Blob,这意味着 Blob 对象包含一个指向 SQL BLOB 数据而不是数据本身的逻辑指针。Blob 对象在它被创建的事务处理期间有效。
    [/quote]

    TCifPhoto.getPhoto()的类型如果是Blob型而不是 byte[]的话,
    一旦检索事务处理结束了,的确有可能变成null

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

悬赏问题

  • ¥15 安装svn网络有问题怎么办
  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献