Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.5k views
in Technique[技术] by (71.8m points)

spring - RestTemplate set timeout per request

I have a @Service with several methods, each method consumes a different web api. Each call should have a custom read timeout. Is it thread-safe to have one RestTemplate instance and change the timeout via the factory in each method like so

((HttpComponentsClientHttpRequestFactory)restTemplate.getRequestFactory())
.setReadTimeout(customMillis);

My concern is that I'm changing the timeout on the factory and its not like a RequestConfig. Will this approach be thread-safe considering these methods might get called by multiple users at the same time? Or each method should have its own RestTemplate?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Option 1: More than one RestTemplate

If you are changing the properties of the connections created, you will need to have one RestTemplate per configuration. I had this very same problem recently and had two versions of RestTemplate, one for "short timeout" and one for "long timeout". Within each group (short/long) I was able to share that RestTemplate.

Having your calls change the timeout settings, create a connection, and hope for the best is a race condition waiting to happen. I would play this safe and create more than one RestTemplate.

Example:

@Configuration
public class RestTemplateConfigs {
    @Bean("shortTimeoutRestTemplate")
    public RestTemplate shortTimeoutRestTemplate() {
       // Create template with short timeout, see docs.
    }
    @Bean("longTimeoutRestTemplate")
    public RestTemplate longTimeoutRestTemplate() {
       // Create template with short timeout, see docs.
    }
}

And then you can wire them in to your services as needed:

@Service
public class MyService {
    private final RestTemplate shortTimeout;
    private final RestTemplate longTimeout;

    @Autowired
    public MyService(@Qualifier("shortTimeoutRestTemplate") RestTemplate shortTimeout, 
                     @Qualifier("longTimeoutRestTemplate") RestTemplate longTimeout) {
        this.shortTimeout = shortTimeout;
        this.longTimeout = longTimeout;
    }

    // Your business methods here...
}

Option 2: Wrap calls in a Circuit Breaker

If you are calling out to external services, you probably should be using a circuit breaker for this. Spring Boot works well with Hystrix, a popular implementation of the circuit breaker pattern. Using hystrix you can control the fallback for each service you call out to, and the timeouts.

Suppose you have two options for Service A: 1) Cheap but sometimes slow 2) Expensive but fast. You can use Hystrix to give up on Cheap/Slow and use Expensive/Fast when you really need to. Or you can have no backup and just have Hystrix call a method that provides a sensible default.

Untested example:

@EnableCircuitBreaker
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp .class, args);
    }
}

@Service
public class MyService {
    private final RestTemplate restTemplate;

    public BookService(RestTemplate rest) {
        this.restTemplate = rest;
    }

    @HystrixCommand(
        fallbackMethod = "fooMethodFallback",
        commandProperties = { 
            @HystrixProperty(
                 name = "execution.isolation.thread.timeoutInMilliseconds", 
                 value="5000"
            )
        }
    )
    public String fooMethod() {
        // Your logic here.
        restTemplate.exchange(...); 
    }

    public String fooMethodFallback(Throwable t) {
        log.error("Fallback happened", t);
        return "Sensible Default Here!"
    }
}

The fallback method has options too. You could annotate that method with @HystrixCommand and attempt another service call. Or, you could just provide a sensible default.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...