我使用Spring Integration 4.3.9.RELEASE和Apache HTTP組件HttpClient(4.5.2)將包含300k上傳文件的請求中繼到後端服務。有時整個配置工作正常。但有時它表現不佳,而且它將需要將近10分鐘才能發送請求並獲得迴應。我使用純Java編寫了一些測試(請參閱Sending HTTP POST Request In Java),結果如下。如何使用大緩衝區設置HTTP出站網關發送請求
+------------------------------+------------------------+
| Data block size | Pause | Totally time consuming |
+------------------------------+------------------------+
| 2k | 1 second | ~6 minutes |
| 2k | 0.1 seocnd | ~33 seconds |
| 4k | 0.1 second | ~16 seconds |
| 0.2k | 0.1 second | ~6 minutes |
+------------------------------+------------------------+
每2k暫停1s和每0.2k暫停0.1s的情景都具有關閉時間流逝值。我想最可能發生的事情是發送數據的小塊(0.2k),但更少的停頓間隔(0.1s)。顯然不令人滿意的是,需要10分鐘才能得到迴應。 那麼如何設置緩衝區有點大以保證性能?
我的配置如下。
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.apache.http.impl.client.HttpClients"/>
<property name="targetMethod" value="createMinimal"/>
</bean>
</constructor-arg>
<property name="connectTimeout" value="${wonders.cloud.api.request.timeout}" />
<property name="readTimeout" value="${wonders.cloud.api.request.timeout}" />
</bean>
</constructor-arg>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<bean class="org.springframework.http.converter.FormHttpMessageConverter">
</bean>
</list>
</property>
</bean>
<bean id="objectMapper" class="org.springframework.integration.support.json.Jackson2JsonObjectMapper">
<constructor-arg ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" >
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg index="0" type="java.lang.String" value="yyyy-MM-dd'T'HH:mm:ss" />
</bean>
</property>
<property name="serializationInclusion" value="#{ T(com.fasterxml.jackson.annotation.JsonInclude.Include).NON_NULL }" />
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="targetObject" ref="jacksonObjectMapper"/>
<property name="targetMethod" value="disable"/>
<property name="arguments" value="#{ T(com.fasterxml.jackson.databind.DeserializationFeature).FAIL_ON_UNKNOWN_PROPERTIES }"/>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="targetObject" ref="jacksonObjectMapper"/>
<property name="targetMethod" value="enable"/>
<property name="arguments" value="#{ T(com.fasterxml.jackson.databind.DeserializationFeature).READ_UNKNOWN_ENUM_VALUES_AS_NULL }"/>
</bean>
<int-http:inbound-gateway id="certificateInboundGateway"
path="/{uuid}/certificate"
supported-methods="POST"
request-channel="certificateRequestChannel"
reply-channel="certificateResponseChannel"
reply-key="fullway"
view-name="index">
<int-http:header name="uuid" expression="#pathVariables.uuid" />
</int-http:inbound-gateway>
<int:channel id="certificateRequestChannel" />
<int:channel id="certificateResponseChannel" />
<int:chain id="certificateProcessChain"
input-channel="certificateRequestChannel"
output-channel="certificateResponseChannel">
<int:header-enricher>
<int:header name="multipartForm" expression="payload"/>
</int:header-enricher>
<int:transformer expression="headers.uuid" />
<int:gateway request-channel="crmMemberInfoRetrieveChannel" />
<int:filter expression="payload != null" />
<int:transformer expression=" T(com.wd.fw.business.facade.huayan.transformer.WondersCloudObjectTransformer).buildCertificateForm(headers.multipartForm, payload.get('userid'), '${wonders.cloud.api.token}') " />
<int:transformer ref="commonHeaderEnricher" method="transform" />
<int:header-enricher>
<int:header name="octopus_sid" expression="'${wonders.cloud.api.octopus.sid}'" overwrite="true" />
<int:header name="Content-Type" expression="'multipart/form-data'" overwrite="true" />
<int:header name="octopus_apiid" expression="'${wonders.cloud.api.certificate.octopus.apiid}'" />
</int:header-enricher>
<int-http:outbound-gateway url="${wonders.cloud.api.protocol}://${wonders.cloud.api.host}/${wonders.cloud.api.context.path}"
http-method="POST"
header-mapper="headerMapper"
rest-template="restTemplate"
charset="UTF-8"
expected-response-type="java.lang.String">
<int-http:request-handler-advice-chain>
<ref bean="retrier" />
</int-http:request-handler-advice-chain>
</int-http:outbound-gateway>
<int:gateway request-channel="dataEncryptChannel" />
</int:chain>
非常感謝。
非常感謝@ArtemBilan的回答。我認爲它確實增加了緩衝區大小。但是,緩衝區大小並不是性能的關鍵,任何其他謎團都需要探索。 –
我試過兩種方法來測試這個問題,HttpClient和純Java,在服務器端收到的請求沒有區別。所以很難說,服務器有一些問題。 –