ribbon 详解

1. 顶层架构

2. 简单的示例:使用ResourceTemplate方式

  1. @Test
  2. public void testGroup(){
  3. HttpResourceGroup httpResourceGroup = Ribbon.createHttpResourceGroup("test",
  4. ClientOptions.create().withMaxAutoRetries(3).
  5. withConfigurationBasedServerList("localhost:8081,localhost:8080"));
  6. HttpRequestTemplate<ByteBuf> recommendationsByUserIdTemplate = httpResourceGroup.newTemplateBuilder("recommendationsByUserId", ByteBuf.class)
  7. .withMethod("GET")
  8. .withUriTemplate("/aa/index")
  9. .withHeader("X-Auth-Token", "abc")
  10. //.withFallbackProvider(new RecommendationServiceFallbackHandler())
  11. //.withResponseValidator(new RecommendationServiceResponseValidator())
  12. .build();
  13. RibbonRequest<ByteBuf> request = recommendationsByUserIdTemplate.requestBuilder()
  14. .withRequestProperty("userId", "test")
  15. .build();
  16. ByteBuf buf = request.execute();
  17. byte[] bytes = new byte[buf.capacity()];
  18. buf.readBytes(bytes);
  19. System.out.println(new String(bytes));
  20. }

3.实现:

3.1 关键对象
  1. public interface RibbonRequest<T> {
  2. /**
  3. * Blocking API that returns a single (or last element if there is a sequence of objects from the execution) element
  4. */
  5. public T execute();
  6. /**
  7. * Non blocking API that returns a {@link Future}, where its {@link Future#get()} method is blocking and returns a
  8. * single (or last element if there is a sequence of objects from the execution) element
  9. */
  10. public Future<T> queue();
  11. /**
  12. * Non blocking API that returns an {@link Observable} while the execution is started asynchronously.
  13. * Subscribing to the returned {@link Observable} is guaranteed to get the complete sequence from
  14. * the beginning, which might be replayed by the framework. Use this API for "fire and forget".
  15. */
  16. public Observable<T> observe();
  17. /**
  18. * Non blocking API that returns an Observable. The execution is not started until the returned Observable is subscribed to.
  19. */
  20. public Observable<T> toObservable();
  21. /**
  22. * Create a decorated {@link RequestWithMetaData} where you can call its similar blocking or non blocking
  23. * APIs to get {@link RibbonResponse}, which in turn contains returned object(s) and
  24. * some meta data from Hystrix execution.
  25. */
  26. public RequestWithMetaData<T> withMetadata();
  27. }

明显,最终生成的关键对象RibbonRequest,使用的时观察者模式,底层实现肯定会使用RxJava或者Hystrix。

3.2 关键实现:HystrixObservableCommandChain
  1. HystrixObservableCommandChain<T> createHystrixCommandChain() {
  2. List<HystrixObservableCommand<T>> commands = new ArrayList<HystrixObservableCommand<T>>(2);
  3. if (cacheProvider != null) {
  4. commands.add(new CacheObservableCommand<T>(cacheProvider.getCacheProvider(), cacheProvider.getKey(), cacheHystrixCacheKey,
  5. requestProperties, template.cacheHystrixProperties()));
  6. }
  7. commands.add(new HttpResourceObservableCommand<T>(client, httpRequest, hystrixCacheKey, requestProperties, template.fallbackHandler(),
  8. template.responseValidator(), template.getClassType(), template.hystrixProperties()));
  9. return new HystrixObservableCommandChain<T>(commands);
  10. }

在HystrixObservableCommandChain执行toObservable的时候,会依次便利集合中所有的HystrixObservableCommand,知道其toObservable不为null。

所以,如果cacheProvider不为null会调用CacheObservableCommand的toObservable,如果cacheProvider为null,则直接调用HttpResourceObservableCommand的toObservable.

