翻译文章:https://www.jianshu.com/p/df9393755a05
参考文章:https://www.cnblogs.com/noneplus/p/11374968.html
代码:https://github.com/tanghh0410/eureka-ribbon.git
前言:
上篇文章我们学了如何搭建Eureka 服务注册中心,这节我们结合Ribbo 来实现客户端负载均衡。本文按照上面的翻译文章所写。
首先我们需要了解一下什么是Ribbon?
Ribbon 是Netflix 发布的负载均衡器,有助于控制HTTP和TCP 客户端的行为。
Ribbon为我们提供了负载均衡的算法,例如轮询 随机 也可以自定义负载均衡的算法,和Eureka Server一起使用的时候,可以自动获取Eureka Server 的服务者所提供的地址。
(1)接上篇文章我们搭建好Eureka 服务和消费者之后,整个代码结构如下:
(2)在我们的consumer-hello中(服务消费方)的pom中引入依赖文件
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
(3)修改服务消费者中的启动类
3.1 @EnableDiscoveryClient 说是这是当前的一个Eureka的客户端。
3.2 @LoadBalanced 注解 ,该注解就是让RestTemplate启动客户端负载均衡。
其中RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法
/***
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.twostepsfromjava.cloud.consumer.hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.web.client.RestTemplate;
/**
* TwoStepsFromJava Cloud -- Hello Consumer
*
* @author CD826(CD826Dong@gmail.com)
* @since 1.0.0
*/
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
@Bean(value = "restTemplate")
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
@Primary
@Bean(value = "lbcRestTemplate")
RestTemplate lbcRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
(4)启动Eureka 服务器
因为这边开启了权限验证,需要输入用户名和密码 root root
(5)启动多个服务提供者(Service-Hello)
启动俩个服务 端口分别是2100 和2200.
接下来通过maven将项目打开jar 包。
接下来就可以有俩个服务提供者进来了。
(6)启动服务消费者 consumer-hello
在浏览器上访问 localhost:8088/hello ,可以看到在交互访问,也就是说此时consumer-hello 这个项目 在交替访问 server-hello的2100 和2200 端口。
(7)
除了使用上文我们提到的使用@LoadBalanced 实现负载均衡以外,还可以调用Ribbon的API.
如下:
在我们的consumer-hello 的项目中写一个测试控制层 HelloController,其中 helloEx
我们在浏览器上访问一下 localhost:8088/helloEx
/***
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.twostepsfromjava.cloud.consumer.hello.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.net.URI;
/**
* Hello Controller
*
* @author CD826(CD826Dong@gmail.com)
* @since 1.0.0
*/
@RestController
public class HelloController {
protected Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired
@Qualifier(value = "restTemplate")
private RestTemplate restTemplate;
@Autowired
@Qualifier(value = "lbcRestTemplate")
private RestTemplate lbcRestTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return restTemplate.getForEntity("http://SERVICE-HELLO/hello", String.class).getBody();
}
@RequestMapping(value = "/helloEx", method = RequestMethod.GET)
public String helloEx() {
ServiceInstance instance = this.loadBalancerClient.choose("SERVICE-HELLO");
URI helloUri = URI.create(String.format("http://%s:%s/hello", instance.getHost(), instance.getPort()));
logger.info("Target service uri = {}. ", helloUri.toString());
return this.lbcRestTemplate.getForEntity(helloUri, String.class).getBody();
}
}
(8)总结 Ribbon的负载均衡策略
我们可以通过继承ClientConfigEnabledRoundRobinRule
,来实现自己负载均衡策略。
- RoundRobinRule: 轮询策略,Ribbon以轮询的方式选择服务器,这个是默认值。所以示例中所启动的两个服务会被循环访问;
- RandomRule: 随机选择,也就是说Ribbon会随机从服务器列表中选择一个进行访问;
- BestAvailableRule: 最大可用策略,即先过滤出故障服务器后,选择一个当前并发请求数最小的;
- WeightedResponseTimeRule: 带有加权的轮询策略,对各个服务器响应时间进行加权处理,然后在采用轮询的方式来获取相应的服务器;
- AvailabilityFilteringRule: 可用过滤策略,先过滤出故障的或并发请求大于阈值一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个;
- ZoneAvoidanceRule: 区域感知策略,先使用主过滤条件(区域负载器,选择最优区域)对所有实例过滤并返回过滤后的实例清单,依次使用次过滤条件列表中的过滤条件对主过滤条件的结果进行过滤,判断最小过滤数(默认1)和最小过滤百分比(默认0),最后对满足条件的服务器则使用RoundRobinRule(轮询方式)选择一个服务器实例。
Ribbon的工作原理:
- Ribbon首先根据其所在Zone优先选择一个负载较少的Eureka Server;
- 定期从Eureka Server更新并过滤服务实例列表;
- 根据指定的负载均衡策略,从可用的服务器列表中选择一个服务实例的地址;
- 然后通过RestClient进行服务调用