Moqui在Elastic Beanstalk Tomcat实例上部署到AWS

时间:2019-05-15 22:43:02

标签: postgresql amazon-ec2 tomcat8 amazon-elastic-beanstalk moqui

背景

我们使用Java环境在Elastic Beanstalk上使用嵌入式Jetty服务器运行Moqui 2.0已有大约一年的时间。出于安全原因,我们将应用程序与Postgres数据库一起在专用子网中运行,并通过VPN对其进行访问。因此,我们从不费心启用HTTPS访问。

我们现在要在公共子网中部署Moqui,以便无需VPN即可访问它,因此我们需要HTTPS访问。

旁注:请记住,我已经通读了部署选项here!。

独立的Moqui上的HTTPS

我的第一个问题是,您能否仅使用嵌入式服务器通过HTTPS运行Moqui?我查看了MoquiStart类,并且main似乎默认仅支持端口8080上的HTTP初始化。有一整段被注释掉,其中还包含用注释初始化HTTPS和HTTP / 2的代码:

// Possible code to handle HTTPS, HTTP/2 (h2, h2c):

所以我认为Moqui不支持HTTPS作为独立应用程序?

Web应用程序服务器中的Moqui

基于以上假设,Moqui并未将Jetty配置为服务HTTPS请求,因此到目前为止,使用Java环境在公共子网中使用Java来运行Moqui显然变得不可接受。剩下两个选择。诸如Docker之类的容器化(这超出了我的技能范围),或者在诸如Tomcat之类的应用程序服务器中运行(这也超出了我的技能范围,但我至少可以在概念上有所帮助)。导致我进入issue上的StackOverflow线程!。

我对J2EE体系结构不熟悉,但是我假设一旦在Tomcat中运行,Catalina就会绕过MoquiStart 中的Jetty端口初始化? [为我的理解,请多作简短的解释]

无论如何,以上线程确认我在使用HTTPS解决方案的正确轨道上。

问题

问题是,Moqui无法正常工作。我知道Tomcat运行良好,因为在创建环境时,我使用示例应用程序,并且可以通过HTTP正常访问。部署ROOT.war文件(在../apache-tomcat-8.5.6/webapps中找到)后,我既无法通过HTTP也无法通过HTTPS访问Moqui。 (我的安全组是完全开放的)它尝试连接并最终超时。

我已经检查了EB日志,可能的罪魁祸首已记录在catalina.YYYY-MM-DD.log文件中。

14-May-2019 21:21:07.101 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/var/lib/tomcat8/webapps/ROOT]
14-May-2019 21:21:23.946 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal One or more listeners failed to start. Full details will be found in the appropriate container log file
14-May-2019 21:21:23.956 SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal Context [] startup failed due to previous errors
14-May-2019 21:21:23.965 WARNING [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [AsyncAppender-AsyncLog] but has failed to stop it. This is very likely to create a memory leak.

堆栈跟踪如下:

sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:403)
org.apache.logging.log4j.core.appender.AsyncAppender$AsyncThread.run(AsyncAppender.java:282)

立即出现的下游错误是:

14-May-2019 21:21:23.989 SEVERE [localhost-startStop-1] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [com.hazelcast.internal.util.ThreadLocalRandom$1] (value [com.hazelcast.internal.util.ThreadLocalRandom$1@4379b697]) and a value of type [com.hazelcast.internal.util.ThreadLocalRandom] (value [com.hazelcast.internal.util.ThreadLocalRandom@37d77b2b]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
14-May-2019 21:21:24.006 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/var/lib/tomcat8/webapps/ROOT] has finished in [16,904] ms

相关部分MoquiActualConf是:

   ...
    <default-property name="webapp_http_host" value="[OUR_IP_HERE]"/>
    <default-property name="webapp_http_port" value="80"/>
    <default-property name="webapp_https_port" value="443"/>
    <default-property name="webapp_https_enabled" value="true"/>
    <default-property name="entity_ds_db_conf" value="h2"/>
    <default-property name="entity_ds_host" value="localhost"/>
    <default-property name="entity_ds_port" value=""/>
    <default-property name="entity_ds_database" value="moqui"/>
    <default-property name="entity_ds_url" value="jdbc:h2:${moqui_runtime}/db/h2/${entity_ds_database};lock_timeout=30000"/>
    <default-property name="entity_ds_schema" value=""/>
    <default-property name="entity_ds_user" value="sa"/>
    <default-property name="entity_ds_password" value="sa"/>
    ...
        <webapp name="webroot" http-port="80" http-host="[OUR_IP_HERE]" https-port="443" https-host="[OUR_IP_HERE]" https-enabled="true" require-session-token="true" websocket-timeout="600000">
            <root-screen host=".*" location="component://webroot/screen/webroot.xml"/>
            <error-screen error="unauthorized" screen-path="error/Unauthorized"/>
            <error-screen error="forbidden" screen-path="error/Forbidden"/>
            <error-screen error="not-found" screen-path="error/NotFound"/>
            <error-screen error="too-many" screen-path="error/TooMany"/>
            <error-screen error="internal-error" screen-path="error/InternalError"/>
            <listener class="org.moqui.impl.webapp.MoquiSessionListener"/>
            <servlet name="MoquiServlet" class="org.moqui.impl.webapp.MoquiServlet" load-on-startup="1">
                <url-pattern><![CDATA[/*]]></url-pattern>
            </servlet>
            <servlet name="MoquiFopServlet" class="org.moqui.impl.webapp.MoquiFopServlet" load-on-startup="1">
                <url-pattern><![CDATA[/fop/*]]></url-pattern>
            </servlet>
            <session-config timeout="60"/>
            <endpoint path="/notws" class="org.moqui.impl.webapp.NotificationEndpoint" timeout="3600000" enabled="true"/>
    ...

我已经研究EC2实例的Tomcat胆量了三天了,什么也没想出来,所以非常感谢您的帮助。

PS:出于某种原因,出于某种原因,MoquiActualConf被MoquiProductionConf而不是Procfile中指定的MoquiTestConf覆盖。

web: java -Xmx1024M -cp . MoquiStart port=8080 conf=conf/MoquiTestConf.xml

我不认为这是问题的根源,但在指向生产数据库等时会导致问题。

2 个答案:

答案 0 :(得分:1)

我通过设置ec2负载平衡器,设法通过HTTPS访问AWS EB中的Moqui实例。显而易见,Moqui的码头监听端口5000,ec2 Nginx监听端口80(并将其转发到端口5000),ec2负载均衡器监听端口80和443(并将其转发到ec2 Nginx端口80)。 如果您不想使用负载均衡器,则可以设置ec2 Nginx来侦听HTTPS,并将其转发到Moqui的码头端口5000,就像Nginx HTTP一样。 最不推荐的方法是通过环境变量传递一些https jetty的参数,在MoquiStart中可能需要进行一些小的更改。几年前,我不记得详细信息,但是Jetty能够以这种方式提供HTTPS服务。

答案 1 :(得分:0)

webapp元素上的http *属性用于配置URL编写,而不用于配置Moqui外部的Web服务器。即使在使用嵌入式Jetty方法的情况下,Moqui仍在Java Servlet容器(例如Tomcat或Jetty)中运行,并且Servlet容器的配置是配置HTTP接口的地方。

通常,终止HTTPS的最佳方法是使用基于httpd或nginx的反向代理。默认情况下,甚至ElasticBeanstalk图像(使用httpd)都执行此操作,如果您通过AWS EB配置HTTPS证书,则由httpd处理。 Docker Compose示例中的nginx-proxy使用了相同的方法。