六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

通過壓縮SOAP改善XML Web service性能

[摘要]壓縮文本是一個可以減少文本內容尺寸達80%的過程。這意味著存儲壓縮的文本將會比存儲沒有壓縮的文本少80%的空間。也意味著在網絡上傳輸內容需要更少的時間,對于使用文本通信的客戶端服務器應用程序來說,將會表現出更高的效率,例如XML Web services。 本文的主要目的就是尋找在客戶端和服...
壓縮文本是一個可以減少文本內容尺寸達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()
'Start time counting…
test1.StartTiming()
'Fill datagrid with the dataset
DataGrid1.DataSource = ws.getorders()
test1.StopTiming()
'Stop time counting…
TextBox5.Text = "Total time: " & test1.TotalTime.ToString & "msec"
End Sub

'This function invokes the XML Web service, which returns the dataset
'using compression.
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim ws As New wstest2.Service1()
Dim test1 As New ClsTimer()
'Start time counting…
test1.StartTiming()
'Fill datagrid with dataset
DataGrid1.DataSource = ws.getorders()
test1.StopTiming()
'Stop time counting…
TextBox4.Text = "Total time: " & test1.TotalTime.ToString & "msec"
End Sub

End Class

客戶端調用了兩個不同的XML Web services, 僅其中的一個使用了SOAP壓縮。下面的Timer類是用來計算調用時間的:

Public Class ClsTimer
' Simple high resolution timer class
'
' Methods:
' StartTiming reset timer and start timing
' StopTiming stop timer
'
'Properties
' TotalTime Time in milliseconds
'Windows API function declarations
Private Declare Function timeGetTime Lib "winmm" () As Long

'Local variable declarations
Private lngStartTime As Integer
Private lngTotalTime As Integer
Private lngCurTime As Integer

Public ReadOnly Property TotalTime() As String
Get
TotalTime = lngTotalTime
End Get
End Property

Public Sub StartTiming()
lngTotalTime = 0
lngStartTime = timeGetTime()
End Sub

Public Sub StopTiming()
lngCurTime = timeGetTime()
lngTotalTime = (lngCurTime - lngStartTime)
End Sub
End Class

服務端的SOAP擴展

在服務端,為了減小SOAP響應的尺寸,它被壓縮。下面這段告訴你怎么做:

第一步

使用Microsoft Visual Studio .NET, 我們創建一個新的Visual Basic .NET 類庫項目(使用"ServerSoapExtension"作為項目名稱),添加下面的類:

Imports System
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.IO
Imports zipper

Public Class myextension
Inherits SoapExtension
Private networkStream As Stream
Private newStream As Stream

Public Overloads Overrides Function GetInitializer(ByVal _
methodInfo As LogicalMethodInfo, _
ByVal attribute As SoapExtensionAttribute) As Object
Return System.DBNull.Value
End Function

Public Overloads Overrides Function GetInitializer(ByVal _
WebServiceType As Type) As Object
Return System.DBNull.Value
End Function

Public Overrides Sub Initialize(ByVal initializer As Object)
End Sub

Public Overrides Sub ProcessMessage(ByVal message As SoapMessage)
Select Case message.Stage

Case SoapMessageStage.BeforeSerialize

Case SoapMessageStage.AfterSerialize
AfterSerialize(message)

Case SoapMessageStage.BeforeDeserialize
BeforeDeserialize(message)

Case SoapMessageStage.AfterDeserialize

Case Else
Throw New Exception("invalid stage")
End Select
End Sub

' Save the stream representing the SOAP request or SOAP response into a
' local memory buffer.
Public Overrides Function ChainStream(ByVal stream As Stream) As Stream
networkStream = stream
newStream = New MemoryStream()
Return newStream
End Function

' Write the compressed SOAP message out to a file at
'the server's file system..
Public Sub AfterSerialize(ByVal message As SoapMessage)
newStream.Position = 0
Dim fs As New FileStream("c:\temp\server_soap.txt", _
FileMode.Append, FileAccess.Write)
Dim w As New StreamWriter(fs)
w.WriteLine("-----Response at " + DateTime.Now.ToString())
w.Flush()
'Compress stream and save it to a file
Comp(newStream, fs)
w.Close()
newStream.Position = 0
'Compress stream and send it to the wire
Comp(newStream, networkStream)
End Sub

