解決在OFFICE平台傳輸數據慢的問題,使用GZIP+JSON替代WEBSERVICE提供數據


解決思路:

原使用Xfire進行webservice數據提供,嚴重懷疑是這個家伙造成速度慢,所以考慮的思路是以action和json的方式替換掉這個webservice.

在JAVA端要提供的數據以下面的形式提供:

    /// <summary>
    /// 功能:綁定JS樹的數據
    /// 作者:黃海
    /// 時間:2007-11-14
    /// </summary>
    @RequestMapping(value="/getactiontreedata",method=RequestMethod.GET)
    public @ResponseBody String getactiontreedata()
    {
        return sysMenuService.getactiontreedata();
    }

老框架這么寫

    /**
     * 把字符串返回到前台頁面,用Ajax時使
     */
    private void responseTxt(String str){
        try {
            ServletActionContext.getResponse().setContentType(
                    "text/html;charset=utf-8");
            PrintWriter pw = ServletActionContext.getResponse().getWriter();
            pw.write(str);
            pw.flush();
            pw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }        
    }

因為使用的是text/html形式返回,所以Tomcat設置了壓縮后就啟用了這個形式的壓縮。

這個是以Spring mvc為框架搭建的提供原碼,如果是Struts2的舊項目,應該也是提供String返回值,但不能使用@ResponseBody,而是使用responseText函數完成這個操作。如果獲取的是一個List<Bean>,List<Map>,Bean等,建議使用fastjson轉化為json字符串后進行提供數據。

提供的測試調用如下圖:

 

 考慮到json的原始數據模型,需要進行數據壓縮進行傳遞,性能才會更好,所以參考設置一下Tomcat中的gzip壓縮,不在代碼層面采用GZIP壓縮辦法:

http://blog.csdn.net/hbcui1984/article/details/5666327

 

黃海成功按上面的文章配置了Tomcat啟用了GZIP壓縮后,檢查了下我們兩種輸出方式的文本格式:

@ResponseBody


responseTxt

直接按上面的鏈接配置TOMCAT的gzip,會造成只啟用了一部分,不是全都能解析,所以黃海的配置如下:

    <Connector port="8400" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               URIEncoding="utf-8" 
               compression="on" 
               compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata" 
               compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,text/json"/>

也就是添加了text/json格式,說明這樣的也需要進行GZIP壓縮處理。

 

然后黃海測試了在JAVA中使用HttpClient進行訪問有無GZIP兩種方式情況下的代碼異同點:

 @Test
    public void testGZIPHttpClient() throws IOException {

        //Tomct服務器端啟動壓縮設置的Url地址
        URL url = new URL("http://10.10.3.13:8080/digital/officegetResrouceBase.action?xdkmid=D4F913E3-EA88-4B06-B9FD-3F1C6AE9341A&ts=0&currentpage=1&pagerow=5000");

        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        //如果這里不設置,返回的就不是gzip的數據了,也就不用解壓縮了
        conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
        //構建user-agent頭
        //conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; Maxthon 2.0)");

        conn.connect();
        InputStream in = conn.getInputStream();

        /*經實測試,可以壓縮的大小由335K壓縮到74KB*/
        //持久化這個流,我們測試一下大小
        /*
        String outPath="c:/2.data";
        FileOutputStream out = new FileOutputStream(new File(outPath));
        int chByte = in.read();
        while (chByte != -1)
        {
            out.write(chByte);
            chByte = in.read();
        }
        out.close();
        */

        //無壓縮設置時啟用下面的代碼,關閉以    GZIPInputStream讀取的代碼
       // BufferedReader bin = new BufferedReader(new InputStreamReader(in,"UTF-8"));

        //有GZIP壓縮設置時啟用下面的代碼,關閉上面的無壓縮設置代碼
        GZIPInputStream gzin = new GZIPInputStream(in);
        BufferedReader bin = new BufferedReader(new InputStreamReader(gzin, "UTF-8"));

        String s = null;
        while((s=bin.readLine())!=null)
        {
            System.out.println(s);
        }
    }

 

至此,JAVA端的提供服務完成,下面將開始C#客戶端接收的部分。

 

================================================================================

================================================================================

================================================================================

 

 

在C#端調用的示例代碼如下:

 private void button1_Click(object sender, EventArgs e)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8400/base_db/getactiontreedata.action");
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            MessageBox.Show(retString);
        }

執行結果:

 

 

 c# 接收到json數據后,采用下面的辦法轉換為可以理解的對象進行處理:

http://www.cnblogs.com/txw1958/archive/2012/08/01/csharp-json.html

 

如果需要進一步優化,那么需要在JAVA端啟用了GZIP壓縮方式,這樣一來,C#需要使用WEBCLIENT進行調用 ,也需要啟用GZIP解壓功能,參考下面的鏈接:

http://www.2cto.com/kf/201109/106076.html

 ======================================================================================

附上測試結果:

