大名鼎鼎的memcached恐怕沒人不知道吧!hessian是一種遠程調(diào)用的機制,類似與web service,不過它是使用自己的序列化協(xié)議.
那么,為什么要把hessian的序列化協(xié)議和memcached結合起來實現(xiàn)緩存的讀取呢?
有過使用memcached的經(jīng)驗的人會了解到,php+memcached的性能是最好的,java+memcached的性能比較差,其主要原因就是在于java本身的序列化機制很慢.
我做了個簡單的測試,一個UserData類,有一個字符串屬性,一個日期屬性,一個double屬性,分別用java,hessian來序列化一百萬次,結果讓人吃驚,不止是hessian序列化的速度要比java的快上一倍,而且hessian序列化后的字節(jié)數(shù)也要比java的少一倍.因為我在測試的時候只是做了序列化這部分的工作,并沒有把序列化后的結果放到網(wǎng)絡上傳輸,所以,實際中的性能hessian應該會更好!
既然hessian的序列化協(xié)議要比java本身的好,而memcached客戶端的性能又在很大程度上依賴與對象的序列化.所以,我就決定把我的cache實現(xiàn)中序列化這部分的工作改成用hessian來實現(xiàn)了.
我用的memcached客戶端是用的danga.MemCached包,主要是改動了MemCachedClient的get方法及set方法,在set方法中改為調(diào)用hessian的序列化:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//修改以前的序列化代碼:
//(new ObjectOutputStream( bos )).writeObject( value );
//修改后的序列化代碼:
serializeByHessian(bos, value);
val = bos.toByteArray();
serializeByHessian方法如下:
protected void serializeByHessian(OutputStream os, Object object) throws IOException {
AbstractHessianOutput out = new Hessian2Output(os);;
SerializerFactory serializerFactory = getSerializerFactory();
out.setSerializerFactory(serializerFactory);
out.startReply();
out.writeObject(object);
out.completeReply();
out.flush();
}
在get方法中主要是修改了這個方法調(diào)用的類ContextObjectInputStream的readObject方法:
在ContextObjectInputStream中覆蓋了readObjectOverride方法:
protected Object readObjectOverride() throws IOException, ClassNotFoundException {
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
ClHessian2Input in = new ClHessian2Input(is, this.mLoader);
in.setSerializerFactory(getSerializerFactory());
int code = in.read();//"r"
int major = in.read();//>=2
int minor = in.read();//0
Object value = in.readObject();
is.close();
return value;
}
因為我的框架是基于osgi的,所以我重載了Hessian2Input,把classloader作為參數(shù)傳進去,否則hessian在反序列化的時候會找不到類.如果你沒有用osgi框架的話, ClHessian2Input in = new ClHessian2Input(is, this.mLoader);這行代碼就可以直接用: Hessian2Input in = new Hessian2Input(is);
這樣修改就基本完成了.
我把memcached client的序列化協(xié)議改為hessian也有另外一個系統(tǒng)架構的原因,那就是因為我的服務層邏輯都是用java+spring+osgi的方式實現(xiàn),而web層則是用php實現(xiàn),兩者之間通訊已經(jīng)是采用hessian的遠程調(diào)用.所以,部分緩存數(shù)據(jù)在服務層通過java設置到memcached服務器中,在php中一樣可以用memcached php client讀取出來.(php的memcached client我用的是memcached-client.php,而不是php擴展,所以一樣可以修改memcached-client.php的序列化機制)