HttpClient timeout
У меня есть клиент-серверное приложение, использующее Spring HttpInvokers. Я борюсь с таймаутами. Я вижу другие темы относительно этого, но нет четких ответов.
Насколько я знаю, readTimeout должен контролировать длину транзакции после того, как она уже подключена. Я сделал это очень долго, потому что некоторые процессы, такие как запросы отчетов, требуют времени для запуска. Это работало хорошо в течение длительного периода времени.
Теперь проблема заключается в том, что иногда интернет-соединение не срабатывает или мигает в тот момент, когда делается запрос, и соединение никогда не устанавливается. Вместо ошибки я ввел процедуру повторной попытки, которая перехватывает сбойное соединение и повторяет его. Я хочу, чтобы эти сбои происходили быстро, поэтому я установил для параметров HttpClient soTimeout и connectionManagerTimeout значение 2 секунды.
Казалось, это работает по большей части. Иногда для решения проблемы требуется больше 2 секунд, но это нормально. Проблема в том, что soTimeout, кажется, применяется или переопределяет readTimout. Так что теперь все мои долго выполняющиеся запросы получают функцию повтора, даже если они подключены нормально и просто ждут ответа. Кажется, настройка connectionManagerTimeout ничего не делает. Кажется, ничто не влияет на время, необходимое для фактического установления первоначального соединения.
Есть ли другой параметр тайм-аута, который я должен установить?
<bean id="myServiceInterceptor"
class="org.springframework.remoting.httpinvoker.HttpInvokerClientInterceptor">
<property name="serviceUrl">
<value>https://myhost/myservices/myMgrService</value>
</property>
<property name="remoteInvocationFactory" ref="remoteInvocationFactory"/>
<property name="httpInvokerRequestExecutor">
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor">
<!--read time out is how long we will wait for a reply. This is large in case we are waiting on a long server process-->
<property name="readTimeout" value="2000000"/>
<!-- we manually set this so we can control the parameter timeout values-->
<property name="httpClient">
<bean class="org.apache.commons.httpclient.HttpClient">
<constructor-arg index="0">
<!--we want multi threaded if we want to ever connect in background threads, this is default if not set anyways in CommonsHttpInvokerRequestExecutor but since we are overriding we have to manually set it or we get the simple one-->
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"></bean>
</constructor-arg>
<property name="params">
<bean class="org.apache.commons.httpclient.params.HttpClientParams">
<!--Here we set the socket time out and connection manager time out which is how long we wait for the socket to connect before showing bad feedback.
The default is 60 seconds which makes the client just hang. Now we get immediate response from our RetryConnection-->
<property name="soTimeout" value="2000"/>
<property name="connectionManagerTimeout" value="2000"/>
</bean>
</property>
</bean>
</property>
</bean> </property>
</bean>
<bean id="myServiceMgr" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<list>
<value>clientExceptionAdvisor</value>
<value>retryConnection</value>
<value>myServiceInterceptor</value>
</list>
</property>
<property name="proxyInterfaces">
<value>ServiceIF</value>
</property>
</bean>
* * РЕШЕНИЕ ОБНОВЛЕНИЯ Похоже, soTimout также является тайм-аутом чтения. Есть способ установить тайм-аут соединения, это просто боль. Вот весенний xml, который я использовал:
<bean class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor">
<!--read time out is how long we will wait for a reply. This is large in case we are waiting on a long server process-->
<property name="readTimeout" value="2000000"/>
<!-- we manually set this so we can control the parameter timeout values-->
<property name="httpClient">
<bean class="org.apache.commons.httpclient.HttpClient">
<constructor-arg index="0">
<bean class="org.apache.commons.httpclient.params.HttpClientParams">
<!--Here we set the connection manager time out which is supposed to be how long we wait for the established connection to be returned from the connection manager. This shortness allows us to catch it and enable the retry function.-->
<property name="connectionManagerTimeout" value="2500"/>
</bean>
</constructor-arg>
<constructor-arg index="1">
<!--we want multi threaded if we want to ever connect in background threads, this is default if not set anyways in CommonsHttpInvokerRequestExecutor but since we are overriding we have to manually set it or we get the simple one-->
<bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
<property name="params">
<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
<!--Here we set the socket time out which is essentially the same thing as the readTimeout. It is the time we wait for a response-->
<property name="soTimeout" value="2000000"/>
<!--Here we set the connection time out which is supposed to be how long we wait for the connect to be established. This shortness allows us to catch it and enable the retry function. The default is 60 seconds which makes the client just hang. -->
**<property name="connectionTimeout" value="2500"/>**
</bean>
</property>
</bean>
</constructor-arg>
<property name="params">
<bean class="org.apache.commons.httpclient.params.HttpClientParams">
<!--Here we set the socket time out which is essentially the same thing as the readTimeout. It is the time we wait for a response-->
<property name="soTimeout" value="2000000"/>
<!--Here we set the connection manager time out which is how long we wait to get an established connection returned from the connection manager.
The default is 60 seconds which makes the client just hang. Now we get more immediate response from our RetryConnection. But it isn't totally reliable cause of underlying tcp/ip-->
**<property name="connectionManagerTimeout" value="2500"/>**
</bean>
</property>
</bean>
</property>
</bean>
4 ответа
Вы не можете установить максимальную продолжительность запроса. Это имеет некоторую полезную информацию.
Как правило, для http-соединений у вас должно быть одинаковое время ожидания независимо от типа соединения. Нет смысла иметь несколько тиков, считающих одно и то же в разных точках.
Вы должны настроить свой API так, чтобы отчеты были либо подготовлены заранее, либо запущены в другом потоке, который не блокирует вашего инициатора. Таким образом, вы можете получить объект статуса, который сообщит вам, нужно ли вам снова проверять отчет.
Может быть, я неправильно понимаю проблему здесь, но вы не можете сначала проверить правильность сетевого подключения, прежде чем вызывать sotimeout? Или отключить sotimeout, когда у вас есть действующее соединение?
Извините, если это не актуально, я немного устал:D
Вы можете использовать OkHttp и позвонить
HttpURLConnection connection = okHttpClient.open(new URL(urlStr));
connection.setReadTimeout(60000);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
if(getMethod != null) {
getMethod.abort();
}
}
}, timeout * 1000);
Вы можете попробовать это, чтобы увеличить время ожидания.
или можете предпочесть ссылку Apache HttpComponents HttpClient timeout