' Write the SOAP request message out to a file at the server's file system.
Public Sub BeforeDeserialize(ByVal message As SoapMessage)
Copy(networkStream, newStream)
Dim fs As New FileStream("c:\temp\server_soap.txt", _
FileMode.Create, FileAccess.Write)
Dim w As New StreamWriter(fs)
w.WriteLine("----- Request at " + DateTime.Now.ToString())
w.Flush()
newStream.Position = 0
Copy(newStream, fs)
w.Close()
newStream.Position = 0
End Sub

Sub Copy(ByVal fromStream As Stream, ByVal toStream As Stream)
Dim reader As New StreamReader(fromStream)
Dim writer As New StreamWriter(toStream)
writer.WriteLine(reader.ReadToEnd())
writer.Flush()
End Sub

Sub Comp(ByVal fromStream As Stream, ByVal toStream As Stream)
Dim reader As New StreamReader(fromStream)
Dim writer As New StreamWriter(toStream)
Dim test1 As String
Dim test2 As String
test1 = reader.ReadToEnd
'String compression using NZIPLIB
test2 = zipper.Class1.Compress(test1)
writer.WriteLine(test2)
writer.Flush()
End Sub

End Class

' Create a SoapExtensionAttribute for the SOAP extension that can be
' applied to an XML Web service method.
<AttributeUsage(AttributeTargets.Method)> _
Public Class myextensionattribute
Inherits SoapExtensionAttribute

Public Overrides ReadOnly Property ExtensionType() As Type
Get
Return GetType(myextension)
End Get
End Property

Public Overrides Property Priority() As Integer
Get
Return 1
End Get
Set(ByVal Value As Integer)
End Set
End Property

End Class



第二步

我們增加ServerSoapExtension.dll程序集作為引用,并且在web.config聲明SOAP擴展:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

<system.web>
<webServices>
<soapExtensionTypes>
<add type="ServerSoapExtension.myextension,
ServerSoapExtension" priority="1" group="0"/>
</soapExtensionTypes>
</webServices>

...
</system.web>
</configuration>

就象你在代碼中看到的那樣,我們使用了一個臨時目錄("c:\temp")來捕獲SOAP請求和壓縮過的SOAP響應到文本文件("c:\temp\server_soap.txt")中 。

客戶端的SOAP擴展

在客戶端,從服務器來的SOAP響應被解壓縮,這樣就可以獲取原始的響應內容。下面就一步一步告訴你怎么做:

第一步

使用Visual Studio .NET, 我們創建一個新的Visual Basic .NET類庫項目(使用 "ClientSoapExtension"作為項目名稱),并且添加下面的類:

Imports System
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.IO
Imports zipper
Public Class myextension
Inherits SoapExtension

Private networkStream As Stream
Private newStream As Stream

Public Overloads Overrides Function GetInitializer(ByVal _
methodInfo As LogicalMethodInfo, _
ByVal attribute As SoapExtensionAttribute) As Object
Return System.DBNull.Value
End Function

Public Overloads Overrides Function GetInitializer(ByVal _
WebServiceType As Type) As Object
Return System.DBNull.Value
End Function

Public Overrides Sub Initialize(ByVal initializer As Object)
End Sub

Public Overrides Sub ProcessMessage(ByVal message As SoapMessage)
Select Case message.Stage

Case SoapMessageStage.BeforeSerialize

Case SoapMessageStage.AfterSerialize
AfterSerialize(message)

Case SoapMessageStage.BeforeDeserialize
BeforeDeserialize(message)

Case SoapMessageStage.AfterDeserialize

Case Else
Throw New Exception("invalid stage")
End Select
End Sub

' Save the stream representing the SOAP request or SOAP response
' into a local memory buffer.
Public Overrides Function ChainStream(ByVal stream As Stream) _
As Stream
networkStream = stream
newStream = New MemoryStream()
Return newStream
End Function

' Write the SOAP request message out to a file at
' the client's file system.
Public Sub AfterSerialize(ByVal message As SoapMessage)
newStream.Position = 0
Dim fs As New FileStream("c:\temp\client_soap.txt", _
FileMode.Create, FileAccess.Write)
Dim w As New StreamWriter(fs)
w.WriteLine("----- Request at " + DateTime.Now.ToString())
w.Flush()
Copy(newStream, fs)
w.Close()
newStream.Position = 0
Copy(newStream, networkStream)
End Sub

