2017-09-04 78 views
0

我使用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> 

非常感谢。

回答

0

你可以尝试这样的事情:

ConnectionConfig connConfig = ConnectionConfig.custom() 
    .setBufferSize(DESIRED_BUFFER_SIZE) 
    .build(); 

CloseableHttpClient client = HttpClients.custom() 
     .setDefaultConnectionConfig(connConfig) 
     .build(); 

Setting socket buffer size in Apache HttpClient

Is there a way to see what the current value and change it for the socket buffer size used by Apache Http Client?

但是,为什么你认为这个问题是不是在服务器端?

+0

非常感谢@ArtemBilan的回答。我认为它确实增加了缓冲区大小。但是,缓冲区大小并不是性能的关键,任何其他谜团都需要探索。 –

+0

我试过两种方法来测试这个问题,HttpClient和纯Java,在服务器端收到的请求没有区别。所以很难说,服务器有一些问题。 –

0

增加缓冲区大小无助于提高性能。 最后,我必须创建一个服务激活器,它将通过我的问题中提到的纯java方法向远程发送请求。

我在纯Java中编写了一些测试(参考发送Java POST中的HTTP POST请求),结果如下。

我也比较发送给服务器的请求,并且找不到任何区别。这很奇怪。

相关问题