1、在xfire提供的webservice情況下,使用的代碼:

 @Test
    public void testWEBSERVICE() throws Exception
    {
        //在你的方法第一行加上:
        long a=System.currentTimeMillis();

        String webservice_url="http://10.10.3.13:8080/digital/services/IResourceBaseService?wsdl";
        JaxWsDynamicClientFactory dcf=null;
        Client client=null;
        Object[] objects=null;
        dcf = JaxWsDynamicClientFactory.newInstance();
        client = dcf.createClient(webservice_url);
        objects = client.invoke("getResrouceBase","D4F913E3-EA88-4B06-B9FD-3F1C6AE9341A","0",1,5000);

        //在最好的一行加上:
        System.out.println("\r<br>執行耗時 : "+(System.currentTimeMillis()-a)/1000f+"");
    }

執行時間:

 

2、換成json+gzip的方法測試代碼:

@Test
    public void testGZIPHttpClient() throws IOException {

        //在你的方法第一行加上:
        long a=System.currentTimeMillis();

        //Tomct服務器端啟動壓縮設置的Url地址
        URL url = new URL("http://10.10.3.13:8080/digital/officegetResrouceBase.action?xdkmid=D4F913E3-EA88-4B06-B9FD-3F1C6AE9341A&ts=0&currentpage=1&pagerow=5000");

        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        //如果這里不設置,返回的就不是gzip的數據了,也就不用解壓縮了
        conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
        //構建user-agent頭
        //conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; Maxthon 2.0)");

        conn.connect();
        InputStream in = conn.getInputStream();

        /*經實測試,可以壓縮的大小由335K壓縮到74KB*/
        //持久化這個流,我們測試一下大小
        /*
        String outPath="c:/2.data";
        FileOutputStream out = new FileOutputStream(new File(outPath));
        int chByte = in.read();
        while (chByte != -1)
        {
            out.write(chByte);
            chByte = in.read();
        }
        out.close();
        */

        //無壓縮設置時啟用下面的代碼,關閉以    GZIPInputStream讀取的代碼
       // BufferedReader bin = new BufferedReader(new InputStreamReader(in,"UTF-8"));

        //有GZIP壓縮設置時啟用下面的代碼,關閉上面的無壓縮設置代碼
        GZIPInputStream gzin = new GZIPInputStream(in);
        BufferedReader bin = new BufferedReader(new InputStreamReader(gzin, "UTF-8"));

        //在最好的一行加上:
        System.out.println("\r<br>執行耗時 : "+(System.currentTimeMillis()-a)/1000f+"");

//        String s = null;
//        while((s=bin.readLine())!=null)
//        {
//            System.out.println(s);
//        }
    }

執行時間:

 

3、使用josn+no gzip的情況下:

@Test
    public void testGZIPHttpClient() throws IOException {

        //在你的方法第一行加上:
        long a=System.currentTimeMillis();

        //Tomct服務器端啟動壓縮設置的Url地址
        URL url = new URL("http://10.10.3.13:8080/digital/officegetResrouceBase.action?xdkmid=D4F913E3-EA88-4B06-B9FD-3F1C6AE9341A&ts=0&currentpage=1&pagerow=5000");

        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        //如果這里不設置,返回的就不是gzip的數據了,也就不用解壓縮了
        //conn.setRequestProperty("Accept-Encoding", "gzip,deflate");
        //構建user-agent頭
        //conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Alexa Toolbar; Maxthon 2.0)");

        conn.connect();
        InputStream in = conn.getInputStream();

        /*經實測試,可以壓縮的大小由335K壓縮到74KB*/
        //持久化這個流,我們測試一下大小
        /*
        String outPath="c:/2.data";
        FileOutputStream out = new FileOutputStream(new File(outPath));
        int chByte = in.read();
        while (chByte != -1)
        {
            out.write(chByte);
            chByte = in.read();
        }
        out.close();
        */

        //無壓縮設置時啟用下面的代碼,關閉以    GZIPInputStream讀取的代碼
        BufferedReader bin = new BufferedReader(new InputStreamReader(in,"UTF-8"));

        //有GZIP壓縮設置時啟用下面的代碼,關閉上面的無壓縮設置代碼
       // GZIPInputStream gzin = new GZIPInputStream(in);
       // BufferedReader bin = new BufferedReader(new InputStreamReader(gzin, "UTF-8"));

        //在最好的一行加上:
        System.out.println("\r<br>執行耗時 : "+(System.currentTimeMillis()-a)/1000f+"");

//        String s = null;
//        while((s=bin.readLine())!=null)
//        {
//            System.out.println(s);
//        }
    }

執行時間:

測試結論:

視程序部署到哪種網絡環境下,

如果是內網,TOMCAT不必啟用GZIP壓縮,這樣速度反而更快。如果啟用了GZIP壓縮,那么瓶頸在於壓縮和解壓的時間,反而慢了下來,考慮到每次5000條的容量不算小了,這樣應該算是一個結論了。

如果是互聯網,TOMCAT應啟用GZIP壓縮,這樣因為瓶頸在於網絡傳輸。 

 

后來黃海修改了數據的量,改用20000條做為閥值,結果如下:

webservice:

no gzip:

gzip:

發現5000的閥值偏小,20000與5000差距不大,建議采用更大的閥值,比如20000,采用NO GZIP的方式。

 為什么webservice這么慢呢?

http://www.tuicool.com/articles/quuyMv

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM