Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring RestTemplate readtimeout属性工作不正常-奇怪的问题_Java_Spring_Sockets_Weblogic_Resttemplate - Fatal编程技术网

Java Spring RestTemplate readtimeout属性工作不正常-奇怪的问题

Java Spring RestTemplate readtimeout属性工作不正常-奇怪的问题,java,spring,sockets,weblogic,resttemplate,Java,Spring,Sockets,Weblogic,Resttemplate,我想使用2个服务,并希望有不同的超时。因此,我重写了Spring的SimpleClientHttpRequestFactory,并从我的HttpDaoImpl中使用它 现在,所有东西都在一个环境中工作,但完全相同的EAR在另一个环境中不工作,两个环境中唯一的区别是,我连接的服务URL在一个环境中是负载平衡URL,在另一个环境中是非LB URL。问题出现在负载平衡服务URL中 问题是每次httpReadTimeout生效或正在使用,但不是XYZHttpReadTimeout,即使我有条件地设置超时

我想使用2个服务,并希望有不同的超时。因此,我重写了Spring的
SimpleClientHttpRequestFactory
,并从我的
HttpDaoImpl
中使用它

现在,所有东西都在一个环境中工作,但完全相同的EAR在另一个环境中不工作,两个环境中唯一的区别是,我连接的服务URL在一个环境中是负载平衡URL,在另一个环境中是非LB URL。问题出现在负载平衡服务URL中

问题是每次
httpReadTimeout
生效或正在使用,但不是
XYZHttpReadTimeout
,即使我有条件地设置超时

这是一个非常奇怪的问题,因为所有东西都在一个环境中工作。而不是在其他方面。到目前为止,我猜测可能的根本原因是负载平衡的URL,但我仍然看不到任何关于负载平衡URL可能出现问题的技术原因,因为我的机器将在读取超时后打开并关闭套接字

我已将记录器置于
CustomClientHttpRequestFactory
中,并验证了使用的值是否正确,但最终读取超时没有按预期工作

CustomClientHttpRequestFactory.java

