如何使服务器发送事件(SSE)在 Apache + Tomcat 中正常工作?

如何使服务器发送事件(SSE)在 Apache + Tomcat 中正常工作?

我在 Debian 上使用 Apache 2.4.10 作为前端 Web 服务器,后端使用 Tomcat 8.0.28 实例。它们的目的是提供标准 jsp 页面,其中一些页面是动态刷新的。

我的 Web 应用运行良好,但通过 SSE 广播通知时除外。几分钟后,Tomcat 就崩溃了,停止提供页面(HTTP 500),有时会将 SSE 内容与常规 HTML 流混合在一起。

重要提示:在开发环境中,所有 SSE 内容均运行良好,即当我们在 Windows 7/10 下运行不带 Apache 的 Tomcat 时。这个细节以及我在日志中读到的内容使我相信问题出在 Apache 上。

Apache 能够处理 SSE 请求吗?

如果是的话,我应该应用哪种配置?

非常感谢您的帮助。

附加信息:

Apache 的配置:

- Apache 2.4.10 (Debian 64 bits) OpenSSL/1.0.1k
- mpm-event, with mod_headers, mod_ssl, mod_rewrite, mod_proxy, mod_proxy_http
- The Tomcat's integration is operated with the mod_proxy_ajp

Web 应用程序配置:

- Tomcat 8.0.28, with java version "1.7.0_79" (OpenJDK 64 bits)
- The connector is set to use the AJP/1.3 protocol
- SSE server based upon Jersey 2.5.1
- Tomcat hosts several Web Apps, all routed through a ProxyPass directive (such as ProxyPass /webapp1 ajp://10.10.12.2:8015/webapp1, ProxyPass /webapp2 ajp://10.10.12.2:8015/webapp2, and so on).

Tomcat 日志:

[list]  07-Apr-2019 19:55:19.580 INFO [pool-13-thread-1] org.apache.coyote.AbstractProcessor.setErrorState An error occurred in processing while on a non-container thread. The connection will be closed immediately
     java.io.IOException: Relais brisé (pipe)
        at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
        at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
        [...]
        at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
        [...]
        at org.apache.coyote.ajp.AbstractAjpProcessor.action(AbstractAjpProcessor.java:410)
        [...]
        at org.glassfish.jersey.server.Broadcaster.broadcast(Broadcaster.java:150)
        [...]
        at SAR.DTS.Base.b.o.run(ThreadMajRappels.java:58)
        [...]
        at java.lang.Thread.run(Thread.java:745)[/list]

    07-Apr-2019 20:10:05.344 INFO [ajp-nio-8015-exec-10] org.apache.catalina.connector.CoyoteAdapter.checkRecycled Encountered a non-recycled response and recycled it forcedly.
     org.apache.catalina.connector.CoyoteAdapter$RecycleRequiredException
        at org.apache.catalina.connector.CoyoteAdapter.checkRecycled(CoyoteAdapter.java:710)
        at org.apache.coyote.ajp.AbstractAjpProcessor.recycle(AbstractAjpProcessor.java:943)
        at org.apache.coyote.ajp.AjpNioProtocol$AjpConnectionHandler.release(AjpNioProtocol.java:163)

Apache 日志:

[Sun Apr 07 20:05:22.338619 2019] [proxy_ajp:error] [pid 6573] [client xx.xx.x.xxx:61445] AH00893: dialog to 10.10.12.2:8015 (10.10.12.2) failed, referer: http://yy.yy.yy.yyy/webapp1
    [Sun Apr 07 20:10:05.344774 2019] [proxy_ajp:error] [pid 6573] [client xx.xx.x.xxx:62693] AH00992: ajp_read_header: ajp_ilink_receive failed, referer: http://yy.yy.yy.yyy/webapp1
    [Sun Apr 07 20:10:05.344783 2019] [proxy_ajp:error] [pid 6573] (120006)APR does not understand this error code: [client xx.xx.x.xxx:62693] AH00878: read response failed from 10.10.12.2:8015 (10.10.12.2), referer: http://yy.yy.yy.yyy/webapp1
    [Sun Apr 07 20:10:05.344745 2019] [proxy_ajp:error] [pid 6573] (104)Connection reset by peer: AH01030: ajp_ilink_receive() can't receive header

答案1

是的,Apache 可以!

我找到了一种让 SSE 在 Apache + Tomcat 中运行的方法,即用非常简单的 HTTP 连接器替换 AJP 连接器:

在 Apache 配置中:

# This statment prevents Apache from redirecting to the local URL.
# Oddly, it is unnecessary when using the AJP Connector...
ProxyPreserveHost On
ProxyPass /webapp1 http://10.10.12.2:8016/webapp1

在 Tomcat 配置中:

<Connector
    port="8016"
    protocol="org.apache.coyote.http11.Http11NioProtocol"
    proxyPort="80" />

我不知道这是否是最初问题的正确答案,但它让我更接近目标......

现在,我将尝试 1) 找到(如果有)适合 AJP 的正确配置和 2) 使 http 配置与 SSL 和 SSE 一起工作。

相关内容