zoukankan      html  css  js  c++  java
  • 【Feign】Feign源码分析(三): FeignClient请求的过程

    FeignClient请求的过程,主要是在发送请求的过程中,整合了Ribbon实现负载均衡,以及从注册中心获取服务列表的,最终响应的过程

    一.源码入口 SynchronousMethodHandler.invoke()方法

    @Override
      public Object invoke(Object[] argv) throws Throwable {
    //发送http请求的模板类,具备请求方法,协议类型,类似,GET /hello HTTP/1.1 RequestTemplate template
    = buildTemplateFromArgs.create(argv);
    //获取重试器,主要用于在异常时的重试 Retryer retryer
    = this.retryer.clone(); while (true) { try {
    //执行请求的核心逻辑
    return executeAndDecode(template); } catch (RetryableException e) { retryer.continueOrPropagate(e); if (logLevel != Logger.Level.NONE) { logger.logRetry(metadata.configKey(), logLevel); } continue; } } }

      执行请求的核心逻辑executeAndDecode()

    Object executeAndDecode(RequestTemplate template) throws Throwable {
    //将requestTemplate对象转换为request对象 类似 GET http://HELLO-SERVICE/hello,以及执行拦截器相关的逻辑
    Request request
    = targetRequest(template); if (logLevel != Logger.Level.NONE) { logger.logRequest(metadata.configKey(), logLevel, request); } Response response; long start = System.nanoTime(); try {
       //这里主要是使用LoadBalanceFeignClient执行execute()方法 response
    = client.execute(request, options); // ensure the request is set. TODO: remove in Feign 10 response.toBuilder().request(request).build(); } catch (IOException e) { if (logLevel != Logger.Level.NONE) { logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start)); } throw errorExecuting(request, e); } long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); boolean shouldClose = true; try { if (logLevel != Logger.Level.NONE) { response = logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime); // ensure the request is set. TODO: remove in Feign 10 response.toBuilder().request(request).build(); } if (Response.class == metadata.returnType()) { if (response.body() == null) { return response; } if (response.body().length() == null || response.body().length() > MAX_RESPONSE_BUFFER_SIZE) { shouldClose = false; return response; } // Ensure the response body is disconnected byte[] bodyData = Util.toByteArray(response.body().asInputStream()); return response.toBuilder().body(bodyData).build(); } if (response.status() >= 200 && response.status() < 300) { if (void.class == metadata.returnType()) { return null; } else { return decode(response); } } else if (decode404 && response.status() == 404 && void.class != metadata.returnType()) { return decode(response); } else { throw errorDecoder.decode(metadata.configKey(), response); } } catch (IOException e) { if (logLevel != Logger.Level.NONE) { logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime); } throw errorReading(request, response, e); } finally { if (shouldClose) { ensureClosed(response.body()); } } }

      client.execute(request, options);执行真实请求

    @Override
        public Response execute(Request request, Request.Options options) throws IOException {
            try {
           //获取请求的URI URI asUri
    = URI.create(request.url()); String clientName = asUri.getHost(); URI uriWithoutHost = cleanUrl(request.url(), clientName); FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest( this.delegate, request, uriWithoutHost); IClientConfig requestConfig = getClientConfig(options, clientName);
           //lbClient主要是通过服务名,在Ribbon中获取服务名对应的FeignLoadBalance,执行executeWithLoadBalancer()
    return lbClient(clientName).executeWithLoadBalancer(ribbonRequest, requestConfig).toResponse(); } catch (ClientException e) { IOException io = findIOException(e); if (io != null) { throw io; } throw new RuntimeException(e); } }

      lbClient(clientName) 整合Ribbon,通过服务名获取FeignLoadBalance

    public FeignLoadBalancer create(String clientName) {
    //优先从缓存工厂里面获取 FeignLoadBalancer client
    = this.cache.get(clientName); if(client != null) { return client; } IClientConfig config = this.factory.getClientConfig(clientName); ILoadBalancer lb = this.factory.getLoadBalancer(clientName); ServerIntrospector serverIntrospector = this.factory.getInstance(clientName, ServerIntrospector.class); client = loadBalancedRetryFactory != null ? new RetryableFeignLoadBalancer(lb, config, serverIntrospector, loadBalancedRetryFactory) : new FeignLoadBalancer(lb, config, serverIntrospector); this.cache.put(clientName, client); return client; }

       executeWithLoadBalancer()方法

    public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
            LoadBalancerCommand<T> command = buildLoadBalancerCommand(request, requestConfig);
         //comand.submit方法就是通过FeignLoadBalancer去获取服务名对应的服务URL
            try {
                return command.submit(
                    new ServerOperation<T>() {
                        @Override
                        public Observable<T> call(Server server) {
                            URI finalUri = reconstructURIWithServer(server, request.getUri());
                            S requestForServer = (S) request.replaceUri(finalUri);
                            try {
                                return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig));
                            } 
                            catch (Exception e) {
                                return Observable.error(e);
                            }
                        }
                    })
                    .toBlocking()
                    .single();
            } catch (Exception e) {
                Throwable t = e.getCause();
                if (t instanceof ClientException) {
                    throw (ClientException) t;
                } else {
                    throw new ClientException(e);
                }
            }
            
        }

    二.流程图

     

  • 相关阅读:
    shell基础命令
    UITest 单元测试常用的断言
    UIColor 使用起来的坑
    appledoc 使用brew命令安装使用
    appledoc 使用
    Xcode升级 Alcatraz 无法使用
    APP多语言环境支持
    VVDocumenter 使用
    NSDate NSString相互转化
    iOS 常见设计模式
  • 原文地址:https://www.cnblogs.com/july-sunny/p/15501949.html
Copyright © 2011-2022 走看看