' Write the uncompressed SOAP message out to a file
' at the client's file system..
Public Sub BeforeDeserialize(ByVal message As SoapMessage)
'Decompress the stream from the wire
DeComp(networkStream, newStream)
Dim fs As New FileStream("c:\temp\client_soap.txt", _
FileMode.Append, FileAccess.Write)
Dim w As New StreamWriter(fs)
w.WriteLine("-----Response at " + DateTime.Now.ToString())
w.Flush()
newStream.Position = 0
'Store the uncompressed stream to a file
Copy(newStream, fs)
w.Close()
newStream.Position = 0
End Sub

Sub Copy(ByVal fromStream As Stream, ByVal toStream As Stream)
Dim reader As New StreamReader(fromStream)
Dim writer As New StreamWriter(toStream)
writer.WriteLine(reader.ReadToEnd())
writer.Flush()
End Sub

Sub DeComp(ByVal fromStream As Stream, ByVal toStream As Stream)
Dim reader As New StreamReader(fromStream)
Dim writer As New StreamWriter(toStream)
Dim test1 As String
Dim test2 As String
test1 = reader.ReadToEnd
'String decompression using NZIPLIB
test2 = zipper.Class1.DeCompress(test1)
writer.WriteLine(test2)
writer.Flush()
End Sub

End Class

' Create a SoapExtensionAttribute for the SOAP extension that can be
' applied to an XML Web service method.
<AttributeUsage(AttributeTargets.Method)> _
Public Class myextensionattribute
Inherits SoapExtensionAttribute

Public Overrides ReadOnly Property ExtensionType() As Type
Get
Return GetType(myextension)
End Get
End Property

Public Overrides Property Priority() As Integer
Get
Return 1
End Get
Set(ByVal Value As Integer)
End Set
End Property

End Class

就象你在代碼中看到的那樣,我們使用了一個臨時目錄("c:\temp") 來捕獲SOAP請求和解壓縮的SOAP響應到文本文件("c:\temp\client_soap.txt")中。

第二步

我們添加ClientSoapExtension.dll程序集作為引用,并且在我們的應用程序的XML Web service引用中聲明SOAP擴展:

'-------------------------------------------------------------------------
' <autogenerated>
' This code was generated by a tool.
' Runtime Version: 1.0.3705.209
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </autogenerated>
'-------------------------------------------------------------------------
Option Strict Off
Option Explicit On

Imports System
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.Xml.Serialization

'
'This source code was auto-generated by Microsoft.VSDesigner,
'Version 1.0.3705.209.
'
Namespace wstest2

'<remarks/>
<System.Diagnostics.DebuggerStepThroughAttribute(), _
System.ComponentModel.DesignerCategoryAttribute("code"), _
System.Web.Services.WebServiceBindingAttribute(Name:="Service1Soap", _
[Namespace]:="http://tempuri.org/")> _
Public Class Service1
Inherits System.Web.Services.Protocols.SoapHttpClientProtocol

'<remarks/>
Public Sub New()
MyBase.New
Me.Url = "http://localhost/CompressionWS/Service1.asmx"
End Sub

'<remarks/>
<System.Web.Services.Protocols.SoapDocumentMethodAttribute _
("http://tempuri.org/getproducts",RequestNamespace:= _
"http://tempuri.org/", ResponseNamespace:="http://tempuri.org/", _
Use:=System.Web.Services.Description.SoapBindingUse.Literal,_
ParameterStyle:=System.Web.Services.Protocols.SoapParameterStyle _
.Wrapped), ClientSoapExtension.myextensionattribute()> _
Public Function getproducts() As System.Data.DataSet
Dim results() As Object = Me.Invoke("getproducts", _
New Object(-1) {})
Return CType(results(0), System.Data.DataSet)
End Function

'<remarks/>
Public Function Begingetproducts(ByVal callback As _
System.AsyncCallback, ByVal asyncState As Object) As System.IAsyncResult _

Return Me.BeginInvoke("getproducts", New Object(-1) {}, _
callback, asyncState)
End Function

'<remarks/>
Public Function Endgetproducts(ByVal asyncResult As _
System.IAsyncResult) As System.Data.DataSet
Dim results() As Object = Me.EndInvoke(asyncResult)
Return CType(results(0), System.Data.DataSet)
End Function
End Class
End Namespace



