天天看点

restTemplate服务调用踩坑

restTemplate 调用服务的不同的方式需要的服务实例是不一样的。

restTemplate 调用服务有以下几种方式:请求地址直接调用、服务名调用

请求地址直接调用

restTemplate实例如果使用@Autowire方式注入,url中直接写明调用接口具体的IP地址(域名)及端口号

服务名调用

服务名调用也可以分为两种方式:一种是自行获取注册中心的服务列表,根据服务名找到对应的服务实例进行调用;第二种方法就是使用@LoadBalanced注解,系统自动根据hostName来获取对应的服务实例,LoadBalancerInterceptor.intercept如下

public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
        URI originalUri = request.getURI();
        String serviceName = originalUri.getHost();
        Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
        return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
    }
           

踩坑过程

项目使用了spring boot 2.2.5,spring cloud Finchley.SR2

该项目主要用于调用外部公司的接口,为本公司的其他的系统提供统一的调用外部公司接口的地址。调用外部公司接口时使用请求地址直接调用。项目中我直接使用@Autowire方式注入restTemplate实例,此时调用外部公司接口可以正常调用,回调本公司其他服务的接口时通过服务名调用,调用接口失败,调用时没有将服务名转为对应的IP及端口号。

restTemplate实例上增加@LoadBalanced注解后,本公司接口调用成功,外部公司接口调用失败(接口调用时,IP地址也被认为是服务名,到服务列表中去寻找对应的服务实例,找不到对应的实例报错了)最终在启动类里注入了两个restTemplate实例

错误排查的过程中,还遇到了另外一个小问题,版本降低到E版本之后增加了@LoadBalanced注解之后还是无法通过服务名进行调用,发现启动类上没有加@EnableDIscoveryClient注解,增加该注解之后通过服务名调用接口成功。网上查询发现E版本之后无需在启动类上增加服务发现的相关注解,E版本是否需要加该注解,大家可以自行验证一下。

菜鸟踩坑中,高手们请自动忽略