日期:2010-08-06  浏览次数:20379 次

压缩文本是一个可以减少文本内容尺寸达80%的过程。这意味着存储压缩的文本将会比存储没有压缩的文本少80%的空间。也意味着在网络上传输内容需要更少的时间,对于使用文本通信的客户端服务器应用程序来说,将会表现出更高的效率,例如XML Web services。

本文的主要目的就是寻找在客户端和服务器之间使交换的数据尺寸最小化的方法。一些有经验的开发者会使用高级的技术来优化通过网络特别是互联网传送的数据,这样的做法在许多分布式系统中都存在瓶颈。解决这个问题的一个方法是获取更多的带宽,但这是不现实的。另一个方法是通过压缩的方法使得被传输的数据达到最小。

当内容是文本的时候,通过压缩,它的尺寸可以减少80%。这就意味着在客户端和服务器之间带宽的需求也可以减少类似的百分比。为了压缩和解压缩,服务端和客户端则占用了CPU的额外资源。但升级服务器的CPU一般都会比增加带宽便宜,所以压缩是提高传输效率的最有效的方法。

XML/SOAP在网络中

让我们仔细看看SOAP在请求或响应XML Web service的时候,是什么在网络上传输。我们创建一个XML Web service,它包含一个 add 方法。这个方法有两个输入参数并返回这两个数的和:

<WebMethod()> Public Function add(ByVal a As Integer, ByVal b As _Integer) As Integer
add = a + b
End Function

当 XML Web service 消费端调用这个方法的时候,它确实发送了一个SOAP请求到服务器:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body><add xmlns="http://tempuri.org/"><a>10</a><b>20</b></add>
</soap:Body></soap:Envelope>

服务端使用一个SOAP响应来回应这个SOAP请求:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body><addResponse xmlns="http://tempuri.org/">
<addResult>30</addResult></addResponse>
</soap:Body></soap:Envelope>

这是调用XML Web service的方法后,在网络上传输的实际信息。在更复杂的XML Web service中,SOAP响应可能是一个很大的数据集。例如,当Northwind中的表orders中的内容被序列化为XML后,数据可能达到454KB。如果我们创建一个应用通过XML Web service来获取这个数据集,那么SOAP响应将会包含所有的数据。

为了提高效率,在传输之前,我们可以压缩这些文本内容。我们怎样才能做到呢?当然是使用SOAP扩展!

SOAP 扩展

SOAP扩展是ASP.NET的Web方法调用的一个拦截机制,它能够在SOAP请求或响应被传输之前操纵它们。开发者可以写一段代码在这些消息序列化之前和之后执行。(SOAP扩展提供底层的API来实现各种各样的应用。)

使用SOAP扩展,当客户端从XML Web service调用一个方法的时候,我们能够减小SOAP信息在网络上传输的尺寸。许多时候,SOAP请求要比SOAP响应小很多(例如,一个大的数据集),因此在我们的例子中,仅对SOAP响应进行压缩。就像你在图1中所看到的,在服务端,当SOAP响应被序列化后,它会被压缩,然后传输到网络上。在客户端,SOAP信息反序列化之前,为了使反序列化成功,SOAP信息会被解压缩。




图 1. SOAP信息在序列化后被压缩(服务端),在反序列化前被解压缩(客户端)

我们也可以压缩SOAP请求,但在这个例子中,这样做的效率增加是不明显的。

为了压缩我们的Web service的SOAP响应,我们需要做两件事情:

· 在服务端序列化SOAP响应信息后压缩它。
· 在客户端反序列化SOAP信息前解压缩它。

这个工作将由SOAP扩展来完成。在下面的段落中,你可以看到所有的客户端和服务端的代码。

首先,这里是一个返回大数据集的XML Web service:

Imports System.Web.Services
<WebService(Namespace := "http://tempuri.org/")> _
Public Class Service1
Inherits System.Web.Services.WebService

<WebMethod()> Public Function getorders() As DataSet
Dim OleDbConnection1 = New System.Data.OleDb.OleDbConnection()
OleDbConnection1.ConnectionString = "Provider=SQLOLEDB.1; _
Integrated Security=SSPI;Initial Catalog=Northwind; _
Data Source=.;Workstation ID=T-MNIKIT;"
Dim OleDbCommand1 = New System.Data.OleDb.OleDbCommand()
OleDbCommand1.Connection = OleDbConnection1
OleDbConnection1.Open()
Dim OleDbDataAdapter1 = New System.Data.OleDb.OleDbDataAdapter()
OleDbDataAdapter1.SelectCommand = OleDbCommand1
OleDbCommand1.CommandText = "Select * from orders"
Dim objsampleset As New DataSet()
OleDbDataAdapter1.Fill(objsampleset, "Orders")
OleDbConnection1.Close()
Return objsampleset
End Function

End Class



在客户端,我们构建了一个Windows应用程序来调用上面的XML Web service,获取那个数据集并显示在DataGrid中:

Public Class Form1
Inherits System.Windows.Forms.Form
''This function invokes the XML Web service, which returns the dataset
''without using compression.
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim ws As New wstest.Service1()
Dim test1 As New ClsTimer()