您的位置:首页 > 其它

如何优化WebService进行大批量数据传送(WSE3.0应用技巧)

2009-03-05 10:54 621 查看
在网上找了一下资料,用WebService进行大量数据传送的人并不多,主要原因是因为传送速度慢,因为WebService是以XML文件流的方式来传送的,写过XML的人都知道,XML中会有很多冗余的内容,比说字段名,他是每一行就要写一次,如果有约束,还要附加很多描述语句,而且从WebService返回数据时,还要进行64位编码,所以用WebService进行通迅效率很低.找了好久终于找到了一位高手的文章,原来WebService可以通过三步瘦身,但他用的方法是VS2003+wse2.0,而我用的是Vs2008+Wse3.0写法有所不同,于是写下此日志,帮助自己记录,也希望帮到有相关需求的人.

 

正文:

将DataSet设置为用于远程传送的精简二进制模式

用压缩程序对数据进行压缩(此处使用微软提供的ICSharpCode.SharpZipLib.dll)

使用WSE3.0的MTOM技术优化SOAP.

WSE3.0配置:

安装完WSE3.0后,你会发现安装目录下会有一个WebService3.dll,要将其引入到WebService项目中(不能像VS2005中可以直接创建一个WSE3.0的项目),然后要配置Web.config,置于具体的配置写法可以用Wse3.0安装目录下的WseConfigEditor3.exe进行配置,例如要开通MTOM,则先在General页中勾选Enable this project for Web Service Enhancements,再在Messaging页中Client Mode选择on 然后关闭程序,会提示生成配置文件,打开文件,将相关项目填回Web.config中就可以使用了.

具体Web.config内容如下

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
<compilation>
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
</system.web>
<microsoft.web.services3>
<messaging>
<mtom clientMode="On" />
</messaging>
</microsoft.web.services3>
</configuration>


具体代码:

一.压缩类:

using System;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

namespace ClassLb1
{
/// <summary>
/// 压缩强度。
/// </summary>
public enum CompressionLevel
{
/// <summary>
/// 采用最好的压缩率。
/// </summary>
BestCompression,

/// <summary>
/// 采用默认的压缩率。
/// </summary>
DefaultCompression,

/// <summary>
/// 采用最快的压缩速度。
/// </summary>
BestSpeed,

/// <summary>
/// 不采用任何压缩。
/// </summary>
NoCompression
}

/// <summary>
/// CompressionHelper 的摘要说明。
/// </summary>
public class CompressionHelper
{
/// <summary>
/// 获取和设置压缩强度。
/// </summary>
public CompressionLevel Level;

public CompressionHelper()
{
Level = CompressionLevel.DefaultCompression;
}

public CompressionHelper(CompressionLevel level)
{
Level = level;
}

#region Public Methods
/// <summary>
/// 从原始字节数组生成已压缩的字节数组。
/// </summary>
/// <param name="bytesToCompress">原始字节数组。</param>
/// <returns>返回已压缩的字节数组</returns>
public byte[] CompressToBytes(byte[] bytesToCompress)
{
MemoryStream ms = new MemoryStream();
Stream s = GetOutputStream(ms);
s.Write(bytesToCompress, 0, bytesToCompress.Length);

s.Close();
return ms.ToArray();
}

/// <summary>
/// 从已压缩的字节数组生成原始字节数组。
/// </summary>
/// <param name="bytesToDecompress">已压缩的字节数组。</param>
/// <returns>返回原始字节数组。</returns>
public byte[] DecompressToBytes(byte[] bytesToDecompress)
{
byte[] writeData = new byte[4096];              //设置缓冲区
Stream s2 = GetInputStream(new MemoryStream(bytesToDecompress));        //解压缩数组
MemoryStream outStream = new MemoryStream();      //由于Stream类型不能直接转换为byte[]只能通过MemoryStream做中间变换

while (true)            //循环读取数据流到outStream,直至读取完毕
{
int size = s2.Read(writeData, 0, writeData.Length);
if (size > 0)
{
outStream.Write(writeData, 0, size);
}
else
{
break;
}
}
s2.Close();
byte[] outArr = outStream.ToArray();
outStream.Close();
return outArr;
}
#endregion

#region Private Methods
/// <summary>
/// 根据压缩强度返回使用了不用压缩算法的 Deflate 对象。
/// </summary>
/// <param name="level">压缩强度。</param>
/// <returns>返回使用了不用压缩算法的 Deflate 对象。</returns>
private Deflater GetDeflater(CompressionLevel level)
{
switch (level)
{
case CompressionLevel.DefaultCompression:
return new Deflater(Deflater.DEFAULT_COMPRESSION);

case CompressionLevel.BestCompression:
return new Deflater(Deflater.BEST_COMPRESSION);

case CompressionLevel.BestSpeed:
return new Deflater(Deflater.BEST_SPEED);

case CompressionLevel.NoCompression:
return new Deflater(Deflater.NO_COMPRESSION);

default:
return new Deflater(Deflater.DEFAULT_COMPRESSION);
}
}

/// <summary>
/// 从给定的流生成压缩输出流。
/// </summary>
/// <param name="inputStream">原始流。</param>
/// <returns>返回压缩输出流。</returns>
private DeflaterOutputStream GetOutputStream(Stream inputStream)
{
return new DeflaterOutputStream(inputStream, GetDeflater(Level));
}

/// <summary>
/// 从给定的流生成压缩输入流。
/// </summary>
/// <param name="inputStream">原始流。</param>
/// <returns>返回压缩输入流。</returns>
private InflaterInputStream GetInputStream(Stream inputStream)
{
return new InflaterInputStream(inputStream);
}
#endregion

}
}


 

