項目中碰到一個問題,為客戶做系統的另一家廠商居然用我們提供的Web service來初始化應用系統資料庫,通過web service從來源資料庫中取一次取三百萬行的表,處理後去填充另外一張表。調用介面的那哥們居然使用一個“select *"就想把所有資料都取過去,結果肯定是報記憶體溢出的錯誤。經過溝通後讓他分批進行調用,但感覺效率還是不夠高。在.net與java用戶端自己暫時實在實驗不出其它方法,所以決定使用壓縮資料的方法。
.net與java互動的壓縮方式較為簡單的實現方式是用gzip格式,java本身有gzip的支援,.net沒有相應的類庫,我使用了開源項目sharpziplib來實現.net端的壓縮功能。
經過實驗,傳輸相同的字串,起碼能夠讓長度減少三分之二,並且有效減低CPU的利用率。
代碼如下:
1、C#端代碼
public static string Compress(string uncompressedString)
{
byte[] byteData=System.Text.Encoding.UTF8.GetBytes(uncompressedString);
MemoryStream ms=new MemoryStream();
Stream s=new GZipOutputStream(ms);
s.Write(byteData,0,byteData.Length);
s.Close();
byte[] compressData=(byte[])ms.ToArray();
ms.Flush();
ms.Close();
return System.Convert.ToBase64String(compressData,0,compressData.Length);
}
public static string DeCompress(string compressedString)
{
// string uncompressedString=string.Empty;
StringBuilder sb=new StringBuilder(40960);
int totalLength=0;
byte[] byteInput=System.Convert.FromBase64String(compressedString);
byte[] writeData=new byte[4096];
Stream s=new GZipInputStream(new MemoryStream(byteInput));
while(true)
{
int size=s.Read(writeData,0,writeData.Length);
if(size>0)
{
totalLength+=size;
sb.Append(System.Text.Encoding.UTF8.GetString(writeData,0,size));
}
else
{
break;
}
}
s.Flush();
s.Close();
return sb.ToString();
}
2、Java端代碼
public static String compress(String s) throws IOException{
ByteArrayInputStream input = new ByteArrayInputStream(s.getBytes("UTF-8"));
ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
GZIPOutputStream gzout = new GZIPOutputStream(output);
byte[] buf=new byte[1024];
int number;
while ((number = input.read(buf)) != -1){
gzout.write(buf,0,number);
}
gzout.close();
input.close();
String result =new BASE64Encoder().encode(output.toByteArray());
output.close();
return result;
}
public static String decompress(String data) throws IOException{
ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
ByteArrayInputStream input = new ByteArrayInputStream(new BASE64Decoder().decodeBuffer(data));
GZIPInputStream gzinpt = new GZIPInputStream(input);
byte[] buf = new byte[1024];
int number = 0;
while((number = gzinpt.read(buf)) != -1){
output.write(buf,0,number);
}
gzinpt.close();
input.close();
String result = new String(output.toString("UTF-8"));
output.close();
return result;
}
在web service伺服器端加壓,java用戶端的調用解壓,使用web service的效能得到了提升。
但覺得這樣還是不能徹底的解決問題,下一步準備做的改進主要有兩點,一是把伺服器把返回的大資料量壓縮成zip檔案以attachment的格式返回給java用戶端,另一個是在內部網路以tcp soap的方式進行調用,輔以多線程的技術,更有效地利用伺服器的多CPU與並實現服務的分流,使web service不必依賴於IIS(當然啦,這些都需要WSE的支援)。