這里是zipper類的源代碼,它是使用免費軟件NZIPLIB庫實現的:

using System;
using NZlib.GZip;
using NZlib.Compression;
using NZlib.Streams;
using System.IO;
using System.Net;
using System.Runtime.Serialization;
using System.Xml;
namespace zipper
{
public class Class1
{
public static string Compress(string uncompressedString)
{
byte[] bytData = System.Text.Encoding.UTF8.GetBytes(uncompressedString);
MemoryStream ms = new MemoryStream();
Stream s = new DeflaterOutputStream(ms);
s.Write(bytData, 0, bytData.Length);
s.Close();
byte[] compressedData = (byte[])ms.ToArray();
return System.Convert.ToBase64String(compressedData, 0, _
compressedData.Length);
}

public static string DeCompress(string compressedString)
{
string uncompressedString="";
int totalLength = 0;
byte[] bytInput = System.Convert.FromBase64String(compressedString);;
byte[] writeData = new byte[4096];
Stream s2 = new InflaterInputStream(new MemoryStream(bytInput));
while (true)
{
int size = s2.Read(writeData, 0, writeData.Length);
if (size > 0)
{
totalLength += size;
uncompressedString+=System.Text.Encoding.UTF8.GetString(writeData, _
0, size);
}
else
{
break;
}
}
s2.Close();
return uncompressedString;
}
}
}



分析

軟件&硬件

· 客戶方: Intel Pentium III 500 MHz, 512 MB RAM, Windows XP.
· 服務器方: Intel Pentium III 500 MHz, 512 MB RAM, Windows 2000 Server, Microsoft SQL Server 2000.

在客戶端,一個Windows應用程序調用一個XML Web service。這個XML Web service 返回一個數據集并且填充客戶端應用程序中的DataGrid。



圖2. 這是一個我們通過使用和不使用SOAP壓縮調用相同的XML Web Service的樣例程序。這個XML Web service返回一個大的數據集。

CPU 使用記錄

就象在圖3中顯示的那樣,沒有使用壓縮的CPU使用時間是 29903 milliseconds.



圖 3. 沒有使用壓縮的CPU使用記錄

在我們的例子中,使用壓縮的CPU使用時間顯示在圖4中, 是15182 milliseconds.



圖 4. 使用壓縮的CPU 使用記錄

正如你看到的,我們在客戶方獲取這個數據集的時候,使用壓縮與不使用壓縮少用了近50%的CPU時間,僅僅在CPU加載時有一點影響。當客戶端和服務端交換大的數據時,SOAP壓縮能顯著地增加XML Web Services效率。 在Web中,有許多改善效率的解決方案。我們的代碼是獲取最大成果但是最便宜的解決方案。SOAP擴展是通過壓縮交換數據來改善XML Web Services性能的,這僅僅對CPU加載時間造成了一點點影響。并且值得提醒的是,大家可以使用更強大的和需要更小資源的壓縮算法來獲取更大的效果



主站蜘蛛池模板: 日本视频免费看 | 色网站观看 | 伊人网综合在线观看 | 亚洲一区二区三区在线免费观看 | 日本亚洲高清 | 亚洲v日本v欧美v综合v | 深夜国产一区二区三区在线看 | 探花视频在线看视频 | 影音先锋精品国产资源 | 日韩国产成人资源精品视频 | 色无极在线观看 | 欧美在线三级 | 天天射天天干天天操 | 亚洲一二三四区 | 青青草原在线免费观看 | 中文字幕第99页 | 欧美一级乱理片免费观看 | 日韩成人免费视频播放 | 欧美综合图区亚洲综合图区 | 日本一本二本在线观看 | 天堂资源在线中文 | 五月婷婷深深爱 | 在线播放亚洲视频 | 欧美又大又粗又长又硬 | 日韩久久中文字幕 | 亚洲欧美日韩精品一区 | 亚洲伦理在线观看 | 天天躁天天狠天天透 | 色站app| 日韩中文字幕精品免费一区 | 欧美一级片网 | 欧美一级免费看 | 亚日韩 | 亚洲伊人久久大香线蕉结合 | 亚洲va欧美va天堂v国产综合 | 午夜资源网 | 青娱乐福利 | 日本在线免费看片 | 亚洲最大看欧美片网站 | 亚洲成a人v欧美综合天堂下载 | 最新影院 |