我使用Spring从我的应用程序执行RestTemplate请求。我们需要调用几种服务,一些在互联网上,一些在内部网上,一些快速的,有些慢的。我已经被指示为每个服务配置自定义设置,基本上是连接超时、读取超时。
这些设置将非常具体--例如,托管在intranet上的服务的超时时间为2-5秒,而它们为99.9%的请求提供了1000 5s的SLA。而其他第三方服务则在10-60岁左右。
由于这些参数只能在工厂中为模板设置,所以我正在创建多个bean,不同的工厂仅在超时时有所不同。就像这样:
@Bean
RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
factory.setReadTimeout(20000);
factory.setConnectTimeout(5000);
RestTemplate restTemplate = new RestTemplate(factory);
}
我担心这最终会造成一场维护噩梦。它能以更好的方式解决吗?
PS:应用程序是一个调用各种服务的monolith。
发布于 2020-06-25 09:55:31
使用RestTemplate bean的参数化构造解决了我的问题。bean现在被配置为:
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public RestTemplate getRestTemplate(String configParam){
int connectionTimeout; //get from config using configParam
int readTimeout; //get from config using configParam
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(connectionTimeout);
factory.setReadTimeout(readTimeout);
return new RestTemplate(factory);
}
而不是@Autowiring这个字段,它可以注入到可能的@PostConstruct方法中,如下所示。依赖bean可以执行以下操作:
@Autowire
BeanFactory beanFactory;
RestTemplate restTemplate;
@PostConstruct
public void init(){
restTemplate = beanFactory.getBean(RestTemplate.class, configParam);
}
在这里,您可以使用自定义设置在restTemplate
中注入bean。
发布于 2020-06-24 14:49:24
您必须创建多个RestTemplates并分配超时、连接池大小。连接池将大大提高性能。
我对连接属性进行了硬编码,您可以从application.properties文件中选择它。
@Configuration
class RestTemplateConfigs {
@Bean
public HttpClient httpClient() {
return HttpClientBuilder.create()
.setMaxConnPerRoute(200)
.setMaxConnTotal(50)
.setConnectionTimeToLive(10L, TimeUnit.SECONDS)
.build();
}
@Bean(name = "restTemplate1")
RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
RestTemplate restTemplate = new RestTemplate(factory);
return restTemplate;
}
}
您可以使用限定符名称创建多个RestTemplates并自动更新它。
发布于 2020-06-24 15:00:48
免责声明:我的答案建议使用另一个Http客户端,而不是Rest模板--如果您必须使用Rest模板,那么我的答案就无关紧要了。
我处理了一个类似的设计问题,下面是我所做的。我写了我自己的HttpClient课程。它的使用要比大多数已知的Http客户端简单得多。这个类可以单独使用,或者(这与您的情况相关)它可以用作一组类的父类(实现相同的接口),其中每个类都是特定Rest服务的Http客户端。在这个类中,您可以预先设置目标URL和所有参数(如读取和连接超时等)。一旦预先设置了该类,只需调用sendHttpRequestMethod()即可。只是为了扩展一下--假设您有一个具有CRUD的用户Rest服务,该服务由具有不同HTTP方法的特定URL调用实现,并且可能是不同的URL。(假设除了创建(POST) update (PUT)、读取(GET)和delete (DELETE)方法之外,位于HTTP://www.myserver.com:8083/user :8083/user/ deactivate )的方法还将在URLs ://www.myserver.com:8083/user/ activate /和HTTP://www.myserver.com:8083/user/deactivate上激活和停用(例如,两种GET)。因此,在本例中,您的Http客户机将设置所有所需的超时和其他配置,并且它还会预先设置目标URL HTTP://www.myserver.com:8083/user。正如上面提到的,它将有六个方法,其中每个方法只调用父类方法sendHttpRequest()。当然,对于激活和停用方法,您将需要附加“激活”和“禁用”后缀的预置基URL。因此,对于每个REST服务,您可以创建一个专门的Http客户机,因为基类已经完成了大部分工作。除此之外,我还为实现相同接口的任何类组编写了一个自填充工厂。对于该工厂,您所要做的就是编写附加的Http客户端,工厂将检测到它,并根据预先定义的名称或类的名称(根据您的选择)使其可以单独使用。所有这些对我来说都很好,所以我把它打包到了名为MgntUtils的开源库中,并在Maven和Github上发布了它(带有源代码和Javadoc )。JavaDoc是可用的这里)。关于自填充工厂的详细说明可以在Javadoc 这里中看到。另外,关于库的一般文章可以找到这里,关于自填充工厂的思想和实现的具体文章可以找到这里。源代码中的包com.mgnt.lifecycle.management.example包含一个工作示例。我希望这能帮到你。
https://stackoverflow.com/questions/62557080
复制相似问题