Dynami c Тайм-аут для Dynami c URL-адрес http-outbound-gateway - PullRequest
1 голос
/ 19 марта 2020

У меня есть http-outbound-gateway, который использует динамические c URL-адреса с подключением и временем ожидания чтения

<int-http:outbound-gateway request-channel="request"
        reply-channel="response" url-expression="headers.serviceUrl" http-method="POST"
        expected-response-type="java.lang.String" charset="UTF-8" request-factory="httpOutboundRequestFactoryBean" message-converters="messageConverterList" header-mapper="headerMapperBean"/>

<bean id="httpOutboundRequestFactoryBean"
      class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
        <property name="readTimeout" value="5000"/>
        <property name="connectTimeout" value="1000"/>
</bean>

Можно ли настроить указанное c время ожидания в соответствии с URL-адресом, определенным в headers.serviceUrl ?

Я искал вокруг и нашел только эту проблему .

Один из возможных способов - использовать непосредственно RestTemplate и каждый раз создавать экземпляр RestTemplate. время и динамически установить requestFactory (с тайм-аутом) в соответствии с URL, но, возможно, есть встроенный способ сделать это с помощью интеграции пружин

заранее спасибо!

EDIT : ADD ANSWER

Я добавил этот активатор службы незадолго до того, как http-outbound-gateway

public class ThreadLocalSample {

public static ThreadLocal<Integer> serviceTimeout = new ThreadLocal<>();

private static final Logger LOGGER = LoggerFactory.getLogger(ThreadLocalSample.class);

public Message<?> setTimeout(final Message<?> message){
    final int number = (new Random().nextInt(20 - 1 + 1) + 1)*1000;
    serviceTimeout.set(number);
    LOGGER.info("Service timeout thread local: "+number);

    return message;
}

Расширил HttpComponentsClientHttpRequestFactory и переопределил конфигурацию слияния, используя локальный тайм-аут:

public class MyHttpConnectionFactory extends HttpComponentsClientHttpRequestFactory {

private RequestConfig requestConfig;

private static final Logger LOGGER = LoggerFactory.getLogger(MyHttpConnectionFactory.class);


@Override
protected RequestConfig createRequestConfig(final Object client) {
    this.requestConfig = super.createRequestConfig(client);
    return this.requestConfig;
}

@Override
protected RequestConfig mergeRequestConfig(final RequestConfig clientConfig) {
    if (this.requestConfig == null) {  // nothing to merge
        return clientConfig;
    }

    final RequestConfig.Builder builder = RequestConfig.copy(clientConfig);
    final int connectTimeout = this.requestConfig.getConnectTimeout();
    if (connectTimeout >= 0) {
        builder.setConnectTimeout(connectTimeout);
    }
    final int connectionRequestTimeout = this.requestConfig.getConnectionRequestTimeout();
    if (connectionRequestTimeout >= 0) {
        builder.setConnectionRequestTimeout(connectionRequestTimeout);
    }
    final int socketTimeout = ThreadLocalSample.serviceTimeout.get();
    LOGGER.info("Service timeout: "+socketTimeout);
    if (socketTimeout >= 0) {
        builder.setSocketTimeout(socketTimeout);
    }
    return builder.build();
}

}

Изменен поток интеграции пружины:

<int-http:outbound-gateway request-channel="request"
        reply-channel="response" url-expression="headers.serviceUrl" http-method="POST"
        expected-response-type="java.lang.String" charset="UTF-8" request-factory="httpOutboundRequestFactoryBean" message-converters="messageConverterList" header-mapper="headerMapperBean"/>

<bean id="httpOutboundRequestFactoryBean"
      class="sample.MyHttpConnectionFactory">
        <property name="readTimeout" value="5000"/>
        <property name="connectTimeout" value="1000"/>
</bean>

1 Ответ

0 голосов
/ 19 марта 2020

Ну, нет, и я сомневаюсь, что мы собираемся сделать что-нибудь по этому вопросу в рамках. Spring Integration полностью полагается на ClientHttpRequestFactory и его контракт. Поэтому максимум, что мы можем предложить, это что-то нестандартное, расширяющее ваши HttpComponentsClientHttpRequestFactory.

Если мы посмотрим на исходный код этой фабрики, мы найдем что-то вроде этого:

public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
    HttpClient client = getHttpClient();

    HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
    postProcessHttpRequest(httpRequest);
    HttpContext context = createHttpContext(httpMethod, uri);
    if (context == null) {
        context = HttpClientContext.create();
    }

    // Request configuration not set in the context
    if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
        // Use request configuration given by the user, when available
        RequestConfig config = null;
        if (httpRequest instanceof Configurable) {
            config = ((Configurable) httpRequest).getConfig();
        }
        if (config == null) {
            config = createRequestConfig(client);
        }
        if (config != null) {
            context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
        }
    }

Таким образом, каждый раз, когда вызывается createRequest(), он обращается к чему-то вроде HttpContext и / или RequestConfig.

Итак, в качестве решения для вашего требования я бы предложил иметь дело с ThreadLocal, который вы заполняете до упомянутого <int-http:outbound-gateway> и считываете из этого пользовательского createHttpContext() или createRequestConfig().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...