在上一篇文章中,限于篇幅,并没有对服务消费进行展开讲解,希望通过这篇文章,让大家能对基于Ribbon的服务消费有所认识。废话不都说,我们直接上实例。
老规矩,依然在父工程下先创建消费者项目,其中,添加的依赖与配置文件具体如下:
pom.xml
<!-- 项目依赖 -->
<dependencies>
<!-- netflix eureka client 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- spring boot web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- lombok 依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- spring boot test 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
复制代码
application.yml
spring:
application:
name: service-consumer
server:
port: 7003
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://localhost:7000/eureka/
复制代码
限于篇幅的关系,具体的测试用 service,controll,pojo 类等不再详述,大家可以自行创建或者查看我的github地址,代码都有上传。
对于基于Ribbon的服务消费,主要有两种实现方式:
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient; // Ribbon 负载均衡器
/**
* 根据主键查询订单
*
* @param id
* @return
*/
@Override
public Order selectOrderById(Integer id) {
return new Order(id, "123456", "中国",
selectProductList());
}
private List<Product> selectProductList() {
StringBuffer sb = null;
// 根据服务名称获取服务
ServiceInstance si = loadBalancerClient.choose("eureka-provider");
if (null == si) {
return null;
}
sb = new StringBuffer();
sb.append("http://" + si.getHost() + ":" + si.getPort() + "/product/list");
// ResponseEntity: 封装了返回数据
ResponseEntity<List<Product>> response = restTemplate.exchange(
sb.toString(),
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<Product>>() {});
return response.getBody();
}
复制代码
启动类注入 RestTemplate 时添加 @LoadBalanced 负载均衡注解即可
@SpringBootApplication
@EnableEurekaClient
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
@Bean
@LoadBalanced // 负载均衡注解
//Spring Boot 不提供任何自动配置的RestTemplate bean,所以需要在启动类中注入 RestTemplate
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
复制代码
具体的业务实现
@Autowired
private RestTemplate restTemplate;
/**
* 根据主键查询订单
*
* @param id
* @return
*/
@Override
public Order selectOrderById(Integer id) {
return new Order(id, "123456", "中国",
selectProductListByLoadBalancerAnnotation());
}
private List<Product> selectProductListByLoadBalancerAnnotation() {
// ResponseEntity: 封装了返回数据
ResponseEntity<List<Product>> response = restTemplate.exchange(
"http://eureka-provider/product/list",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<Product>>() {});
return response.getBody();
}
复制代码
访问 http://localhost:7003/order/1
相信通过上面的案例,我们已经对Ribbon有了一个感性的认识,它的确起到了服务消费的作用。那么,Ribbon具体是什么呢?
Ribbon 是一个基于 HTTP 和 TCP 的 客服端负载均衡工具,它是基于 Netflix Ribbon 实现的。
它不像 Spring Cloud 服务注册中心、配置中心、API 网关那样独立部署,但是它几乎存在于每个 Spring Cloud 微服务中。包括 Feign 提供的声明式服务调用也是基于该 Ribbon 实现的。
Ribbon 默认提供很多种负载均衡算法,例如轮询、随机等等。甚至包含自定义的负载均衡算法。
**Ribbon 提供了一套微服务的负载均衡解决方案。**其具体的负载均衡策略主要有以下一些:
策略对应类名: RoundRobinRule
实现原理:轮询策略表示每次都顺序取下一个 provider,比如一共有 3 个 provider,第 1 次取第 1 个,第 2 次取第 2 个,以此类推。
策略对应类名: WeightedResponseTimeRule
实现原理:
策略对应类名: RandomRule
实现原理:从 provider 列表中随机选择一个。
策略对应类名: BestAvailableRule
实现原理:选择正在请求中的并发数最小的 provider,除非这个 provider 在熔断中。
策略对应类名: RetryRule
实现原理:其实就是轮询策略的增强版,轮询策略服务不可用时不做处理,重试策略服务不可用时会重新尝试集群中的其他节点。
此外,如果查看其源码,会发现 这些策略都是实现接口 IRule 的,如果有需要,我们也可以自己实现 IRULE 接口,实现我们自定义的负载均衡策略。
为了观察负载均衡的表现,我们将服务提供者复制一份出来,修改端口即可。同时。在消费者调用时,将其选择的服务提供者的地址打印在控制台,方便观察。
此时,可以看到已经有了两个服务提供者,端口号分别为7002,7004
多次访问 http://localhost:7003/order/1
可以看到,Ribbon默认策略的确是轮询。
那么,如何根据自己的需要进行更改呢?也很简单,注入对应的负载均衡策略对象即可,其中,即可对全局进行设置,也可对局部进行设置。
在启动类或配置类中注入即可,以随机策略为例
@Configuration
public class Config {
@Bean
public RandomRule randomRule() {
return new RandomRule();
}
}
复制代码
此时,多次访问 http://localhost:7003/order/1 ,结果如下
修改配置文件指定服务的负载均衡策略。格式: 服务应用名.ribbon.NFLoadBalancerRuleClassName
# 负载均衡策略
# service-provider 为调用的服务的名称
service-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
复制代码
相关代码已提交至 github仓库 ,有兴趣的朋友可以自行对比查看