不知道有多少人有遇到跟我一樣的問題,就是Web Service的資料回傳量太大了,如果都是走區域網路的話,除非量很大,不然還感覺不太出來,可是,如果是透過ADSL的頻寬的話,那就很驚人了,以30MB的資料量來說,透過2M/512K的網路上傳,加上網路品質的損耗以65%來看,也大概要花738秒左右來上傳. (30*1024)/((512*0.65)/8)=738.46. 這樣的時間,看起來很嚇人,何況在上傳滿載時,下載的頻寬可能剩40%不到,如果今天能壓縮這資料量,讓資料量剩25%左右,那上傳時間就只要185秒左右,這樣的差異就很大了,如果今天我們採用的是n-tier架構,Client是透過Web Service在要資料,那要怎麼去壓縮這傳輸過程中的資料? 這時就可以拿GZipStream出來用了.

  起初,GZipStream只是被我拿來當檔案壓縮用的,剛好這段時間遇到公司ERP系統效能調校,突然產生了一個想法,如果我能拿它來壓縮資料,那傳輸的資料量不就小很多,尤其是XML的文字檔,效果一定更明顯,就在這個念頭下,著手開始寫了測試的程式,在這裡,我做了兩種不同的做法,一個是純壓縮,不Serialize,另一種做法是壓縮與Serialize,而這兩種做法,是會產生些微的資料量差異.

在提到程式內容之前,先說明這做法所造成的資料量差異,詳見下表 :

正常資料量

壓縮後

壓縮+Serialize

18,368,067 Bytes

4,755,570 Bytes

4,445,278 Bytes

17,937.57 Kb

4,644.11 Kb

4,341.09 Kb

接下來,就是程式碼部份,分兩個部份說明:

1 .純壓縮 :

WebService Side :

