上篇文章我们了解了springcloud 的的服务如何进行注册以及服务的调用,也就是eureka.

在实际生产环境中,我们为了保障服务的高可用,以及稳定都各种因素的考量,基本都会多实例部署。那么我们的eureka 的客户端如何来选择合适的服务提供者来进行服务调用呢,这里我们就需依赖负载均衡技术来解决。常规的负载均衡有硬件负载以及软负载,硬件负载主要是通过在服务节点之间安装专门用于负载均衡的设备,比如F5等,而软件负载主要是在服务器上安装一些具备负载均衡的模块或者软件来进行负载均衡,比如常见的nginx等。下图是架构图:

Java 负载均衡程序 springboot负载均衡_spring

下面我们来搭建具备负载均衡功能的eureka 客户端。

pom:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
 </dependency>

spring 配置文件:

Java 负载均衡程序 springboot负载均衡_spring_02

在springboot 引导类中我们加入@LoadBalanced 注解

@Bean
 @LoadBalanced
 RestTemplate restTemplate() {
 return new RestTemplate();
 }

 

服务调用代码:

Java 负载均衡程序 springboot负载均衡_负载均衡_03

 

然后我们修改服务提供者配置开启两个服务,如图:

Java 负载均衡程序 springboot负载均衡_客户端_04

然后查看eureka控制台:

 

Java 负载均衡程序 springboot负载均衡_spring_05

我们看到已经有两个helloservice服务实例。

然后我们启动我们的带ribbon的客户端。

然后在浏览器输入:http://localhost:8089/hello?name=米记小匠,

连续请求两次。然后我们观察控制台日志:

Java 负载均衡程序 springboot负载均衡_客户端_06

看到分别请求了不同的服务实例。

 

下面我们来了解下关于ribbon 的配置:

#用来开启ribbon是否启用重试机制,需要依赖spring-retry模块
spring.cloud.loadbalancer.retry.enabled=true
 #此处是ribbon 全局配置#ribbon等待响应超时时间,对标http readTimeout
 ribbon.ReadTimeout=200#ribbon 建立连接超时时间,对标http connection
 ribbon.ConnetTimeout=500#我们也可以单独对服务设置单独的超时时间,格式为 SERVICENAME.ribbon.*,如下:
HELLOSERVICE.ribbon.ConnetTimeout=2000
 HELLOSERVICE.ribbon.ReadTimeout=1000
 HELLOSERVICE.ribbon.MaxAutoRetries=3

 

在进行这些属性测试时笔者踩了一个坑,网上所有资料包括我手头的书籍资料,对ribbon 超时配置都是上面描述的,但是在我进行测试时发现配置没有生效。后来在查阅各种资料,在看到一篇http连接池的时候,突然灵光一闪,很可能是请求客户端没有采用连接池,使用了jdk 自带的URL 发起http 请求,于是又去翻看ribbon的配置属性,发现了这个属性:

{
 "name": "ribbon.http.client.enabled",
 "type": "java.lang.Boolean",
 "description": "Deprecated property to enable Ribbon RestClient.",
 "defaultValue": false
 },

默认值为false,于是我尝试设置这个属性值为ture。但是之前的版本是没有这个的。然后进行测试,发现配置生效了,配置如下:

ribbon.http.client.enabled=true。经过源码跟踪debug,也证实了我上面的猜想。

这里,做个小说明,springcloud 各版本之间的差异还是很大的,我们后续的所有讨论都基于soringcloud 的 Greenwich.SR1 版本,所以希望大家一定注意这个坑。

下面我们来做一些简单的实验,来验证ribbon的超时已经重试机制,我们修改我们之前的服务实现:

@GetMapping("hello")
public String hello(String name) throws InterruptedException {
    log.info("hello:{}-线程睡眠:{}",name);
    Thread.sleep(3000);
    return "hello"+name;
}


我们让现场等待3s,然后我们发起请求,查看控制台输出:

Java 负载均衡程序 springboot负载均衡_spring_07

我们看到一共发起了4次请求,因为我们设置了重试次数是3,所以加上第一次的请求一共是4次请求,符合预期,并且我们的超时机制也生效了,符合预期。

继续往下看日志,发现还会继续请求另外的一台机器:

 

 

Java 负载均衡程序 springboot负载均衡_Java 负载均衡程序_08

其实是这个参数在起作用:HELLOSERVICE.ribbon.MaxAutoRetriesNextServer=2

这个参数指定了尝试请求另外的服务的最大次数,所以如何配置我们的服务超时时间以及重试server 的次数需要我们结合具体的业务场景进行不同的考量决定,切勿应为重试机制的存在导致生产的事故。

本篇文章就介绍到这里,后面可能还会单独写一篇文章介绍如何自定义实现ribbon 的负载均衡策略,如有错误之处欢迎指正交流!