編輯下面的第一條評論問題。多線程http/https中間代理服務器,Socket性能
我的問題主要是Java套接字的性能,特別是從目標服務器讀取。
該服務器是用於從火狐
主要問題每個連接創建客戶線程的簡單的ServerSocket.accept()循環是插座輸入流中讀取,對於巨大量的時間塊。
客戶線程如下:
//Take an httpRequest (hc.apache.org), raw string http request, and the firefox socket outputstream
private void handle(httpRequest req, String raw, Outputstream out)
{
InputStream targetIn =null;
OutputStream targetOut = null;
Socket target = null;
try {
System.out.println("HANDLE HTTP");
String host = req.getHeaders("Host")[0].getValue();
URI uri = new URI(req.getRequestLine().getUri());
int port = uri.getPort() != -1 ? uri.getPort() : 80;
target = new Socket(host, port);
//**I have tried to play around with these but cannot seem to get a difference in performance**
target.setTcpNoDelay(true);
// target.setReceiveBufferSize(1024 *1024);
// target.setSendBufferSize(1024 * 1024);
//Get your plain old in/out streams
targetIn = target.getInputStream();
targetOut = target.getOutputStream();
//Send the request to the target
System.out.println("---------------Start response---------------");
targetOut.write(raw.getBytes());
System.out.println("request sent to target");
////Same as membrane
byte[] buffer = new byte[8 * 1024];
int length = 0;
try {
while((length = targetIn.read(buffer)) > 0) {
out.write(buffer, 0, length);
out.flush();
}
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("closing out + target socket");
//IOUTILS
// long count = IOUtils.copyLarge(targetIn, out, 0L, 1048576L);
// int count = IOUtils.copy(targetIn, out);
// System.out.println("transfered : " + count);
//CHANNEL COPY
//
// ReadableByteChannel input = Channels.newChannel(targetIn);
// WritableByteChannel output = Channels.newChannel(out);
//
// ChannelTools.fastChannelCopy(input, output);
//
// input.close();
// output.close();
//CHAR TO CHAR COPY
// int c;
// while ((c = targetIn.read()) != -1) {
// out.write(c);
// }
target.close();
out.close();
System.out.println("-------------------- end response ------------------------------");
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
的主要問題在於在適當的方法對目標的InputStream複製到客戶端(Firefox)的輸出流。
我用來測試這個網站是http://www.ouest-france.fr(新的網站與負載的圖像和負載的請求)。
從工作站平安到達目標:10ms的
在iceweasel正常負載(火狐的debian,螢火蟲時間):14秒,這背後代理2.5MB
加載:14分鐘(螢火蟲網面板是全假404s和中止的請求,在一段時間後回到黑色,負載的請求處於阻塞或等待模式)
現在,當執行我加載視覺虛擬機,啓動分析沒有類過濾器(看到哪裏應用程序真的花費時間),並且它在java.net.SocketInputStream.read(byte。)中花費了99%的時間[],int,int),它讀取目標套接字輸入流。
我想我已經完成了我的功課,並且正在尋找一個測試不同的解決方案,在任何地方我都可以。
但表現似乎從未改善。
我什麼,我已經嘗試過:
-Putting輸入和輸出流進他們的緩衝版本,在所有
-int沒有變化爲int副本,一點變化都沒有,
- 經典的byte []陣列拷貝可變大小陣列,根本沒有任何變化
擺弄settcpnodelay,setsendbuffersize,setreceivebuffersize,無法得到任何改變。
正在考慮嘗試使用nio套接字通道,但無法找到一種方法來對sslsocket進行套接字劫持。
所以目前我有點卡住和尋找解決方案。
我看着開源代理的源代碼,似乎無法找到邏輯的根本區別,所以我完全失去了這一點。
嘗試了其它試驗:
出口HTTP_PROXY = 「本地主機:4242」 的wget debiandvd.iso
吞吐量到達2MB/s的。 和線程似乎要花費66%的時間從目標讀取的33%的時間寫客戶端
我想,也許我有多個線程運行,但在www.google.com上運行測試要少得多請求貫通進入但仍然是同樣的問題www.ouest-france.fr
隨着debian iso測試我想我必須運行多個線程(ouest-france約270請求),但谷歌測試(10請求)測試似乎以確認線程號碼不是問題。
任何幫助將不勝感激。
環境是Debian的,太陽的java 1.6,偏差用eclipse和VisualVM的
根據需要我可以提供的代碼的其餘部分。
謝謝您發現
對不起,但這個問題太長了。請編輯它以減少一些簡潔的問題。就目前而言,它太長太漫長。 – Gray 2012-07-06 15:29:35