ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最核心的逻辑来了:RibbonRoutingFilter是如何将请求转发给服务的

2019-06-28 20:49:10  阅读:505  来源: 互联网

标签:return 转发给 RibbonRoutingFilter request public context Override response 请求


1.RibbonRoutingFilter类

@Override
public Object run() {
	RequestContext context = RequestContext.getCurrentContext();
	this.helper.addIgnoredHeaders();
	try {
		RibbonCommandContext commandContext = buildCommandContext(context);
		ClientHttpResponse response = forward(commandContext);
		setResponse(response);
		return response;
	}
	//省略(catch信息)
}

点击forward(commandContext)进入如下代码。

2.RibbonRoutingFilter类

protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception {
	Map<String, Object> info = this.helper.debug(context.getMethod(),
			context.getUri(), context.getHeaders(), context.getParams(),
			context.getRequestEntity());

	RibbonCommand command = this.ribbonCommandFactory.create(context);
	try {
		ClientHttpResponse response = command.execute();
		this.helper.appendDebug(info, response.getRawStatusCode(), response.getHeaders());
		return response;
	}
	catch (HystrixRuntimeException ex) {
		return handleException(info, ex);
	}
}

分析:
1)第1行是解析context里面的信息,封装为一个map。
2)点击下面这行代码,进入第3步

RibbonCommand command = this.ribbonCommandFactory.create(context);  

3)核心逻辑,点击 command.execute()进入第4步

ClientHttpResponse response = command.execute();     	

3.HttpClientRibbonCommandFactory类

@Override
public HttpClientRibbonCommand create(final RibbonCommandContext context) {
	ZuulFallbackProvider zuulFallbackProvider = getFallbackProvider(context.getServiceId());
	//省略
	return new HttpClientRibbonCommand(serviceId, client, context, zuulProperties, zuulFallbackProvider,
			clientFactory.getClientConfig(serviceId));
}

分析:
1)这个可以用于做同步降级,后面项目会用到

ZuulFallbackProvider zuulFallbackProvider = getFallbackProvider(context.getServiceId());

2)返回的是一个HttpClientRibbonCommand对象

4.HystrixCommand类

public R execute() {
        try {
            return queue().get();
        } catch (Exception e) {
            throw Exceptions.sneakyThrow(decomposeException(e));
        }
    }

点击queue()进入如下代码

5.HystrixCommand类

public Future<R> queue() {     
    final Future<R> delegate = toObservable().toBlocking().toFuture();
	
    final Future<R> f = new Future<R>() {
        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            /*
			省略
			*/
		}

        @Override
        public boolean isCancelled() {
            return delegate.isCancelled();
		}

        @Override
        public boolean isDone() {
            return delegate.isDone();
		}

        @Override
        public R get() throws InterruptedException, ExecutionException {
            return delegate.get();
        }

        @Override
        public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            return delegate.get(timeout, unit);
        }        	
    };

    if (f.isDone()) {
        try {
            f.get();
            return f;
        } catch (Exception e) {
          		/*
				省略
				*/
          }
    }

    return f;
}

分析:
1)好好研究下Future。
2)进一步断点进入第6步

6.AbstractRibbonCommand类

@Override
protected ClientHttpResponse run() throws Exception {
	final RequestContext context = RequestContext.getCurrentContext();

	RQ request = createRequest();
	RS response;
	
	boolean retryableClient = this.client instanceof AbstractLoadBalancingClient
			&& ((AbstractLoadBalancingClient)this.client).isClientRetryable((ContextAwareRequest)request);
	
	if (retryableClient) {
		response = this.client.execute(request, config);
	} else {
		response = this.client.executeWithLoadBalancer(request, config);
	}
	context.set("ribbonResponse", response);

	if (this.isResponseTimedOut()) {
		if (response != null) {
			response.close();
		}
	}

	return new RibbonHttpResponse(response);
}

分析:
1)retryableClient默认为false,所以在if-else语句中执行的是

response = this.client.executeWithLoadBalancer(request, config);

2)这里进一步执行会跳转到第7步中
3)根据拿到的server,构造实际的请求

URI finalUri = reconstructURIWithServer(server, request.getUri());    

finalUri的值为:

http://localhost:9090/ServiceB/user/sayHello/1
4)这行代码调用底层的http组件,发送请求到对应的机器上去。

return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig));

5)将执行结果response设置到context中去。

context.set("ribbonResponse", response);

7.AbstractRibbonCommand类

public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
     LoadBalancerCommand<T> command = buildLoadBalancerCommand(request, requestConfig);

      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) {
        //省略
      }
      
  }

进入这个方法一直断点会到第8步中

8.LoadBalancerCommand类

private Observable<Server> selectServer() {
    return Observable.create(new OnSubscribe<Server>() {
        @Override
        public void call(Subscriber<? super Server> next) {
            try {
                Server server = loadBalancerContext.getServerFromLoadBalancer(loadBalancerURI, loadBalancerKey);   
                next.onNext(server);
                next.onCompleted();
            } catch (Exception e) {
                next.onError(e);
            }
        }
    });
}

分析:
1)点击getServerFromLoadBalancer(loadBalancerURI, loadBalancerKey)进入

9.LoadBalancerContext类

 public Server getServerFromLoadBalancer(@Nullable URI original, 
 			@Nullable Object loadBalancerKey) throws ClientException {
       /*
	省略
	*/
       ILoadBalancer lb = getLoadBalancer();
       if (host == null) {
           // Partial URI or no URI Case
           // well we have to just get the right instances from lb - or we fall back
           if (lb != null){
               Server svc = lb.chooseServer(loadBalancerKey);
               //省略
               return svc;
           } else {
            	//省略
             }
   }

分析:
1)这行代码是拿到一个server。这里loadBalancerKey默认为null。

Server svc = lb.chooseServer(loadBalancerKey);

这里全速前进会返回到第6步中的方法中

标签:return,转发给,RibbonRoutingFilter,request,public,context,Override,response,请求
来源: https://blog.csdn.net/zjuwzp/article/details/94046202

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有