目录
本文环境:Java jdk 8 + Spring boot 2.1.3 + spring cloud Greenwich.SR1 + spring 5.1.5。
netflix ribbon 负载均衡
1、ribbon 与 eureka 一样都是 netflix 下的子项目,spring cloud 对它们进行了集成。
2、ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,可以轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。
3、Spring Cloud Ribbon 虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API 网关的请求转发等内容,实际上都是通过 Ribbon 实现。
4、nginx 在服务端实现负载均衡,ribbon 在客户端提供负载均衡。即客户端程序使用 ribbon 后,就会自动对多个节点微服务进行负载均衡。
5、负载均衡有好几种实现策略,常见的有:随机 (Random)、轮询 (RoundRobin)、一致性哈希(ConsistentHash)、哈希 (Hash)、加权(Weighted)。默认是轮询。官网地址:
https://github.com/Netflix/ribbon
6、使用下面的命令启动多个微服务节点,动态修改应用端口以及实例名称。
java -jar eurekaclient_food-0.0.1-SNAPSHOT.jar --server.port=9396 --eureka.instance.instance-id=changSha-food-9396
java -jar eurekaclient_food-0.0.1-SNAPSHOT.jar --server.port=9397 --eureka.instance.instance-id=changSha-food-9397
如上所示此时 Eureka 服务端可以看到微服务 EUREKA-CLIENTFOOD 下面有3个节点。
netflix Ribbon 基本使用
1、Ribbon 是客户端实现的负载均衡,也就是谁发起请求,谁自己实现负载均衡,所以 eurekaclient_cat 向 eurekaclient_food 发起请求,则应该修改 eurekaclient_cat 应用。第一步应该引入 Ribbon 组件,但是 eureka 组件默认已经依赖了 ribbon 组件,所以只要引入了 eureka 就已经引入了 ribbon。
......
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
......
2、修改 eurekaclient_cat 创建 RestTemplate 实例的代码,加上 @LoadBalanced 使 RestTemplate 具有负载均衡的能力。
/**
* @SpringBootApplication 注解自己依赖了 @Configuration 注解,所以可以直接在启动类上使用 @Bean 注解
* 当然也可以新建一个配置类(@Configuration) 专门管理需要创建的实例
* @Bean 作用就是使用 DI 往 spring 容器中传教实例,以后可以直接使用 @Resource 取值使用。
* <p>
* LoadBalanced:英文就是负载均衡的意思,@LoadBalanced 注解表示 RestTemplate 具有负载均衡的能力。
* 意味着 RestTemplate 每次发送 http 请求时,都会根据 ribbon 的负载均衡机制向微服务下的某台节点服务器发送请求
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
//RestTemplate 有3个构造器,这里使用无参构造器,底层使用 jdk 原生的 java.net 下 api 进行 http 操作
return new RestTemplate();
}
3、然后修改 RestTemplate 发起 http 请求的代码,将原来写死的 ip与端口换成微服务的名称,本文是为了演示简单,微服务名称直接写死了,实际开发中可以从配置文件中获取:
@Resource
private RestTemplate restTemplate;
//通过 id 获取猫咪信息。这里只是简单的模拟,并不是操作数据库
//请求地址:http://localhost:9394/getCatById?id=110
@GetMapping("getCatById")
public String getCatById(String id) throws IOException {
//猫咪的基本信息,这里直接设置
JsonNodeFactory nodeFactory = JsonNodeFactory.instance;
ObjectNode objectNode = nodeFactory.objectNode();
objectNode.put("id", id);
objectNode.put("color", "white");
objectNode.put("age", 0.2);
//猫咪的食谱/菜谱信息调用 eurekaclient_food 微服务进行获取。
//未使用负载均衡时的地址:http://localhost:9395/getHunanCuisine。使用负载均衡后,其中的 ip:port 必须使用微服务名称代替
//EUREKA-CLIENT-FOOD 是在注册中心注册好的微服务名称(不是节点名称),也就是微服务配置文件中使用 spring.application.name 配置的名称
String foodMenu = restTemplate.getForObject("http://EUREKA-CLIENT-FOOD/getHunanCuisine", String.class);
if (!StringUtils.isEmpty(foodMenu)) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(foodMenu);//先将 json 字符串专户 json 节点对象
objectNode.putPOJO("menu", jsonNode);//对象节点插入子节点
}
return objectNode.toString();
}
5、代码很简单,修改两处就好了,接下来访问测试:
可以看出 ribbon 默认采用的轮询的策略,即对集群的服务轮流进行访问。
注意:具有负载均衡后的 RestTemplate 请求时只能使用微服务名称,无法再直接使用 ip:port 的形式,如果应用中还需要直接使用 ip 请求,则可以再提供一个非负载均衡的 RestTemplate 实例即可,使用时根据方法名注入。
@Bean
RestTemplate restTemplateNotBalance() {
return new RestTemplate();
}
带负载均衡(@LoadBalanced)的 RestTemplate 必须使用微服务名称发起请求,不能使用 ip:port
不带负载均衡(@LoadBalanced)的 RestTemplate 不能使用微服务名称发起请求,只能使用 ip:port
更多负载均衡策略可以参考《Ribbon 负载均衡策略 与 脱离 Eureka 使用、LoadBalancerClient》
演示源码 github 地址:https://github.com/wangmaoxiong/ribbon_study
Ribbon 超时时间配置
官网:/spring-cloud-netflix/2.1.0.RELEASE/single/spring-cloud-netflix.html#_zuul_timeouts
ribbon:
ConnectTimeout: 3000 #连接超时时间
ReadTimeout: 60000 #读取超时时间
SocketTimeout: 60000 #socket 超时时间