无法使用wladm Ant任务在Tomcat上部署大型Worklight应用程序

时间:2014-10-06 12:34:39

标签: ibm-mobilefirst worklight-server

我使用Worklight版 6.2.0.01.20141002-2218 (工作室,服务器,ant任务)和Tomcat 7.0.55 来托管Worklight服务器(一切都是在Windows 8.1上运行。作为CI构建的一部分,我们使用Ant(版本 1.8.4 )构建最新的应用程序(.wlapp)和适配器(.adapter),然后将其部署到Tomcat实例。我们看到的问题是,对于大于大约2 MB的.wlapp个文件,我们会收到以下错误(IP和端口隐藏):

[wladm] Oct 06, 2014 1:42:55 PM org.apache.http.impl.client.DefaultRequestDirector tryExecute
[wladm] INFO: I/O exception (java.net.SocketException) caught when processing request: Connection reset by peer: socket write error
[wladm] Oct 06, 2014 1:42:55 PM org.apache.http.impl.client.DefaultRequestDirector tryExecute
[wladm] INFO: Retrying request
[wladm] Oct 06, 2014 1:42:55 PM org.apache.http.impl.client.DefaultRequestDirector tryExecute
[wladm] INFO: I/O exception (java.net.SocketException) caught when processing request: Software caused connection abort: socket write error
[wladm] Oct 06, 2014 1:42:55 PM org.apache.http.impl.client.DefaultRequestDirector tryExecute
[wladm] INFO: Retrying request
[wladm] Oct 06, 2014 1:42:55 PM org.apache.http.impl.client.DefaultRequestDirector tryExecute
[wladm] INFO: I/O exception (java.net.SocketException) caught when processing request: Software caused connection abort: socket write error
[wladm] Oct 06, 2014 1:42:55 PM org.apache.http.impl.client.DefaultRequestDirector tryExecute
[wladm] INFO: Retrying request
[wladm] Error accessing http://XXX.XX.XX.XXX:XXXX/wladmin/management-apis/1.0/runtimes/MyApp/applications?locale=en_GB:

BUILD FAILED
D:\XXX\build.xml:200: com.ibm.worklight.admin.restclient.RESTException: Error accessing http://XXX.XX.XX.XXX:XXXX/wladmin/management-apis/1.0/runtimes/MyApp/applications?locale=en_GB: Software caused connection abort: socket write error
    at com.ibm.worklight.admin.restclient.RESTClient.getResponse(RESTClient.java:1062)
    at com.ibm.worklight.admin.restclient.RESTClient.getPOSTResponse(RESTClient.java:1207)
    at com.ibm.worklight.admin.restclient.RESTClient.getPOSTFileResponse(RESTClient.java:1227)
    at com.ibm.worklight.admin.commands.DeployApp.getResponse(DeployApp.java:41)
    at com.ibm.worklight.admin.restclient.ActionClient.execute(ActionClient.java:85)
    at com.ibm.worklight.admin.ant.types.AbstractActionElement.executeCommand(AbstractActionElement.java:76)
    at com.ibm.worklight.admin.ant.types.ActionElement.executeCommands(ActionElement.java:43)
    at com.ibm.worklight.admin.ant.WladmTask.executeCommands(WladmTask.java:441)
    at com.ibm.worklight.admin.ant.WladmTask.execute(WladmTask.java:290)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:392)
    at org.apache.tools.ant.Target.performTasks(Target.java:413)
    at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399)
    at org.apache.tools.ant.Project.executeTarget(Project.java:1368)
    at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
    at org.apache.tools.ant.Project.executeTargets(Project.java:1251)
    at org.apache.tools.ant.Main.runBuild(Main.java:811)
    at org.apache.tools.ant.Main.startAnt(Main.java:217)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)