public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory{

    private Log logger = LogFactory.getLog(CustomClientHttpRequestFactory.class);

    @Value("${httpRequest.readTimeoutInMilliseconds}")
    private Integer httpRequestTimeout;

    @Value("${httpRequest.connectionTimeoutInMilliseconds}")
    private Integer httpReadTimeout;

    @Value("${XYZ.httpRequest.readTimeoutInMilliseconds}")
    private Integer XYZHttpRequestTimeout;

    @Value("${XYZ.httpRequest.connectionTimeoutInMilliseconds}")
    private Integer XYZHttpReadTimeout;

    @Value("${sgw.XYZHttp.service.url}")
    private String XYZSystemUrl;


    /**
     * Overriding the default and setting a separate read timeout and HTTP connection timeout values for XYZ transactions.
     * 
     * @param uri
     */
    public void setTimeoutProperties(URI uri){
        boolean isXYZTransaction = isXYZTransaction(uri);
        Integer connectionTimeout = isXYZTransaction ? XYZHttpRequestTimeout : httpRequestTimeout;
        Integer readTimeout = isXYZTransaction ? XYZHttpReadTimeout : httpReadTimeout;
        logger.info("Setting " + connectionTimeout + " : " + readTimeout);
        this.setReadTimeout(readTimeout);
        this.setConnectTimeout(connectionTimeout);
    }

    private boolean isXYZTransaction(URI uri){
        try {
            URI XYZUrl = new URI(XYZSystemUrl);
            logger.info("################################### XYZ Debug");
            logger.info("XYZHttpRequestTimeout = " + XYZHttpRequestTimeout);
            logger.info("XYZHttpReadTimeout = " + XYZHttpReadTimeout);
            return XYZUrl.equals(uri);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }
}
    CustomClientHttpRequestFactory httpRequestFactory = (CustomClientHttpRequestFactory) myAppUtils.getApplicationContext().getBean("httpRequestFactory");
    httpRequestFactory.setTimeoutProperties(lUri);
    restTemplate.setRequestFactory(httpRequestFactory);
    responseString = restTemplate.postForObject(lUri, requestString, String.class);
<bean id="httpRequestFactory" class="com.abc.xyz.customComponents.CustomClientHttpRequestFactory" scope="prototype"/>

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name = "supportedMediaTypes">
                    <list>
                        <value>text/xml;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </list>
    </property>
</bean>
HttpDaoImpl

public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory{

    private Log logger = LogFactory.getLog(CustomClientHttpRequestFactory.class);

    @Value("${httpRequest.readTimeoutInMilliseconds}")
    private Integer httpRequestTimeout;

    @Value("${httpRequest.connectionTimeoutInMilliseconds}")
    private Integer httpReadTimeout;

    @Value("${XYZ.httpRequest.readTimeoutInMilliseconds}")
    private Integer XYZHttpRequestTimeout;

    @Value("${XYZ.httpRequest.connectionTimeoutInMilliseconds}")
    private Integer XYZHttpReadTimeout;

    @Value("${sgw.XYZHttp.service.url}")
    private String XYZSystemUrl;


    /**
     * Overriding the default and setting a separate read timeout and HTTP connection timeout values for XYZ transactions.
     * 
     * @param uri
     */
    public void setTimeoutProperties(URI uri){
        boolean isXYZTransaction = isXYZTransaction(uri);
        Integer connectionTimeout = isXYZTransaction ? XYZHttpRequestTimeout : httpRequestTimeout;
        Integer readTimeout = isXYZTransaction ? XYZHttpReadTimeout : httpReadTimeout;
        logger.info("Setting " + connectionTimeout + " : " + readTimeout);
        this.setReadTimeout(readTimeout);
        this.setConnectTimeout(connectionTimeout);
    }

    private boolean isXYZTransaction(URI uri){
        try {
            URI XYZUrl = new URI(XYZSystemUrl);
            logger.info("################################### XYZ Debug");
            logger.info("XYZHttpRequestTimeout = " + XYZHttpRequestTimeout);
            logger.info("XYZHttpReadTimeout = " + XYZHttpReadTimeout);
            return XYZUrl.equals(uri);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }
}
    CustomClientHttpRequestFactory httpRequestFactory = (CustomClientHttpRequestFactory) myAppUtils.getApplicationContext().getBean("httpRequestFactory");
    httpRequestFactory.setTimeoutProperties(lUri);
    restTemplate.setRequestFactory(httpRequestFactory);
    responseString = restTemplate.postForObject(lUri, requestString, String.class);
<bean id="httpRequestFactory" class="com.abc.xyz.customComponents.CustomClientHttpRequestFactory" scope="prototype"/>

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name = "supportedMediaTypes">
                    <list>
                        <value>text/xml;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </list>
    </property>
</bean>
XML配置

public class CustomClientHttpRequestFactory extends SimpleClientHttpRequestFactory{

    private Log logger = LogFactory.getLog(CustomClientHttpRequestFactory.class);

    @Value("${httpRequest.readTimeoutInMilliseconds}")
    private Integer httpRequestTimeout;

    @Value("${httpRequest.connectionTimeoutInMilliseconds}")
    private Integer httpReadTimeout;

    @Value("${XYZ.httpRequest.readTimeoutInMilliseconds}")
    private Integer XYZHttpRequestTimeout;

    @Value("${XYZ.httpRequest.connectionTimeoutInMilliseconds}")
    private Integer XYZHttpReadTimeout;

    @Value("${sgw.XYZHttp.service.url}")
    private String XYZSystemUrl;


    /**
     * Overriding the default and setting a separate read timeout and HTTP connection timeout values for XYZ transactions.
     * 
     * @param uri
     */
    public void setTimeoutProperties(URI uri){
        boolean isXYZTransaction = isXYZTransaction(uri);
        Integer connectionTimeout = isXYZTransaction ? XYZHttpRequestTimeout : httpRequestTimeout;
        Integer readTimeout = isXYZTransaction ? XYZHttpReadTimeout : httpReadTimeout;
        logger.info("Setting " + connectionTimeout + " : " + readTimeout);
        this.setReadTimeout(readTimeout);
        this.setConnectTimeout(connectionTimeout);
    }

    private boolean isXYZTransaction(URI uri){
        try {
            URI XYZUrl = new URI(XYZSystemUrl);
            logger.info("################################### XYZ Debug");
            logger.info("XYZHttpRequestTimeout = " + XYZHttpRequestTimeout);
            logger.info("XYZHttpReadTimeout = " + XYZHttpReadTimeout);
            return XYZUrl.equals(uri);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }
}
    CustomClientHttpRequestFactory httpRequestFactory = (CustomClientHttpRequestFactory) myAppUtils.getApplicationContext().getBean("httpRequestFactory");
    httpRequestFactory.setTimeoutProperties(lUri);
    restTemplate.setRequestFactory(httpRequestFactory);
    responseString = restTemplate.postForObject(lUri, requestString, String.class);
<bean id="httpRequestFactory" class="com.abc.xyz.customComponents.CustomClientHttpRequestFactory" scope="prototype"/>

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name = "supportedMediaTypes">
                    <list>
                        <value>text/xml;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </list>
    </property>
</bean>

text/xml;字符集=UTF-8

最后,找到问题并使其正常工作

根本原因:
Spring的
RestTemplate
默认使用
org.springframework.http.client.SimpleClientHttpRequestFactory
,并且在多线程环境中会出现问题。如果在多线程环境中使用了
SimpleClientHttpRequestFactory
,并且根据您的一些规则使用了一组以上的超时值(在本例中,基于URL或我使用的服务的不同超时),则会出现此问题

A也一样

这是有道理的,因为我在问题中提到的两个环境的另一个区别是,一个环境(一切正常)总是有一个用户,这意味着只有一个线程,而另一个环境(我有问题)有许多并发用户,这意味着多个线程

解决方案:
使用
org.springframework.http.client.commonclienthtprequestfactory
,这是Spring 3.0.6版中提供的
org.springframework.http.clienthtprequestfactory
的另一个实现,在多线程环境中运行良好


如果Spring版本为3.0+,则使用
HttpComponents客户端HttpRequestFactory

即使我使用的是HttpComponents客户端HttpRequestFactory,这种情况也会发生在我身上。发生在一个环境中,但不发生在另一个环境中。我有两个restTemplates,每个都配置了自己的超时时间,1分钟,另一个3分钟。我看到的是,每件事的超时时间都是1分钟。我没有尝试
httpcomponents客户端httprequestfactory
,但我知道它可以与
org.springframework.http.client.commonclienthtprequestfactory一起工作。不管怎样,我找到了问题的原因。它实际上是前端上的一个apachehttpd服务器,超时设置为1分钟。谢谢@hagrawal@hagrawal谢谢你提供的有用信息。只有一个问题,我是否可以使用一个RestTemplate并像您描述的那样更改每个请求的超时时间,它是否是线程安全的?因为目前我有多个RestTemplate,比如一个读取超时为1000ms的RestTemplate,另一个为3000ms。。所以每次他们需要一个新的超时值时,我都会创建一个新的RestTemplate,我认为我当前的设计很糟糕。请参阅我上一个发布的问题。非常感谢您的帮助。@prettyvoid很抱歉没有及时回复。我认为您可以使用singleton RestTemplate,为每个请求创建单独的“CommonClientHttPrequestFactory”,并在其上设置特定于请求的超时。