Apache 缓冲 tomcat 响应,并在请求大小超过 10397232 字节时关闭与 tomcat 的连接

Apache 缓冲 tomcat 响应,并在请求大小超过 10397232 字节时关闭与 tomcat 的连接

我已经将基于 tomee:8-jre-7.0.4-plume 的 Web 服务应用程序部署为 Docker 容器,该容器位于在同一台机器上运行的另一个 Docker 容器中运行的 apache httpd:2.4 实例后面。

我遇到了以下问题:a) apache 正在缓冲响应,这会产生很大的延迟;b) 如果数据量太大(10397232 字节),apache 将关闭与 TomEE 的连接,并报告 org.apache.catalina.connector.ClientAbortException:java.net.SocketTimeoutException。我认为这与我在 apache error_log(LogLevel trace6)output_filter:由于 THRESHOLD_MAX_BUFFER 而刷新中看到的消息相对应。无论我使用 https 还是 http,都会发生这种情况。

如果我直接向 TomEE 发送请求,则不会发生响应缓冲,并且大型请求也不会出现错误。

我包含了一些能够重现该问题的代码。您会注意到,我基本上是将请求输入通过管道传输到“cat”,然后将其输出通过管道传输到另一个“cat”。然后将最终“cat”输出的输出复制到响应输出流。在“实际”应用程序中,我没有使用 cat,而是在做一些更有趣的事情,但这个例子说明了问题的症结所在。此外,如果我修改代码以将最终“cat”的输出写入本地文件,然后只需将该文件的内容复制到响应输出流,那么问题就会消失,但是,这会引入与缓冲整个响应相同的延迟。

我尝试在 apache httpd.conf 中进行了一些配置更改

<IfModule proxy_ajp_module>
    ProxyPass "/" "http://localhost:8080/" timeout=18000
    TimeOut 18000
</IfModule>

我尝试了以下各种组合:

    ProxyPass "/" "http://localhost:82/" timeout=18000 flushpackets=on receivebuffersize=8192 iobuffersize=8192

我还尝试明确设置文档中提到的一些 TomEE/Tomcat 配置设置。我目前没有使用 ajp 协议。

当前唯一的 server.xml 更改是:

<Connector port="8080" allowTrace="true" ajpFlush="false" maxPostSize="-1" maxSavePostSize="-1"  proxyName="mycustomhost.com" protocol="HTTP/1.1"

我在这里包含了代表性的网络服务代码:

package com.spike

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;

@Path("test")
public class MinTestingResource {
    private final ExecutorService execSvc = Executors.newFixedThreadPool(10);
    @POST
    public void post(
            @Context HttpServletRequest request,
            @Context HttpServletResponse response) throws IOException, InterruptedException, ExecutionException {
        InputStream in = request.getInputStream();
        OutputStream out = response.getOutputStream();
        convertStream(in, out);
    }
    private void convertStream(InputStream in, OutputStream out) throws ExecutionException, IOException, InterruptedException {
        Process p1 = new ProcessBuilder("cat").start();
        Process p2 = new ProcessBuilder("cat").start();
        copyInThread("in-p1", in, p1.getOutputStream());
        copyInThread("p1-p2", p1.getInputStream(), p2.getOutputStream());
        copy("p2-out", p2.getInputStream(), out);
    }
    private Future<Long> copyInThread(String nameToLog, InputStream in, OutputStream out) {
        AtomicBoolean copierStarted = new AtomicBoolean(false);
        final Future<Long> future = execSvc.submit(() -> {copierStarted.set(true); return copy(nameToLog, in, out);});
        waitForStart(nameToLog, copierStarted);
        return future;
    }
    private long copy(String nameToLog, InputStream in, OutputStream out) throws IOException {
        long copied = 0;
        try {
            byte[] buf = new byte[8192];
            for (int bytesRead = 0; (bytesRead = in.read(buf)) > 0;) {
                out.write(buf, 0, bytesRead);
                copied += bytesRead;
            }
            return copied;
        } finally {
            out.close();
        }
    }
    private void waitForStart(String nameToLog, AtomicBoolean copierStarted) {
        pause(5);
        while (!copierStarted.get()) {
            pause(5);
        }
    }
    private void pause(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException ignore) {
        }
    }
}

我在 apache bugzilla 上发现了以下问题错误 61616 - mod_proxy_connect:双向流量停滞和连接丢失但不确定这是否是同一个问题,并且不清楚是否有可用的 Docker 容器解决方案。

相关内容