RetrofitClient的用法介绍

498 阅读2分钟

公司项目中经常会有涉及到各个服务之间的调用,最开始都是使用HttpClient进行管理。最初的时候这种做法没有什么问题,可是随着用户体量变大,服务的增多,逐渐暴露不足之处。

  1. 大量的uri信息需要配置
  2. 无法实现服务之间的负载均衡

最开始的想法是使用OpenFeign解决该现象,后来无意中发现Retrofit这个组件。它与OpenFeign的使用方法大体一致,都能够解决微服务场景下:服务自动发现、服务负载均衡、服务降级等要求。

Retrofit集成

在maven的pom文件中引入retrofi-spring-boot-starter

<dependency>
    <groupId>com.github.lianjiatech</groupId>
    <artifactId>retrofit-spring-boot-starter</artifactId>
    <version>2.3.7</version>
</dependency>

自动化配置

@Configuration
public class RetrofitConfig {

    /***
    *
    * 这里是配合rabbion实现负载均衡策略
    **/
    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Bean
    public ServiceInstanceChooser serviceInstanceChooser() {
        return new SpringCloudServiceInstanceChooser(loadBalancerClient);
    }
}

客户端声明

客户端声明支持两种方式,一种是非微服务体系,一种是微服务体系

非微服务体系下

调用非微服务体系下的api,采用的是baseUrl参数,显示的声明域名。


@Component
@RetrofitClient(baseUrl = "http://a.b.c/user")
public interface RemoteUserService {

    /**
     * 获取用户信息
     * @param memberId
     * @return
     */
    @POST("personHomePage/getPersonFollowData")
    Result<List<Long>> getUserInfo(@Query("memberId") Long memberId);
}

微服务体系下

调用微服务体系下的api,采用的是serviceId参数,自动发现注册在nacos中的所有服务,并进行自动选择,最终实现负载均衡策略

@Component
@RetrofitClient(serviceId = "order")
public interface RemoteOrderService {


    @GET("v1/order/{memberId}")
    R<List<Long>> getOrderByUserId(@Path("memberId") Long memberId);


    
}

如何实现两种形式调用

  1. 发起一个请求调用的时候,retrofit实现了拦截器的功能,根据传入的参数实现了不同策略的调用
  2. 在自动化配置中注册到Spring Bean中的serviceInstanceChooser 实现了负载均衡的选择
public class ServiceChooseInterceptor implements Interceptor {

    protected final ServiceInstanceChooser serviceInstanceChooser;

    public ServiceChooseInterceptor(ServiceInstanceChooser serviceDiscovery) {
        this.serviceInstanceChooser = serviceDiscovery;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Method method = Objects.requireNonNull(request.tag(Invocation.class)).method();
        Class<?> declaringClass = method.getDeclaringClass();
        RetrofitClient retrofitClient =
                AnnotatedElementUtils.findMergedAnnotation(declaringClass, RetrofitClient.class);
        String baseUrl = retrofitClient.baseUrl();
        if (StringUtils.hasText(baseUrl)) {
            return chain.proceed(request);
        }
        // serviceId服务发现
        String serviceId = retrofitClient.serviceId();
        URI uri = serviceInstanceChooser.choose(serviceId);
        HttpUrl url = request.url();
        HttpUrl newUrl = url.newBuilder()
                .scheme(uri.getScheme())
                .host(uri.getHost())
                .port(uri.getPort())
                .build();
        Request newReq = request.newBuilder()
                .url(newUrl)
                .build();
        return chain.proceed(newReq);
    }
}