Load Balanced的 Rest Template用法

LoadBalanced的RestTemplate用法 #

开发中,偶尔会碰到以下的情况

某个web应用提供的某个http接口,刚好满足了我的需求,我需要调用它
它是个web服务,所以它没有提供 RPC接口,我不能像调用Remote接口一样调用它
而直接通过写死 ip:port 的方式来调用,显然也是不行的( 容器重新发布后ip会变化 )

这时候,你可能会选择通过 http://{域名}/{path} 的方式来调用。

这种方式的确是可行的,但是我们生产环境的机器一般都是在同一个内网的,通过域名的方式调用,是从外网兜了一圈,经过网关,再访问到web

这样肯定会增加耗时以及资源消耗

这时候你可能会问,那么有没有一种方式可以通过内网访问,客户端又不用关心服务端的ip呢?

显然答案是肯定的。

通过调研发现,通过 @LoadBalanced 注解的 RestTemplate 的Bean,可以作为 Load Balancer Client 来使用

下面提供demo:

服务端 #

// 服务端提供的需要被调用的接口 服务端应用名称为:duiba-test-web
@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/testLoadBalanced")
    public String testLoadBalanced() {
        return "loadBalanced invoke success!";
    }
}

客户端 #

// 配置类
@Configuration
public class RestTemplateConfiguration {

    // 具有 Load Balancer Client 特性的 RestTemplate
    @LoadBalanced
    @Bean
    public RestTemplate loadBalancedRestTemplate(HttpClient httpClient) {
        return this.getRestTemplate(httpClient);
    }
    
    // 普通的 RestTemplate
    @Bean
    public RestTemplate restTemplate(HttpClient httpClient) {
        return this.getRestTemplate(httpClient);
    }

    private RestTemplate getRestTemplate(HttpClient httpClient) {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(3000);
        httpRequestFactory.setConnectTimeout(3000);
        httpRequestFactory.setReadTimeout(15000);
        httpRequestFactory.setHttpClient(httpClient);
        return new RestTemplate(httpRequestFactory);
    }

}

// 客户端控制器
@RequestMapping("/testLoadBalanced")
@RestController
public class TestLoadBalancedController {

    @Resource
    private RestTemplate loadBalancedRestTemplate;

    @GetMapping("/test")
    public String test() {
        return loadBalancedRestTemplate.getForObject("http://duiba-test-web/test/testLoadBalanced", String.class);
    }
}

以上代码,跑通后,通过访问客户端的 /testLoadBalanced/test 接口,可以成功调用服务端,并且得到 【loadBalanced invoke success!】 的输出结果

在明确了使用方式后,还需要注意:
1、通过 @LoadBalanced 注解的 RestTemplate 的Bean (loadBalancedRestTemplate) 只能发起 http://{appName}/{path} 的请求,不能发 http://{ip:port}/{path} 或者 http://{域名}/{path} 的请求
所以如果要发起后两种方式的请求,需要再创建一个【普通的 RestTemplate Bean (如Demo中所示)】
2、涉及到的客户端和服务端,都是需要注册到eureka的(某些未注册到eureka的前端应用,不支持这样的调用)

上面仅提供一个简单的使用方式,如果需要了解一些其他事项,可以访问 Spring Cloud 官方文档