pre*_*oid 8 spring resttemplate spring-boot
我有@Service几个方法,每个方法使用不同的 web api。每个调用都应该有一个自定义的读取超时。拥有一个 RestTemplate 实例并在每个方法中通过工厂更改超时是否是线程安全的
((HttpComponentsClientHttpRequestFactory)restTemplate.getRequestFactory())
.setReadTimeout(customMillis);
Run Code Online (Sandbox Code Playgroud)
我担心的是我正在更改工厂的超时时间,它不像RequestConfig. 考虑到这些方法可能同时被多个用户调用,这种方法是否是线程安全的?或者每个方法都应该有自己的RestTemplate?
选项 1:多个 RestTemplate
如果要更改创建的连接的属性,则RestTemplate每个配置都需要一个。我最近遇到了同样的问题,并且有两个版本RestTemplate,一个用于“短超时”,一个用于“长超时”。在每个组(短/长)中,我都能够分享RestTemplate.
让您的呼叫更改超时设置,创建连接,并希望最好的是等待发生的竞争条件。我会谨慎行事并创建多个RestTemplate.
例子:
@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.
}
}
Run Code Online (Sandbox Code Playgroud)
然后您可以根据需要将它们连接到您的服务中:
@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...
}
Run Code Online (Sandbox Code Playgroud)
选项 2:将调用封装在断路器中
如果您要调用外部服务,您可能应该为此使用断路器。Spring Boot 与 Hystrix 配合得很好,Hystrix 是断路器模式的一种流行实现。使用 hystrix,您可以控制您调用的每个服务的回退和超时。
假设您对服务 A 有两种选择:1) 便宜但有时慢 2) 贵但速度快。您可以使用 Hystrix 来放弃廉价/慢速,而在真正需要时使用昂贵/快速。或者你可以没有备份,只让 Hystrix 调用一个提供合理默认值的方法。
未经测试的示例:
@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!"
}
}
Run Code Online (Sandbox Code Playgroud)
回退方法也有选项。您可以使用该方法注释@HystrixCommand并尝试另一个服务调用。或者,您可以只提供一个合理的默认值。
初始化后从工厂更改超时RestTemplate只是等待发生的竞争条件(就像托德所解释的那样)。RestTemplate实际上是为了使用预先配置的超时而构建的,并且这些超时在初始化后保持不变。如果您使用Apache HttpClient,那么您可以设置RequestConfig每个请求,在我看来这是正确的设计。
我们已经RestTemplate在项目中的任何地方使用了,但目前我们无法承担随之而来的 http 客户端切换的重构。
现在我最终得到了一个RestTemplate池化解决方案,我创建了一个名为 RestTemplateManager 的类,并赋予它创建模板和池化它们的所有责任。该管理器有一个按服务和 readTimeout 分组的本地模板缓存。想象一下具有以下结构的缓存哈希图:
服务A|1000 -> RestTemplate
服务A|3000 -> RestTemplate
服务B|1000 -> RestTemplate
键中的数字是以毫秒为单位的 readTimeout(以后可以调整键以支持更多的 readTimeout)。因此,当ServiceA请求读取超时时间为1000ms的模板时,管理器将返回缓存的实例,如果不存在,则会创建并返回。
在这种方法中,我不用预先定义 RestTemplates,我只需要向上面的管理器请求 RestTemplate 即可。这也使初始化保持在最低限度。
直到我有时间放弃 RestTemplate 并使用更合适的解决方案为止。
| 归档时间: |
|
| 查看次数: |
17967 次 |
| 最近记录: |