using System.IO;
using System.IO.Compression;
[WebMethod]
public byte[] getZipData()
{
DataSet ds = LoadData().Copy();
MemoryStream unMS = new MemoryStream();
ds.WriteXml(unMS);
byte[] bytes = unMS.ToArray();
int lenbyte = bytes.Length;
MemoryStream compMs = new MemoryStream();
GZipStream compStream = new GZipStream(compMs, CompressionMode.Compress, true);
compStream.Write(bytes, 0, lenbyte);
compStream.Close();
unMS.Close();
compMs.Close();
byte[] zipData = compMs.ToArray();
return zipData;
}
private DataSet LoadData()
{//產生測試資料用
DataSet ds = new DataSet();
DataTable dt = new DataTable("Test");
dt.Columns.Add("ProID",typeof(int));
dt.Columns.Add("ProName", typeof(string));
dt.Columns.Add("CreateTime", typeof(DateTime));
dt.Columns["ProID"].AutoIncrement = true;
for (int i = 0; i < 100000; i++)
{
DataRow dr = dt.NewRow();
dr["ProName"] = Guid.NewGuid().ToString();
dr["CreateTime"] = DateTime.Now.ToString();
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
ds.AcceptChanges();
return ds;
}

Client Side :

using System.IO.Compression;
using System.IO;
private void btn_ZipGet_Click(object sender, EventArgs e)
{
try
{
WS.Service1 wss = new WSZipDemo.WS.Service1();//WebReference
byte[] da = wss.getZipData();
MemoryStream input = new MemoryStream();
input.Write(da, 0, da.Length);
input.Position = 0;
GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true);
MemoryStream output = new MemoryStream();
byte[] buff = new byte[4096];
int read = -1;
read = gzip.Read(buff, 0, buff.Length);
while (read > 0)
{
output.Write(buff, 0, read);
read = gzip.Read(buff, 0, buff.Length);
}
gzip.Close();
byte[] rebytes = output.ToArray();
output.Close();
input.Close();
MemoryStream ms = new MemoryStream(rebytes);
DataSet ds = new DataSet();
ds.ReadXml(ms);
dataGridView1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

2. 壓縮+Serialize

Web Service Side :

using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
[WebMethod]
public byte[] getZipData()
{
DataSet ds = LoadData().Copy();
ds.RemotingFormat = SerializationFormat.Binary;
BinaryFormatter ser = new BinaryFormatter();
MemoryStream unMS = new MemoryStream();
ser.Serialize(unMS, ds);
byte[] bytes = unMS.ToArray();
int lenbyte = bytes.Length;
MemoryStream compMs = new MemoryStream();
GZipStream compStream = new GZipStream(compMs, CompressionMode.Compress, true);
compStream.Write(bytes, 0, lenbyte);
compStream.Close();
unMS.Close();
compMs.Close();
byte[] zipData = compMs.ToArray();
return zipData;
}
private DataSet LoadData()
{//產生測試資料用
DataSet ds = new DataSet();
DataTable dt = new DataTable("Test");
dt.Columns.Add("ProID",typeof(int));
dt.Columns.Add("ProName", typeof(string));
dt.Columns.Add("CreateTime", typeof(DateTime));
dt.Columns["ProID"].AutoIncrement = true;
for (int i = 0; i < 100000; i++)
{
DataRow dr = dt.NewRow();
dr["ProName"] = Guid.NewGuid().ToString();
dr["CreateTime"] = DateTime.Now.ToString();
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
ds.AcceptChanges();
return ds;
}

Client Side :

using System.IO.Compression;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
private void btn_ZipGet_Click(object sender, EventArgs e)
{
try
{
WS.Service1 wss = new WSZipDemo.WS.Service1();//WebReference
byte[] da = wss.getZipData();
MemoryStream input = new MemoryStream();
input.Write(da, 0, da.Length);
input.Position = 0;
GZipStream gzip = new GZipStream(input, CompressionMode.Decompress, true);
MemoryStream output = new MemoryStream();
byte[] buff = new byte[4096];
int read = -1;
read = gzip.Read(buff, 0, buff.Length);
while (read > 0)
{
output.Write(buff, 0, read);
read = gzip.Read(buff, 0, buff.Length);
}
gzip.Close();
byte[] rebytes = output.ToArray();
output.Close();
input.Close();
MemoryStream ms = new MemoryStream(rebytes);
BinaryFormatter bf = new BinaryFormatter();
object obj = bf.Deserialize(ms);
DataSet ds = (DataSet)obj;
dataGridView1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
  這兩種做法只是在部份的程式碼不一樣,但其它大多相同,如果是方法一,在WebService壓縮後Return,Client收到資料後,解壓縮即可,方法二則多了Serialize這部份,所以在WebService這邊,先Serialize,再壓縮,Client端收到後,先解壓縮再Deserialize. 不過,這個壓縮後的量,是很讓人滿意,如果在頻寬有限,又需要傳輸大量資料時,這個方法可以考慮看看. 因為這個是.Net 2.0以後才有的東西,公司現在的ERP還在.Net 1.0,所以.........殘念~

2008/04/29 補充 :

  最近有網友看到這篇文章,有些問題問我朋友,而朋友再來轉問我這個問題(真巧,網友問我朋友,我朋友再來問我),而提出的問題是,壓縮跟解壓是否很耗用CPU的效能? 答案是,不可能不用到CPU的效能,但它也不致於到"很耗用"的地步. 而這耗用率只能視設備狀況來判斷,以我的環境來說,Client端的電腦是P4 3GHT, 上面的這個例子跑的時候有個瞬間最高47%,不到一秒的時間,如果是未壓縮版的,瞬間最高為37%左右,所以大概多個10%吧.

  或許有人還是有疑慮怎麼可以增加CPU的Loading呢,這樣就不好了,這時我們就要換個角度來思考這個問題了,"效能成本"所在為何,我們的Bottleneck在那.CPU在科技的進步下,雙核四核的都推出了,CPU的效能是快速的在倍增中,而我們的網路呢? 絕大多數區域還在100MB,部份Server與Server是1G在連,而ADSL呢? 10M/1M或者是只能2M/512K,因為申請不到更快的頻寬,如果要更快,每月的費用就更高, 注意囉,上傳是1MB或512K哦,而且是多人共用的,所以就目前國內的網路環境來看,ADSL要到100M/100M,似乎還要很長的一段時間,而這段時間的CPU,也不知道已經成長到幾核心了,兩者之間怎麼取捨,就看大家的看法囉.

2008/5/30 補充

  因為一些朋友對這個方式感到有興趣,也在網路上找了一些文章,可是卻又發現了一些疑問,到底這個壓縮技術能用在什麼樣的情況下. 其中一位朋友傳給了我一個網址.Net DataTable 大量資料壓縮加密實測,也是說明用壓縮的方式來減少流量,一些測試結果也很詳盡,有興趣的人建議參考,只是朋友在他的文章開頭的地方看到 [開發 Web 或分散式系統],這是否代表Web網站也可以用? 這個答案當然是沒用的,試想,我們在Web Server壓縮,Client端用IE或Firefox怎麼解壓縮,網頁是無法用Gzipstream的方式來解壓縮來減少Web Server到Client的資料量,能壓一定要能解才有用,所以就不用再去列出那些可以及那些不行了,畢竟這還關係的架構上的問題,所以應用的關鍵就是"能壓要能解才能用".

  另一個問題就是選擇性的使用,壓縮的動作勢必用到系統的效能,如果全面性100%的採用壓縮,當使用者多,或操作頻率高時,資料量大,系統效能也會變的更加吃重,所以必需挑選幾個關鍵的傳輸來壓縮即可,不用連1K不到的資料量也在壓縮,除非Server很猛的,那就另當別論. 依我的情況,我會挑選幾個使用者的查詢作業來壓,依目前手頭上的分析資料來看,有個查詢作業使用頻率較高,資料量也是驚人,最高的資料量就一次高達33MB,平均起來跟其它作業比較,這作業的資料量佔了不小的比率,光這作業一天平均傳輸量650MB,壓縮後只剩162.5MB在傳,所以只壓縮這個作業的查詢動作,就可明顯的改善ADSL的頻寬瓶頸. 所以要視情況去選擇要壓縮的作業.

原文地址:http://www.dotblogs.com.tw/jeff-yeh/archive/2008/04/16/2932.aspx

由GZipStream的压缩,減少Web Service的传输量相关推荐

  1. 藉由GZipStream的壓縮,來減少Web Service的傳輸量

    不知道有多少人有遇到跟我一樣的問題,就是Web Service的資料回傳量太大了,如果都是走區域網路的話,除非量很大,不然還感覺不太出來,可是,如果是透過ADSL的頻寬的話,那就很驚人了,以30MB的 ...

  2. 提高 Web Service 数据传输效率的基本方法

    背景 Web Service 现如今已经成为 SOA 实现标准之一.很多公司已经或者正在参与到 Web Service 项目的实现和部署中.Web Service 的优点在于松散的处理异构系统之间的通 ...

  3. Distributed Systems笔记-Web Service Design Patterns

    CMU 95702 Distributed Systems 笔记.简单介绍 XML-RPC.SOAP.REST 三种 web 服务实现方案以及 RPC.Message.Resource 三种 patt ...

  4. 提高Web Service效率的几种方式(转)

    2008-02-20 16:01 基于SOAP的Web Service的性能一直为人诟病,由于采用 XML标准进行系统间的数据传输,加大了传输的数据量,尤其是在传输一些具有比较严格结构的数据时,会使得 ...

  5. WCF实现RESTFul Web Service

    共同学习了前面一些概念,终于开始正题了哈.RESTful的Web Service调用直观,返回的内容容易解析.这里先会描述一个简单的场景--Web Service提供一个方法来搜索个人信息,传入人名, ...

  6. 从WEB SERVICE 上返回大数据量的DATASET

    前段时间在做一个项目的时候,遇到了要通过WEB SERVICE从服务器上返回数据量比较大的DATASET,当然,除了显示在页面上以外,有可能还要用这些数据在客户端进行其它操作.查遍了网站的文章,问了一 ...

  7. Web service是什么?

    一.Web service的概念 想要理解Web service,必须先理解什么是Service(服务). 传统上,我们把计算机后台程序(Daemon)提供的功能,称为"服务"(s ...

  8. java部署web service的方式

    部署web service的方式一般有两种: 1. 编写java源文件,将文件的java后缀改为jws,然后部署到webapps/axis目录下,axia引擎可以直接执行源文件中定义的java方法为w ...

  9. Java开源Web Service(转)

    为什么80%的码农都做不了架构师?>>>    Axis  Apache Axis 是Apache WebService项目中的子项目,其最初起源于IBM的"SOAP4J& ...

最新文章

  1. guestbook.php注入,TinyGuestBook 'sign.php'多个SQL注入漏洞
  2. Dijkstra 算法
  3. Oracle cursor_sharing 参数 详解
  4. android 定时语音,android 定时语音天气播报
  5. Educational Codeforces Round 76 (Rated for Div. 2) F. Make Them Similar 折半搜索
  6. 配置linux系统ip,Linux系统IP地址配置
  7. android.mk 比较字变量,粉丝投稿 | 谈谈Android.mk
  8. yii+php+当前目录,Yii常用路径方法总结
  9. 域用户权限|连接DC终端服务
  10. Fiddler4的安装与使用
  11. java计算机毕业设计疫情防控期间网上教学管理源程序+mysql+系统+lw文档+远程调试
  12. pxe装机原理_pxe网络安装操作系统 原理与详细过程
  13. 阿尔卡特交换机配置_ALCATEL-交换机配置手册(中文).doc
  14. 标准模板库(STL)介绍
  15. html居中小圆点●,圆点怎么打_居中小圆点怎么打出来_电脑常识_中华康网
  16. onsemi安森美FDMS86252L 50V 12A 56mΩ N沟道屏蔽门极MOSFET管
  17. vue使用百度地图(BMap)去掉百度地图的标志。
  18. 路径中 斜杠/和反斜杠\ 的区别
  19. 【推荐】2022年物流快递行业市场行情分析投资趋势产业发展前景调研究报告(附件中为网盘地址,报告持续更新)
  20. 面向对象(Object-Oriented)

热门文章

  1. 验尸官称Debian创始人 Ian Murdock 是自杀身亡
  2. Facebook keyhash 获取方法总结(含 通过google play后台下载的 .der证书获取 keyhash)
  3. python详细介绍
  4. MATLAB中绘制ROC曲线
  5. android左侧抽屉,Android控件之左侧抽屉菜单
  6. 非参数检验之符号检验、Wilcoxon符号秩检验、游程检验
  7. python | 时间序列折线图
  8. 模板引擎FreeMarker的介绍和使用
  9. [转]Send Fax VBA's Code
  10. Powerdesigner逆向工程从sql server数据库生成pdm