二.客户端:

Thread thread1;
private void button1_Click(object sender, EventArgs e)
{
//try
//{
label1.Text = "整理数据......";
thread1 = new Thread(new ThreadStart(UpLoad));
thread1.Start();
//}
//catch (Exception e1)
//{
//    MessageBox.Show("上传数据失败!错误代码如下:/r/n" + e1.ToString());
//}
}

/// <summary>
/// 上传数据
/// </summary>
private void UpLoad()
{
int LinLimit = 10;

string ZDDB1 = "ZD";
string Prsta = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
//Prsta = Prsta.Substring(0, Prsta.LastIndexOf("//", Prsta.Length - 2));     //截取Prsta的路径
SqlConn sqlConn = new SqlConn();
SqlConnection Conn2 = sqlConn.Sqlc2(Prsta, ZDDB1);
Conn2.Open();
string sqlse1 = "select top 100 * from SqlLogOut";
SqlDataAdapter sqlDa = new SqlDataAdapter(sqlse1, Conn2);
SqlCommandBuilder scb = new SqlCommandBuilder(sqlDa);

DataSet Ds = new DataSet();
sqlDa.Fill(Ds, "SqlLogOut");

label1.Text = "共有" + Ds.Tables[0].Rows.Count.ToString() + "条记录  开始上传..........";

int Loop1 = Ds.Tables[0].Rows.Count / LinLimit;                             //分包数
if (Ds.Tables[0].Rows.Count % LinLimit > 0)
Loop1++;
for (int i = 1; i <= Loop1; i++)
{
DataSet DsPack = PackDs(Ds, LinLimit);
DsPack.RemotingFormat = SerializationFormat.Binary;         //将DS设置为用于远程序传送的精简二进制模式
BinaryFormatter BinForm = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
BinForm.Serialize(ms, DsPack);
byte[] buffer = ms.ToArray();
byte[] byUpload = new CompressionHelper(CompressionLevel.BestSpeed).CompressToBytes(buffer);        //将byte数组再进行加压

localhost.DataTransport daTr = new DataTransport.localhost.DataTransport();
string Res = daTr.DataUpload(byUpload);
if (Res == "#1")
{
progressBar1.Value =Convert.ToInt16( Convert.ToDouble(i) / Loop1 * 100);
sqlDa.Update(Ds, "SqlLogOut");                  //删除数据库上对应记录
}
}
label1.Text = "上传完成.";
Conn2.Close();
thread1.Abort();
}


 

三.WebService

public string DataUpload(byte[] byUpload,string UpBm)
{
try
{
byte[] byData = new CompressionHelper().DecompressToBytes(byUpload);
BinaryFormatter binForm = new BinaryFormatter();
DataSet dsUpload = binForm.Deserialize(new MemoryStream(byData)) as DataSet;

Bz1= "#1";
}
catch (Exception e1)
{
Bz1 = e1.Message.ToString();
}
return Bz1;
}


经此方法可以将原数据量大大压缩2/3以上,只是原来的1/3左右

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息