Ribbon实战
文章目录
Ribbon怎么读,大部分人发音都是 rui ben( 瑞本) ,他能干什么?能处理负载均衡,是SpringCloud全家桶组件的一个负载均衡组件
他是怎么实现负载均衡的?他再springcloud全家桶中充当一个什么角色?
我们先谈谈 注册中心
1.注册中心
我们都知道微服务就是不同的服务组成的应用,每个应用都注册到注册中心,不管你用什么取注册发现服务的,比如Zookeeper, Eureka ,Nacos 全都提供了服务的注册发现功能
1.1 服务注册到注册中心
注册中心能够让不同的应用取发现找到其他应用的服务信息,方便服务之间调用,比如ABC三个微服务都注册到了Zookeeper
A服务下面有三台实际机器 分别是 a1-ip:port,a2-ip:port,a3-ip:port
B服务下面有三台实际机器 分别是 b1-ip:port,b2-ip:port,b3-ip:port
C服务下面有三台实际机器 分别是 c1-ip:port,c2-ip:port,c3-ip:port
A服务想要调用B服务,就要去注册中心ZK上找服务,只有注册了服务才能找到
1.2 服务注册列表Ribbon负载均衡选取相应节点
A服务想要调用B服务,就要去注册中心ZK上找服务,然后注册中心ZK告诉A, B服务现在有3台机器实例在运行,你想调用就调用吧,但是三台中你要选取哪一台去执行响应操作,这个选取那个节点的操作就是Ribbon去实现的
- 随机选一台?这台机器到底忙不忙
- 轮训选一台,刚用过b1,现在该用b2了?b1现在是否还在处理?
- 选一个服务质量高的 ?如何衡量服务质量
如何选取多个服务列表节点的一个,这就是负载均衡策略,这个负载均衡算法计算的过程及选取结果就是Ribbon实现的
2.负载均衡方案
2.1 集中式负载均衡
集中式负载均衡就是独立的负载均衡设施,独立于应用服务外,比如webPC端,H5页面,APP页面 所有客户端请求全都路由到Nginx,通过Nginx路由转发到不同的应用内部,集中式负载均衡一般都是硬件设置
2.2 进程内聚在均衡
什么是进程?你的应用程序就是一个进程,我一台服务器部署了3台服务应用进程,每个进程内部都有自己的负载均衡逻辑,我的服务从注册中心获取当前有哪些B服务可以被调用,然后我进程自己选择一台去发起请求,Ribbon就是进程内负载均衡实现
这个时候 Ribbon是部署在用户User服务中的,
User服务A,通过A自己的进程中的Ribbon选择 订单服务1,2,3 中的一台 1 去发起调用
User服务B,通过A自己的进程中的Ribbon选择 订单服务1,2,3 中的一台 2 去发起调用
都是进程内部的负载均衡实现
3.Ribbon实践
我们既然要负载均衡,肯定要client去掉用服务的应用,而且应用至少有2个节点注册到Eureka上去供client调用,所以综上所述我们需要四个程序,通过client user用户服务去调用两个订单服务去实践一下Ribbon负载均衡
Ribbon依赖包已经在Euraka Discovery Client中,不需要单独引入
- Eureka Server eureka注册中心服务
- Client User服务 作为客户端
- 服务A 订单服务1 IP:PORT-1 作为被调用方1
- 服务A 订单服务2 IP:PORT-2 作为被调用方2
3.1 配置启动Eureka注册中心
1.新建Springboot项目, 添加组件的时候添加EurekaServer组件
2.配置项目启动类及 application.properties文件
项目启动类加上@EnableEurekaServer注解
application配置基本信息
spring.application.name=eureka-server
server.port=8761
#eureka自动保护 关闭
eureka.server.enable-self-preservation=false
eureka.instance.hostname=eureka-hostname-jzj
#不能调用自己
eureka.client.fetch-registry=false
#不自己注册自己
eureka.client.register-with-eureka=false
#这个地址就是 其他的服务 user,order需要访问注册中心的地址
# !!!!!!! 注意 这个地方 后缀结尾必须是 eureka
eureka.client.service-url.defaultZone = http://localhost:${server.port}/eureka
!!!!! 注意 这个地方 eureka.client.service-url.defaultZone =xxxx/eureka
否则就会出现 这个错误
3.2 访问eureka界面
可以看到Eureka服务正常启动,用的是单机模式, 端口8761
4.Client客户端User服务
我们这次新建一个父子项目,因为除了EurekaServer,其他的User用户服务,Order订单服务 几个都建在一个工程里,避免多个工程切换
- Eureka Server eureka注册中心服务
- Client User服务 作为客户端
- 服务A 订单服务1 IP:PORT-1 作为被调用方1
- 服务A 订单服务2 IP:PORT-2 作为被调用方2
4.1 新建父子工程
新建MAVEN项目
新建项目名字
父 src文件删除,然后修改父文件 pom的打包类型为 pom文件
4.2 构建Ribbon Client User服务
User作为Ribbon客户端发起调用,调用多个Order订单 orderOne及OrderTwo服务
新建Module user, 选择还是 Spring initlize springboot项目, 然后填写服务名字及基本信息
勾选Web 及 Eureka Discovery Client 方便调用
4.3 构建OrderOne 订单服务
新建Module 选择Spring initializr , 然后填写服务名字及基本信息
依旧选择 Web 及 Eureka Discovery Client 方便调用
4.4 同样的方法构建orderTwo 订单服务
按照orderOne的相同的方法构建orderTwo
5.配置 User,OrderOne,OrderTwo服务
配置User,orderOne, orderTwo的服务端口及properties文件及Controller信息
5.1 配置User服务
1.启动类新增注解 @EnableEurekaClient
2.application.properties 配置eureka地址及端口
user服务的服务端口是8088
server.port=8088
#user服务
spring.application.name=user-client
#eureka注册中心地址
# !!!!!!! 注意 这个地方 后缀结尾必须是 eureka 和服务端保持一致
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
3.新建UserController
@RestController
@Slf4j
public class UserController {
@GetMapping("/user")
public String test() {
log.info("client 发起UserController");
return "user";
}
}
4.启动服务,访问Controller
http://localhost:8088/user 访问正常,服务正常启动
5.Eureka看User服务是否注册
user一台已经注册到euraka端口8088
5.1 配置OrderOne服务
1.启动类新增注解 @EnableEurekaClient
2.application.properties 配置eureka地址及端口
user服务的服务端口是8089
server.port=8089
#order服务 , 注意这个地方叫 order ,就是为了 和order2 服务一样的名字都注册eureka上
spring.application.name=order
#eureka注册中心地址
# !!!!!!! 注意 这个地方 后缀结尾必须是 eureka 和服务端保持一致
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
3.新建OrderController
package com.ribbontest.orderone.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class OrderController {
@GetMapping("/order")
public String test() {
log.info("orderOne 发起 请求");
return "orderOne";
}
}
4.启动服务,访问Controller
http://localhost:8089/order访问正常,服务正常启动,返回orderOne
5.Eureka看OrderOne服务是否注册
Order 服务 1台已经注册到Eureka 端口 8089
5.2 配置OrderTwo服务
1.启动类新增注解 @EnableEurekaClient
2.application.properties 配置eureka地址及端口
user服务的服务端口是8090
server.port=8090
#order服务 , 注意这个地方叫 order ,就是为了 和order1 服务一样的名字都注册eureka上,然后去负载均衡
spring.application.name=order
#eureka注册中心地址
# !!!!!!! 注意 这个地方 后缀结尾必须是 eureka 和服务端保持一致
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka
3.新建OrderController
package com.ribbontest.ordertwo.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class OrderController {
@GetMapping("/order")
public String test() {
log.info("orderTwo 发起 请求");
return "orderTwo";
}
}
4.启动服务,访问Controller
http://localhost:8089/order访问正常,服务正常启动,返回orderTwo
5.Eureka看OrderTwo服务是否注册
Order 服务 2台已经注册到Eureka 端口 8089 / 8090
到这里 集群搭建完成了 , 下面开始验证Ribbon
!!!!!!
6.验证Ribbon负载均衡
我们现在开始用User服务去调用Order服务, 我们直接通过Controller调用 LoadBalancerClient 接口来测试, Ribbon默认是轮询策略
LoadBalancerClient 这个就是Ribbon功能的工具client, 去调用Eureka服务列表去负载均衡获取一个节点信息
改造UserController
package com.ribbon.user.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class UserController {
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/user")
public String test() {
log.info("client 发起UserController");
return "user";
}
@GetMapping("/client")
public String client() {
//通过Ribbon client 去实现负载均衡算法,获取URL信息
log.info("client 开始调用");
//我们选择的是eureka 上的 order 应用服务,因为我们直到 order有两个
ServiceInstance order = loadBalancerClient.choose("order");
log.info("Uri:{}", order.getUri());
log.info("Host:{}", order.getHost());
log.info("Port:{}", order.getPort());
log.info("InstanceId:{}", order.getInstanceId());
log.info("Metadata:{}", order.getMetadata());
log.info("ServiceId:{}", order.getServiceId());
log.info("Scheme:{}", order.getScheme());
log.info("==================================================");
return "user";
}
}
访问 地址 http://localhost:8088/client 看下打印结果
既然Ribbon能够轮询的获取每个Order的信息,我们就能用HTTP协议访问到当前的节点,就能实现调用
日志信息
2022-05-14 20:40:16.504 INFO [nio-8088-exec-1] UserController : client 开始调用
2022-05-14 20:40:16.569 INFO [nio-8088-exec-1] UserController : Uri:http://DESKTOP-TA8GFQL:8090
2022-05-14 20:40:16.569 INFO [nio-8088-exec-1] UserController : Host:DESKTOP-TA8GFQL
2022-05-14 20:40:16.570 INFO [nio-8088-exec-1] UserController : Port:8090
2022-05-14 20:40:16.570 INFO [nio-8088-exec-1] UserController : InstanceId:DESKTOP-TA8GFQL:order:8090
2022-05-14 20:40:16.570 INFO [nio-8088-exec-1] UserController : Metadata:{management.port=8090}
2022-05-14 20:40:16.570 INFO [nio-8088-exec-1] UserController : ServiceId:ORDER
2022-05-14 20:40:16.570 INFO [nio-8088-exec-1] UserController : Scheme:http
2022-05-14 20:40:16.570 INFO [nio-8088-exec-1] UserController : ==================================================
2022-05-14 20:40:23.820 INFO [nio-8088-exec-4] UserController : client 开始调用
2022-05-14 20:40:23.821 INFO [nio-8088-exec-4] UserController : Uri:http://DESKTOP-TA8GFQL:8089
2022-05-14 20:40:23.821 INFO [nio-8088-exec-4] UserController : Host:DESKTOP-TA8GFQL
2022-05-14 20:40:23.822 INFO [nio-8088-exec-4] UserController : Port:8089
2022-05-14 20:40:23.822 INFO [nio-8088-exec-4] UserController : InstanceId:DESKTOP-TA8GFQL:order:8089
2022-05-14 20:40:23.822 INFO [nio-8088-exec-4] UserController : Metadata:{management.port=8089}
2022-05-14 20:40:23.822 INFO [nio-8088-exec-4] UserController : ServiceId:ORDER
2022-05-14 20:40:23.822 INFO [nio-8088-exec-4] UserController : Scheme:http
2022-05-14 20:40:23.822 INFO [nio-8088-exec-4] UserController : ==================================================
2022-05-14 20:40:26.409 INFO [nio-8088-exec-6] UserController : client 开始调用
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : Uri:http://DESKTOP-TA8GFQL:8090
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : Host:DESKTOP-TA8GFQL
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : Port:8090
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : InstanceId:DESKTOP-TA8GFQL:order:8090
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : Metadata:{management.port=8090}
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : ServiceId:ORDER
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : Scheme:http
2022-05-14 20:40:26.410 INFO [nio-8088-exec-6] UserController : ==================================================
2022-05-14 20:40:29.007 INFO [nio-8088-exec-7] UserController : client 开始调用
2022-05-14 20:40:29.007 INFO [nio-8088-exec-7] UserController : Uri:http://DESKTOP-TA8GFQL:8089
2022-05-14 20:40:29.007 INFO [nio-8088-exec-7] UserController : Host:DESKTOP-TA8GFQL
2022-05-14 20:40:29.007 INFO [nio-8088-exec-7] UserController : Port:8089
2022-05-14 20:40:29.008 INFO [nio-8088-exec-7] UserController : InstanceId:DESKTOP-TA8GFQL:order:8089
2022-05-14 20:40:29.008 INFO [nio-8088-exec-7] UserController : Metadata:{management.port=8089}
2022-05-14 20:40:29.008 INFO [nio-8088-exec-7] UserController : ServiceId:ORDER
2022-05-14 20:40:29.008 INFO [nio-8088-exec-7] UserController : Scheme:http
至此我们已经简单的可以使用Ribbon了,下一篇我们开始讲讲 Ribbon有哪些 负载均衡策略,怎么使用调整这些策略