<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    心有多大舞臺便有多大

    Embrace changes, pursue excellence, share niceness.

    hessian序列化協(xié)議+memcached的緩存存取

    大名鼎鼎的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的序列化機制)


    posted on 2008-06-18 10:04 pony 閱讀(7875) 評論(11)  編輯  收藏 所屬分類: Java

    評論

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-06-18 10:17 pony

    另外附帶說一句,我的經(jīng)驗,在使用memcached的時候,客戶端在創(chuàng)建socket連接時最好把nagle設置為false.熟悉tcp協(xié)議的都知道setTcpNoDelay有什么作用.如果Tcp_NoDelay被設置為true,那么發(fā)送數(shù)據(jù)包時將使用nagle算法對要發(fā)送的數(shù)據(jù)進行緩存處理,只有當達到一定數(shù)量之后才把包發(fā)送出去,設置為false則立即發(fā)送包.對于memcached緩存,一般我們放進去的數(shù)據(jù),以及發(fā)送的get命令都是很小的包,為了將數(shù)據(jù)及時傳輸出去,所以要禁用nagle.  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-06-18 10:35 CHINA BAIDU

    不錯1!  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-06-18 12:19 dennis

    @pony
    很好的帖子,不知道換成了hession有沒有測試數(shù)據(jù)?
    對于setTcpNoDelay說反了吧?setTcpNoDelay為true,就是設置TCP_NODELAY,也就是禁掉Nagle算法;默認就是false,表示啟用Nagle算法。禁掉Nagle算法可以提高響應性,相應地會降低吞吐量,在這個場景中沒啥必要。



      回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-06-18 13:24 lizongbo

    hession 的序列化效率確實不錯,

    不過需要序列化的對象,試過實現(xiàn)java.io.Externalizable接口的方式?jīng)]?


      回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-06-18 13:41 pony

    @dennis
    測試hessian和java序列化的代碼,寫的不好請見諒^_^
    由于把數(shù)據(jù)存儲到memcached服務器中跟網(wǎng)絡環(huán)境,內(nèi)存有很大關系,跟memcached client設置的參數(shù)也有很大關系,所以就不做memcached的存取測試了.

    下面的代碼在我的機器上的結果是:
    serialize 1000000 users with hessian spend 8 seconds, total size:93000000
    serialize 1000000 users with java spend 17 seconds, total size:190000000

    /**
    * Created at 2008-06-13.
    * 測試比較java和hessian的序列化效率.
    */
    import java.io.ByteArrayOutputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.Date;

    import com.caucho.hessian.io.AbstractHessianOutput;
    import com.caucho.hessian.io.Hessian2Output;
    import com.caucho.hessian.io.SerializerFactory;

    /**
    * @author pony
    *
    * 如果有任何對代碼的修改,請按下面的格式注明修改的內(nèi)容.
    * 序號 時間 作者 修改內(nèi)容
    * 1. 2008-6-13 pony created this class.
    */
    public class TestSerializerPerformanceFucntion {
    //序列化次數(shù).
    private static final int COUNT = 1000000;

    private SerializerFactory factory;

    public static void main(String[] args) throws Exception {
    new TestSerializerPerformanceFucntion().testHessianSerializer();
    new TestSerializerPerformanceFucntion().testJavaSerializer();
    }

    public void testHessianSerializer() throws Exception {
    long curr = new Date().getTime();
    int size = COUNT;
    int len = 0;
    for (int i=0; i<size; i++) {
    User user = new User();
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    AbstractHessianOutput out = new Hessian2Output(os);;
    SerializerFactory serializerFactory = getSerializerFactory();
    out.setSerializerFactory(serializerFactory);
    out.startReply();
    out.writeObject(user);
    out.completeReply();
    out.flush();
    os.flush();
    len += os.size();
    out.close();
    }
    long now = new Date().getTime();
    System.out.println("serialize " + size + " users with hessian spend " + (now-curr)/1000 + " seconds, total size:" + len);
    }

    public void testJavaSerializer() throws Exception {
    long curr = new Date().getTime();
    int size = COUNT;
    int len = 0;
    for (int i=0; i<size; i++) {
    User user = new User();
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    new ObjectOutputStream(os).writeObject(user);
    os.flush();
    len += os.size();
    os.close();
    }
    long now = new Date().getTime();
    System.out.println("serialize " + size + " users with java spend " + (now-curr)/1000 + " seconds, total size:" + len);
    }

    public SerializerFactory getSerializerFactory() {
    if (null == factory) {
    factory = new SerializerFactory();
    }
    return factory;
    }
    }


    class User implements Serializable {
    /**
    * serial Version UID.
    */
    private static final long serialVersionUID = -4845300297590675952L;

    private String name = "test name";

    private Date birthday = new Date();

    private int age = 10;

    private double money = 1000.56;

    /**
    * @return the name
    */
    public String getName() {
    return name;
    }

    /**
    * @param name the name to set
    */
    public void setName(String name) {
    this.name = name;
    }

    /**
    * @return the birthday
    */
    public Date getBirthday() {
    return birthday;
    }

    /**
    * @param birthday the birthday to set
    */
    public void setBirthday(Date birthday) {
    this.birthday = birthday;
    }

    /**
    * @return the age
    */
    public int getAge() {
    return age;
    }

    /**
    * @param age the age to set
    */
    public void setAge(int age) {
    this.age = age;
    }

    /**
    * @return the money
    */
    public double getMoney() {
    return money;
    }

    /**
    * @param money the money to set
    */
    public void setMoney(double money) {
    this.money = money;
    }

    /**
    * @return the serialVersionUID
    */
    public static long getSerialVersionUID() {
    return serialVersionUID;
    }
    }  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-06-18 13:54 pony

    @lizongbo
    謝謝!這是個好建議!試過之后,只有驚訝!結果是比hessian的還快了!
    運行結果是:
    serialize 1000000 users with hessian spend 10 seconds, total size:93000000
    serialize 1000000 users with java spend 9 seconds, total size:86000000

    把上面代碼中的Serializable 改為
    Externalizable,實現(xiàn)下面兩個方法:
    public void readExternal(ObjectInput in) throws IOException,
    ClassNotFoundException {
    String name = in.readUTF();
    long time = in.readLong();
    int age = in.readInt();
    double money = in.readDouble();
    this.setName(name);
    this.setBirthday(new Date(time));
    this.setAge(age);
    this.setMoney(money);
    }

    public void writeExternal(ObjectOutput out) throws IOException {
    out.writeUTF(name);
    out.writeLong(birthday.getTime());
    out.writeInt(age);
    out.writeDouble(money);
    }

    不過因為從架構上考慮,我要用php來讀取cache中的內(nèi)容,所以我希望序列化后的對象能遵循一個統(tǒng)一的協(xié)議,所以,我暫時還是要用hessian的方式.  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2008-12-04 10:31 LiMengyan

    博主能否來個hessian序集?講講hessian部署的結構?我想看看hessian這個服務模塊是怎么給其他應用提供服務的?  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取 2010-09-20 11:00 thebye85

    @pony
    怎么我這邊測試還是hessian快  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取[未登錄] 2010-10-05 16:38 Jeff

    好文章!  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取[未登錄] 2011-06-24 12:03 HK

    好文啊!  回復  更多評論   

    # re: hessian序列化協(xié)議+memcached的緩存存取[未登錄] 2013-12-19 15:40 sa

    hessian4.0.7有一個bigdecimal序列化的bug  回復  更多評論   

    主站蜘蛛池模板: 久久亚洲最大成人网4438| 亚洲中文字幕无码中文| 成人午夜免费视频| 四虎精品亚洲一区二区三区| 亚洲女人被黑人巨大进入| 亚洲黄色在线电影| 五月婷婷免费视频| 国产亚洲精品影视在线产品| 国产精品高清免费网站| 永久亚洲成a人片777777| 亚洲午夜理论片在线观看| 夜夜嘿视频免费看| 日韩亚洲AV无码一区二区不卡| 久久精品成人免费观看| 亚洲欧洲日产国码高潮αv| 成人免费夜片在线观看| 亚洲AV无码成人精品区天堂 | 亚洲国产精品久久久久婷婷软件| 免费人成激情视频在线观看冫| 久久精品国产亚洲AV麻豆王友容| 91香蕉国产线观看免费全集| 国产国拍亚洲精品福利| 无码天堂亚洲国产AV| 亚洲中文字幕无码爆乳av中文 | 日韩精品视频免费在线观看| 亚洲成a人片在线观看播放| 免费无码又爽又刺激高潮软件| 亚洲人成网www| 女人张开腿等男人桶免费视频 | 亚洲AV成人无码网天堂| 国产亚洲人成A在线V网站| 无码国产精品一区二区免费式芒果| 亚洲天堂福利视频| 免费观看日本污污ww网站一区| 精品国产免费一区二区三区| 亚洲综合日韩中文字幕v在线| 麻豆精品国产免费观看| 中国一级特黄高清免费的大片中国一级黄色片| 亚洲欧洲日韩不卡| 亚洲欧洲精品成人久久奇米网| 亚洲黄色免费电影|