java_微服务09SpringCloud常见问题之Ribbon

Eureka解决了服务如何进行注册,注册到哪里,服务消费者如何获取服务生产者的服务信息的问题,但是Eureka只是维护了服务生产者、注册中心、服务消费者三者之间的关系,真正的服务消费者调用服务生产者提供的数据是通过Spring Cloud Ribbon来实现的
服务消费者是将服务从注册中心获取服务生产者的服务列表并维护在本地的,这种客户端发现模式的方式是服务消费者选择合适的节点进行访问服务生产者提供的数据,这种选择合适节点的过程就是Spring Cloud Ribbon完成的。
Spring Cloud Ribbon客户端负载均衡器由此而来。
客户端负载均衡的特点
由客户端内部程序实现,不需要额外的负载均衡器软硬件投入。
程序内部需要解决业务服务器不可用的问题,服务器故障对应用程序的透明度小。
程序内部需要解决业务服务器压力过载的问题。

Ribbon 与 Nginx 的区别

Ribbon是客户端的负载均衡工具,而客户端负载均衡和服务端负载均衡最大的区别在于服务清单所存储的位置不同,在客户端负载均衡中,所有客户端节点下的服务端清单,需要自己从服务注册中心上获取,比如Eureka服务注册中心。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,只是这个步骤需要与服务注册中心配合完成。在Spring Cloud中,由于Spring Cloud对Ribbon做了二次封装,所以默认会创建针对Ribbon的自动化整合配置;

ribbon超时时间

1
ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1);

ribbom重试MaxAutoRetriesNextServer会带来幂等性问题,尽量慎用。

如果ribbon.OkToRetryOnAllOperations配置为true,则任何请求方法都进行重试,ribbon.OkToRetryOnAllOperations配置为false时,GET方式请求无论是连接异常还是读取异常,都会进行重试,非GET方法只有在连接异常时才会进行重试。
Ribbon重试机制默认配置如下:

1
2
3
4
5
6
#同一实例最大重试次数,不包括首次调用。默认值为0
ribbon.MaxAutoRetries = 0
#同一个服务其他实例的最大重试次数,不包括第一次调用的实例。默认值为1
ribbon.MaxAutoRetriesNextServer = 1
#是否所有操作都允许重试。默认值为false
ribbon.OkToRetryOnAllOperations = false

由于MaxAutoRetriesNextServer配置默认值为1,而我们的导入接口恰巧又是GET请求,在业务服务接口数据处理超时的情况下,所以Ribbon会自动重试一次。
涉及到数据插入/更新/删除等操作接口不应该用GET请求方式,在我们的数据导入接口中使用的是GET请求方式,所以此处是存在问题的。
像在一般的系统中,建议关闭Ribbon的重试机制,如果非得开启重试,那么系统的各个接口一定要保证接口的幂等性,否则可能会导致接口逻辑被执行多次的情况,在一些重要数据的场景带来的影响将是灾难性的。

ReadTimeout和ConnectTimeout区别

ConnectTimeout是指建立连接的时间,如果目标服务宕机或网络故障,那么响应的就是ConnectTimeout,无法连接而ReadTimeout则是连接建立后,等待目标服务返回响应的时间,譬如目标服务做了一个复杂操作导致耗时较长,那么会触发ReadTimeout。

LoadBalancer–负载均衡器的核心

LoadBalancer 的职能主要有三个:

1
2
3
维护Sever实例列表的数量(新增、更新、删除等)
维护Server实例列表的状态(状态更新)
当请求Server实例时,通过负载均衡规则IRule返回最合适的Server实例

Ribbon的懒加载

Ribbon是在第一次方法调用的时候才去初始化LoadBalancer。这样看来,第一个方法请求不仅仅包含HTTP连接和方法的响应时间,还包括了LoadBalancer的创建耗时。假如你的方法本身就比较耗时的话,而且超时时间又设置的比较短,那么很大可能这第一次http调用就会失败。其实还有很多框架也实现了类似的懒加载功能,比如Hibernate的lazy-fetch,懒加载在大部分情况下可以节省系统资源开销,但某些情况下反而导致服务响应时间被延长。
3.2 Ribbon饥饿加载配置

1
2
ribbon.eager-load.enabled=true
ribbon.eager-load.clients=ribbon-demo

ribbon.eager-load.enabled:开启Ribbon的饥饿加载模式。
ribbon.eager-load.clients:指定需要饥饿加载的服务名,若有多个则用逗号隔开。

Ribbon不依赖Eureka

当我们在 RestTemplate 上添加 @LoadBalanced 注解后,就可以用服务名称来调用接口了,当有多个服务的时候,还能做负载均衡。
这是因为 Eureka 中的服务信息已经被拉取到了客户端本地,如果我们不想和 Eureka 集成,可以通过下面的配置方法将其禁用。

1
2
# 禁用 Eureka  
ribbon.eureka.enabled=false

当我们禁用了 Eureka 之后,就不能使用服务名称去调用接口了,必须指定服务地址。
2. 配置接口地址列表
上面我们讲了可以禁用 Eureka,禁用之后就需要手动配置调用的服务地址了,配置如下:

1
2
# 禁用 Eureka 后手动配置服务地址  
ribbon-config-demo.ribbon.listOfServers=localhost:8081,localhost:8083

这个配置是针对具体服务的,前缀就是服务名称,配置完之后就可以和之前一样使用服务名称来调用接口了。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×