解决在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

 

posted @ 2013-05-15 10:54  糖豆爸爸  阅读(3698)  评论(2编辑  收藏  举报
Live2D