3.3 http请求:
  1. Observable<HttpClientResponse<ByteBuf>> httpResponseObservable = httpClient.submit(httpRequest);
  1. Observable<T> o =
  2. (server == null ? selectServer() : Observable.just(server))
  3. .concatMap(new Func1<Server, Observable<T>>() {
  4. @Override
  5. // Called for each server being selected
  6. public Observable<T> call(Server server) {
  7. context.setServer(server);
  8. final ServerStats stats = loadBalancerContext.getServerStats(server);
  9. // Called for each attempt and retry
  10. Observable<T> o = Observable
  11. .just(server)
  12. .concatMap(new Func1<Server, Observable<T>>() {
  13. ...
  14. });
  15. if (maxRetrysSame > 0)
  16. o = o.retry(retryPolicy(maxRetrysSame, true));
  17. return o;
  18. }
  19. }
  20. if (maxRetrysSame > 0)
  21. o = o.retry(retryPolicy(maxRetrysSame, true));
  22. return o;

会调用统一服务器n次,后调用下一个服务器m次(n,m为设定的最大调用次数)。

4.简单示例:使用注解方式

  1. public interface AAIndex {
  2. @Http( method = Http.HttpMethod.GET,
  3. uri = "http://localhost:8080/aa/index")
  4. RibbonRequest<ByteBuf> index();
  5. }
  1. @Test
  2. public void testRibbonAnnotation(){
  3. AAIndex aaIndex = Ribbon.from(AAIndex.class);
  4. ByteBuf buf = aaIndex.index().execute();
  5. byte[] bytes = new byte[buf.capacity()];
  6. buf.readBytes(bytes);
  7. System.out.println(new String(bytes));
  8. }

5.实现:

5.1 动态代理:
  1. return (T) Proxy.newProxyInstance(
  2. Thread.currentThread().getContextClassLoader(),
  3. new Class[]{clientInterface, ProxyLifeCycle.class},
  4. new RibbonDynamicProxy<T>(clientInterface, resourceGroupFactory, configFactory, transportFactory, processors)
  5. );

使用JDK自带的代理类实现,代理了client接口,和ProxyLifeCycle,其实现具体类为RibbonDynamicProxy。

5.2 支持的注解:
  1. static void registerAnnotationProcessors(AnnotationProcessorsProvider processors) {
  2. processors.register(new HttpAnnotationProcessor());
  3. processors.register(new HystrixAnnotationProcessor());
  4. processors.register(new CacheProviderAnnotationProcessor());
  5. processors.register(new ClientPropertiesProcessor());
  6. }

最终的实现跟非注解方式的实现是一致的。

  1. @SuppressWarnings("unchecked")
  2. public <O> RibbonRequest<O> executeFromTemplate(Object[] args) {
  3. HttpRequestBuilder<?> requestBuilder = httpRequestTemplateBuilder.build().requestBuilder();
  4. withParameters(requestBuilder, args);
  5. withContent(requestBuilder, args);
  6. return (RibbonRequest<O>) requestBuilder.build();
  7. }

ribbon 详解的更多相关文章

  1. Ribbon详解

    转自Ribbon详解 简介 ​ Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让 ...

  2. Spring Cloud:使用Ribbon实现负载均衡详解(下)

    在上一篇文章(Spring Cloud:使用Ribbon实现负载均衡详解(上))中,我对 Ribbon 做了一个介绍,Ribbon 可以实现直接通过服务名称对服务进行访问.这一篇文章我详细分析一下如何 ...

  3. VC++ 2010 创建高级Ribbon界面详解(1)

    运用 VC++ 2010 创建高级 Ribbon 界面详解,包括 Ribbon 界面的结构层次.Ribbon 控件的使用等,ribbon 用户界面,ribbon interface ,ribbon 高 ...

  4. (2-3)Eureka详解

    基础架构 服务注册中心 服务提供者 服务消费者 服务治理 服务提供者 服务注册.在服务注册时,需要确认一下eureka.client.registerwith-eurek=ture参数是否正确,默认是 ...

  5. Spring Cloud Zuul 限流详解(附源码)(转)

    在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选择,只需要编写一个过滤器就可以了,关键在于如何实现限流的算法. ...

  6. Zuul之Filter详解

    Zuul详解 官方文档:https://github.com/Netflix/zuul/wiki/How-it-Works Zuul的中心是一系列过滤器,能够在HTTP请求和响应的路由过程中执行一系列 ...

  7. Spring Cloud限流详解

    转自:https://blog.csdn.net/tracy38/article/details/78685707 在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud ...

  8. springcloud中Feign配置详解

    Spring Cloud中Feign配置详解 到目前为止,小伙伴们对Feign的使用已经掌握的差不多了,我们在前文也提到Feign是对Ribbon和Hystrix的整合,那么在Feign中,我们要如何 ...

  9. Spring Cloud(十二):Spring Cloud Zuul 限流详解(附源码)(转)

    前面已经介绍了很多zuul的功能,本篇继续介绍它的另一大功能.在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选 ...

随机推荐

  1. eclipse热部署web项目

    一.选中JavaEE视图 因为在普通的Java视图下,窗口下方没有server选项卡 二.双击Tomcat 注意:可能很多人当然包括我一开始的时候,都是喜欢右键Tomcat然后Add and remo ...

  2. 自定义MVC框架---第一章

    MVC基本介绍 介绍:  mvc是一种编程思想,用来解决开发项目的时候,代码如何编写,项目如何架构的问题,更具体一点就是解决多人协同开发时,如何分工协作的问题,从而提升开发效率 举一个例子:有一个人想 ...

  3. Docker基础知识整理

    Docker 1.安装2.三大组件 镜像/容器/仓库3.Docker数据管理4.构建Docker5.docker部署微服务 项目部署到Linux服务器 1.安装jdk2.安装tomcat3.将项目wa ...

  4. 想在网上保持匿名?教你用Linux如何实现!

    想在网上保持匿名?教你用Linux如何实现! 信息时代给我们的生活带来极大便利和好处的同时也带来了很大的风险.一方面,人们只要点击几下按钮,就能基本上访问已知存在的全部信息和知识:另一方面,要是这种权 ...

  5. 2017/11/25 2D变换

    2D变换 一.盒模型解析模式 1.box-sizing:盒模型解析模式 1)content-box:标准盒模型(和css2一样的计算) 宽度和高度之外绘制元素的内边距和边框 width,height外 ...

  6. Nginx+Tomcat 配置负载均衡集群

    一.Hello world 1.前期环境准备 准备两个解压版tomcat,如何同时启动两个tomcat,请看我的另一篇文章<一台机器同时启动多个tomcat>. nginx官网下载解压版n ...

  7. 理解python的元类

    看了一篇文档,借鉴一下!写下自己对python元类的理解,欢迎各位大神给出意见. 我的理解就是 type用来创建元类,元类用来创建类,类用来创建实例 这样一想,是不是可以认为元类创建类的过程等同于类创 ...

  8. java程序性能调优---------------性能概述

    一.程序的性能通过哪几个方面表现 1.执行速度(程序反应反应是否迅速.响应时间是否足够短) 2.分配内存 (分配内存是否合理,是否过多的消耗内存或者内存溢出) 3.启动时间(程序从运行到可以正常处理业 ...

  9. 多线程&定时器Timer&同步&线程通信&ThreadLocal

    1.多线程 线程状态分为:新建状态.就绪状态.运行状态.阻塞状态.死亡状态 对象等待池的阻塞状态:运行状态执行了wait方法 对向锁池的阻塞状态:试图获得某个同步锁,已经被其他线程占用,就会放到对象的 ...

  10. Object类-----java

    Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另一个类,那么这类默认继承object类 Object类中的方法,适合所有子类. 1 toString()方法在Obje ...