首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java - TCP/HTTP通信最快的流?

Java - TCP/HTTP通信最快的流?
EN

Stack Overflow用户
提问于 2012-08-19 08:20:48
回答 1查看 3.3K关注 0票数 4

我正在尝试编写一个Java代理隧道程序,我需要一个专家建议如何使用最好和最快的流来进行通信。

我已经实现了基本的功能,一切都很好。唯一的问题是交流的速度或性能。我的HTTP代理系统由运行在远程服务器上的服务器程序和运行在本地计算机上的客户端程序组成。到目前为止,该项目如下所示:

Listener.java :

代码语言:javascript
复制
/**
 * Listens and accepts connection requests from the browser
 */
ServerSocket listener = null;
try {
    listener = new ServerSocket(port, 128);
} catch (IOException ex) {
    ex.printStackTrace(System.err);
}

ExecutorService executor = Executors.newCachedThreadPool();

Socket connection;
while (!shutdown) {
    try {
        connection = listener.accept();
        executor.execute(new ProxyTunnel(connection));
    } catch (IOException ex) {
        ex.printStackTrace(System.err);
    }
}

ProxyTunnel.java :

代码语言:javascript
复制
try {
    byte[] buffer = new byte[8192];  // 8-KB buffer
    InputStream browserInput = browser.getInputStream();
    OutputStream browserOutput = browser.getOutputStream();

    // Reading browser request ...
    StringBuilder request = new StringBuilder(2048);
    do {
        int read = browserInput.read(buffer);
        logger.log(read + " bytes read from browser.");
        if (read > 0) {
            request.append(new String(buffer, 0, read));
        }
    } while (browserInput.available() > 0 && read > 0);

    // Connecting to proxy server ...
    Socket server = new Socket(SERVER_IP, SERVER_PORT);
    server.setSoTimeout(5000);  // Setting 5 sec read timeout
    OutputStream serverOutput = server.getOutputStream();
    InputStream serverInput = server.getInputStream();

    // Sending request to server ...
    serverOutput.write(request.toString().getBytes());
    serverOutput.flush();

    // Waiting for server response ...
    StringBuilder response = new StringBuilder(16384);
    do {
        try {
            read = serverInput.read(buffer);
        } catch (SocketTimeoutException ex) {
            break; // Timeout!
        }
        if (read > 0) {
            // Send response to browser.");
            response.append(new String(buffer, 0, read));
            browserOutput.write(buffer, 0, read);
            browserOutput.flush();
        }
    } while (read > 0);

    // Closing connections ...
    server.close();

} catch (IOException ex) {
    ex.printStackTrace(System.err);
} finally {
    try {
        browser.close();
    } catch (IOException ex) {
        ex.printStackTrace(System.err);
    }
}

服务器程序使用类似的方式,并将HTTP请求发送到目标服务器(例如www.stackoverflow.com),并将响应转发给客户端程序,其中客户端程序将响应转发给本地浏览器。

  1. 如何提高这些TCP/HTTP通信的性能?
  2. 使用缓冲流(如BufferedInputSreamBufferedOutputStream )是否会改善通信性能?
  3. 如果我使用java.nio通道和缓冲区,而不是使用java.net套接字和java.io流,我会得到任何性能改进吗?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-08-19 08:39:55

不要自己动手

建议0:有大量的代理服务器,更可伸缩,更稳定和成熟。你真的需要自己写吗?

不要使用StringBuilder/String来缓冲请求

代码语言:javascript
复制
byte[] buffer = new byte[8192];  // 8-KB buffer
//...
browserInput.read(buffer);
//...
request.append(new String(buffer, 0, read));
//...
serverOutput.write(request.toString().getBytes());

这是有缺陷的,原因有几个:

  • 假设您的HTTP调用仅为text (ASCII),二进制数据在转换为String并返回到byte[]后将出现格式错误,请参见:字符串、byte[]和压缩
  • 即使协议是基于文本的,您也在使用系统的默认编码.我打赌这不是你想要的
  • 最后,最重要的部分是:不缓冲整个请求。从传入请求中读取数据块,并在一次迭代中立即将其转发到目标服务器。绝对不需要额外的内存开销和延迟。在接收到几个字节后,立即分派它们并忘记它们。

不要使用Executors.newCachedThreadPool()

这个池可以无限增长,在高峰期间创建数千个线程。本质上,每个连接创建一个线程(除了池重用空闲线程,但如果没有可用,则创建新线程)。考虑一下Executors.newFixedThreadPool(100) -100-200个线程在大多数情况下应该足够了.在此基础上,您很可能只需要在上下文切换中消耗CPU,而不需要做大量工作。不要害怕潜伏期,缩小范围。

使用非阻塞奈蒂堆栈

这给了我们最后的建议。完全掉落阻塞插座。它们很方便,但是由于每个连接线程的需求,它们的扩展性不太好。占用堆栈的内存太多,用于上下文切换的CPU太多。netty很棒,它为NIO构建了强大的抽象。

查看例句,它们包括HTTP /服务器代码。有一点学习曲线,但您可以预期性能增长几个数量级。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12025184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档