RestTemplate负载均衡

·  阅读 670

在RestTemplate使用中,很多情况下不了解的开发者认为RestTemplate只是OKHttp、HttpClient这些工具类的替代者,其实这两者是有着本质区别的。OKHttp以及HttpClient这些工具类是Java用来发送Http请求的,这个在日常开发中经常使用,但是RestTemplate定位不是这样,并不是为了取代Http工具类的使用,相反它底层可以使用各种不同的Http工具类,它的目的更多在于简化Http工具类的使用,并且可以通过Spring注解的方式来增强RestTemplate的功能,比如配置负载均衡。

配置RestTemplate

@Configuration
@Slf4j
public class RestTemplateConfig {
    @Bean
    @LoadBalanced    //RestTemplate负载均衡生效
    public RestTemplate getRestTemplate(){
        OkHttpClient okHttpClient = OkHttpClientObject.CLIENT.getClientInstance();
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory(okHttpClient));   //配置OKHttp使用的工具类,这里使用OKHttp
        return restTemplate;

    }
}
复制代码

RestTemplate调用

调用RestTemplate的方法有很多,restTemplate提供了常见的getpostput等方法的调用,这里以Post方法为例进行介绍。

//header一级提交的Post参数均封装成HttpEntity,如果不希望对返回参数进行解析,可以统一返回String
private String sendRequestByRestTemplate(HttpServletRequest wrapper, String serviceName, String path) {
    try {
        String reqUrl = String.format("http://%s%s",serviceName,path);
        HttpHeaders headers = getHttpHeaders(wrapper, reqUrl);
        HttpEntity<String> reqData = new HttpEntity<>  (IOUtils.toString(wrapper.getReader()),headers);
        String result = restTemplate.postForObject(reqUrl,reqData,String.class);
        return result;
    }catch (Exception e){
        log.info("rpc send request failed [{}]",e.getMessage());
        return "";
    }
}
复制代码

header方法如下所示:

private HttpHeaders getHttpHeaders(HttpServletRequest wrapper, String reqUrl) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    Enumeration<String> originHeadersNames = wrapper.getHeaderNames();
    while (originHeadersNames.hasMoreElements()){
        String name = originHeadersNames.nextElement();
        if(!name.contains("x-hmac-auth")){
            headers.add(name, wrapper.getHeader(name));
        }
    }
    return headers;
}
复制代码

需要注意的是,如果希望启用负载均衡,那么传入RestTemplate中的url地址的格式必须是:http://${serviceId}/${requestPath} 其中serviceId是Eureka中注册的服务名称,requestPath是请求路径。具体原因可以参考如下的代码:

public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
    //通过servieId找到负载均衡器
    ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
    Server server = this.getServer(loadBalancer, hint);
    if (server == null) {
        throw new IllegalStateException("No instances available for " + serviceId);
    } else {
        RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
        return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
    }
}
复制代码

很多开发者都知道RestTemplate支持负载均衡器,但是在使用过程中如果没有注意到调用的请求格式,那么在实际应用中就有肯能找不到合法的后端调用服务地址,进而抛出异常。

小结

以上是本人在使用RestTemplate中的一些小的收获,希望能够帮的上大家。下一篇文章介绍一下RestTemplate的源码。

分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改