Caused by: java.net.SocketException: Software caused connection abort: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
    at org.apache.http.impl.io.AbstractSessionOutputBuffer.write(AbstractSessionOutputBuffer.java:153)
    at org.apache.http.impl.io.ContentLengthOutputStream.write(ContentLengthOutputStream.java:114)
    at org.apache.http.entity.mime.content.FileBody.writeTo(FileBody.java:105)
    at org.apache.http.entity.mime.HttpMultipart.doWriteTo(HttpMultipart.java:206)
    at org.apache.http.entity.mime.HttpMultipart.writeTo(HttpMultipart.java:224)
    at org.apache.http.entity.mime.MultipartEntity.writeTo(MultipartEntity.java:183)
    at org.apache.http.entity.HttpEntityWrapper.writeTo(HttpEntityWrapper.java:96)
    at org.apache.http.impl.client.EntityEnclosingRequestWrapper$EntityWrapper.writeTo(EntityEnclosingRequestWrapper.java:108)
    at org.apache.http.impl.entity.EntitySerializer.serialize(EntitySerializer.java:120)
    at org.apache.http.impl.AbstractHttpClientConnection.sendRequestEntity(AbstractHttpClientConnection.java:263)
    at org.apache.http.impl.conn.AbstractClientConnAdapter.sendRequestEntity(AbstractClientConnAdapter.java:227)
    at org.apache.http.protocol.HttpRequestExecutor.doSendRequest(HttpRequestExecutor.java:255)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:645)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:464)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)
    at com.ibm.worklight.admin.restclient.RESTClient.getResponse(RESTClient.java:951)
    ... 25 more

请注意,在服务器日志中没有任何错误的痕迹。与此相关的Ant构建文件的一部分是:

<target name="setup-worklight-tasks">
    <taskdef resource="com/worklight/ant/defaults.properties">
        <classpath>
            <pathelement location="${worklight_ant_builder_path}"/>
        </classpath>
    </taskdef>
    <taskdef resource="com/worklight/ant/deployers/antlib.xml">
        <classpath>
            <pathelement location="${worklight_ant_deployer_path}"/>
        </classpath>
    </taskdef>
</target>

<target name="deploy" depends="setup-worklight-tasks">
    <wladm url="${admin_services_url}" user="${admin_services_user}" password="${admin_services_pass}" secure="false">
        <deploy-app runtime="${runtime_name}" file="bin/MyApp-all.wlapp"/>
    </wladm>
</target>

使用较小的.wlapp文件进行测试不会造成任何问题,从而导致成功部署应用。考虑到Tomcat的默认最大POST大小限制为2 MB,我最初认为问题出在我的连接器配置上。但是,在将所有连接器调整为与此相关的任何内容后,我仍然会收到错误。以下是Tomcat的server.xml

中连接器的配置
...
<Connector port="9080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="9443" maxPostSize="-1" maxSavePostSize="-1" maxHttpHeaderSize="2097152" socketBuffer="-1" bufferSize="20480"/>

<Connector port="9443" protocol="HTTP/1.1" SSLEnabled="true"
           maxThreads="150" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"
           keystoreFile="D:/IBM/apache-tomcat-7.0.55/security/server2_withchain.p12"
           keystoreType="PKCS12"
           keyPass="myPass" maxPostSize="-1" maxSavePostSize="-1" maxHttpHeaderSize="2097152" socketBuffer="-1" bufferSize="20480"/>               

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"  maxPostSize="-1" maxSavePostSize="-1" maxHttpHeaderSize="2097152" socketBuffer="-1" bufferSize="20480"/>
...

我测试的另一件事是通过Worklight控制台UI进行部署,正常工作适用于任何大小的.wlapp文件。我发现与使用Worklight控制台相关的一个有趣的观点是(从检查Tomcat的访问日志)相关的URL是:

XXX.XX.XX.XXX - demo [06/Oct/2014:13:48:05 +0200] "POST /wladmin/management-apis/1.0/runtimes/MyApp/applications?async=true HTTP/1.1" 200 602
0:0:0:0:0:0:0:1 - demo [06/Oct/2014:13:48:05 +0200] "POST /worklightconsole/services/management-apis/1.0/runtimes/MyApp/applications?async=true HTTP/1.1" 200 602

有趣的是存在async=true参数。考虑到这一点并考虑到通常“通过对等方重置连接:套接字写入错误”通常表示客户端存在问题,我认为这可能是wladm任务意外关闭的问题连接(由于async=true参数而在UI中部署时会避免的步骤。)

在部署到Tomcat时,有没有人遇到过使用wladm任务的类似问题?

更新1:

我自己做了.wlapp文件的POST(使用Chrome的POSTman),上传和部署工作正常。这肯定指出wladm ant任务中存在问题。

更新2:

我在我的Ant CI构建过程中替换了使用wladm并调用cURL来向Worklight服务器执行app和适配器文件的POST。我可以确认使用cURL就像魅力一样,这意味着问题确实存在于wladm(更可能是它使用的捆绑式Apache HTTP客户端)。这是我的Ant构建文件的更新部分(我定义了一个使用cURLwladm的布尔标志):

...
<target name="deploy"  unless="deploy_done" depends="build, setup-worklight-tasks" description="Deploy adapters and apps">
    <if>
        <available file="adapters" type="dir"/>
        <then>
            <echo message="Deploying adapters" level="info"/>
            <foreach target="deploy-adapter" param="adapterPath" inheritall="true">
                <path>
                    <dirset dir="adapters" casesensitive="yes">
                        <include name="*"/>
                    </dirset>
                </path>
            </foreach>
        </then>
    </if>
    <echo message="Deploying applications" level="info"/>
    <foreach target="deploy-app" param="appPath" inheritall="true">
        <path>
            <dirset dir="apps" casesensitive="yes">
                <include name="*"/>
            </dirset>
        </path>
    </foreach>
    <property name="deploy_done" value="true"/> 
</target>

<target name="post-curl">
    <exec executable="curl" failonerror="true" outputproperty="curl-output" errorproperty="curl-output-error">
        <arg value="-u"/>
        <arg value="${admin_services_user}:${admin_services_pass}"/>
        <arg value="-F"/>
        <arg value="FILE=@${post-curl.file}"/>
        <arg value="${admin_services_url}/management-apis/1.0/runtimes/${runtime_name}/${post-curl.urlPart}"/>
    </exec>
    <if>
        <not><contains string="${curl-output}" substring="SUCCESS"/></not>
        <then>
            <echo level="error">${curl-output}</echo>
            <echo level="error">${curl-output-error}</echo>
            <fail message="cURL upload failed"/>
        </then>
    </if>
</target>

<target name="deploy-app">
    <basename property="appName" file="${appPath}"/>
    <if>
        <equals arg1="${admin_deploy_curl}" arg2="true"/>
        <then>
            <echo message="Deploying app [${appName}] using cURL..." level="info"/>
            <antcall target="post-curl" inheritAll="true">
                <param name="post-curl.file" value="bin/${appName}-all.wlapp"/>
                <param name="post-curl.urlPart" value="applications"/>
            </antcall>
        </then>
        <else>
            <echo message="Deploying app [${appName}] using wladm..." level="info"/>
            <wladm url="${admin_services_url}" user="${admin_services_user}" password="${admin_services_pass}" secure="false">
                <deploy-app runtime="${runtime_name}" file="bin/${appName}-all.wlapp"/>
            </wladm>
        </else>
    </if>       
    <echo message="App [${appName}] deployed." level="info"/>
</target>

<target name="deploy-adapter">
    <basename property="adapterName" file="${adapterPath}"/>
    <if>
        <equals arg1="${admin_deploy_curl}" arg2="true"/>
        <then>
            <echo message="Deploying adapter [${adapterName}] using cURL..." level="info"/>
            <antcall target="post-curl" inheritAll="true">
                <param name="post-curl.file" value="bin/${adapterName}.adapter"/>
                <param name="post-curl.urlPart" value="adapters"/>
            </antcall>
        </then>
        <else>
            <echo message="Deploying adapter [${adapterName}] using wladm..." level="info"/>                
            <wladm url="${admin_services_url}" user="${admin_services_user}" password="${admin_services_pass}" secure="false">
                <deploy-adapter runtime="${runtime_name}" file="bin/${adapterName}.adapter"/>
            </wladm>
        </else>
    </if>       
    <echo message="Adapter [${adapterName}] deployed." level="info"/>
</target>
...

2 个答案:

答案 0 :(得分:4)

问题是由Tomcat 7.0.55中的新行为引入的。引用其change log:&#34;添加一个新的限制,默认为2MB,以获取Tomcat为中止上传而吞下的数据量。该限制可通过HTTP连接器的maxSwallowSize属性进行配置。&#34;

因此,有三种可能的解决方法:

  • 更改所有&lt;连接器&gt;通过添加属性conf/server.xml(或者您可以施加的应用程序和适配器大小的任何上限),在Tomcat的maxSwallowSize="100000000"中声明。
  • 或使用Worklight Console UI部署应用程序或适配器。
  • 或使用curl程序部署应用程序或适配器。

答案 1 :(得分:0)

根据我的需要,我现在使用我在第二次更新中详述的cURL方法绕过wladm Ant任务(参见原始问题)。通过使用此功能,我再次实现了全自动CI部署。

我将向IBM提交PMR,并根据收到的反馈,继续更新此答案。