以上的服务提供者,我们都是拿到服务提供者的url后访问,正常情况下,生产环境的服务提供者不止一个,如果有多个,服务消费者怎么去访问服务提供者呢?
这就是Ribbon,他为客户端提供负载均衡
3.1. 新创建一个项目futurecloud-ribbon
由于Eureka内部已经内嵌有Ribbon,所以,不需要添加依赖,如果要添加,就加入以下依赖
<!--添加ribbon依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
3.2. 在futurecloud-ribbon的主类上启动Ribbon,使用注解@RibbonClient并指定某个服务进行负载均衡
@SpringBootApplication
@EnableEurekaClient
@RibbonClient("FUTURECLOUD-USER") //启动ribbon ,并对FUTURECLOUD-USER进行负载均衡
public class FuturecloudRibbonApplication
{
@Bean //相当于xml中的bean标签,主要是用于调用当前方法获取到指定对象
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main( String[] args )
{
SpringApplication.run(FuturecloudRibbonApplication.class,args);
}
}
3.3. 在调用服务提供者时,直接使用服务实例名指定路径
@GetMapping("/order/{id}")
public User getOrder(@PathVariable Long id){
//futurecloud-user 是spring 应用别名,配置在application.yml中
//InstanceInfo instance = eurekaClient.getNextServerFromEureka("FUTURECLOUD-USER", false);
//url = instance.getHomePageUrl();
//访问提供者,获取数据
//通过防伪rest,获取到Json数据,然后转换成User对象
User user = restTemplate.getForObject("http://FUTURECLOUD-USER/user/" + id,User.class);
return user;
}
注意,使用Ribbon作为负载均衡时,RestTemplate的获取需要添加注解@LoadBalanced
3.4. Ribbon 负载均衡算法
负载均衡一般的算法有:
1 | 轮询(Round Robin)法 |
---|---|
2 | 随机法 |
3 | 源地址哈希法 |
4 | 加权轮询(Weight Round Robin)法 |
5 | 加权随机(Weight Random)法 |
6 | 最小连接数法 |
Ribbon 默认使用的是轮询法,可通过接口LoadBalancerClient中的方法获取服务实例ServiceInstance,通过ServiceInstance就能获取到调用的服务信息
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/ribbon/arithmetic")
public String TestRibbonArithmetic(){
//查找对应服务的实例,会通过负载均衡
ServiceInstance choose = loadBalancerClient.choose("FUTURECLOUD-USER");
return choose.getServiceId() + choose.getHost()+ choose.getPort();
}
3.5. 自定义Ribbon负载均衡算法-使用Class类文件
自定义的负载均衡算法,不能放在与主函数类同级或以下包里面,必须放在主函数类包以上,保证主函数启动的时候不能扫描到此类。
在主函数中,修改RibbonClient注解,由@RibbonClient(“FUTURECLOUD-USER”) 修改为以下:
@RibbonClient(name = "FUTURECLOUD-USER",configuration = FuturecloudRibbonArithmeticConfig.class)
FuturecloudRibbonArithmeticConfig是在主函数包外自定义的Ribbon算法配置文件,
configuration默认使用的配置文件是RibbonClientConfiguration,我们只需要重写RibbonClientConfiguration类中的方法
public IRule ribbonRule(IClientConfig config) 就好。
自定义Ribbon算法的配置文件如下:
@Configuration
public class FuturecloudRibbonArithmeticConfig {
@Autowired
IClientConfig config;
/**
* 创建负载均衡算法的方法
*/
@Bean
public IRule ribbonRule(IClientConfig config) {
return new RandomRule(); //返回随机算法
}
}
3.6. 不同的服务使用不同的负载均衡算法
通过自定义负载均衡算法,我们可以让不同的服务使用不同的负载均衡算法
根据注解
@RibbonClient(name = "FUTURECLOUD-USER",configuration = FuturecloudRibbonArithmeticConfig.class)
name 指定不同的服务,configuration指定不同的算法。
3.7.自定义Class文件的配置文件位置
以上对Ribbon算法的Class配置文件,不能放啊主函数同级以及以下的包里面,如果我们非要放呢?
我们可以使用扫描排除方法,当Springboot 启动的时候,我们可以按一定规则配置,排除扫描Class的配置文件。
- 创建一个新项目,futurecloud-ribbon-componentscan
- 定义一个注解RibbonConfig,这个注解里面什么都不写,
public @interface ExcludeComponentScan {
}
- 将此注解配置在Ribbon的Class配置类里面,如下:
@Configuration
@ExcludeComponentScan
public class FuturecloudRibbonArithmeticConfig {
@Autowired
IClientConfig config;
/**
* 创建负载均衡算法的方法
*/
@Bean
public IRule ribbonRule(IClientConfig config) {
return new RandomRule(); //返回随机算法
}
}
- 在主函数里面添加ComponentScan的注解,将添加了ExcludeComponentScan注解的Class文件排除掉
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "FUTURECLOUD-USER",configuration = FuturecloudRibbonArithmeticConfig.class) //启动ribbon ,并对FUTURECLOUD-USER进行负载均衡
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,value = ExcludeComponentScan.class)})
public class FuturecloudRibbonApplication
{
@Bean //相当于xml中的bean标签,主要是用于调用当前方法获取到指定对象
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main( String[] args )
{
SpringApplication.run(FuturecloudRibbonApplication.class,args);
}
}
3.8. 自定义Ribbon负载均衡算法-使用配置文件
只需要在application.yml中添加配置文件,指定某个服务的Ribbon的算法
FUTURECLOUD-USER: #写服务的名字
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 给指定的服务配置负载均衡算法
3.9. 前面我们提到过,Eureka内置得有Ribbon,如果我们不用Eureka中的Ribbon,我们可以禁止掉,
同样的,在applicaiton.yml中添加配置,将Eureka中的Ribbon禁止掉
ribbon:
eureka:
enabled: false #在Eureka中禁用ribbon,禁用后需要自己负载均衡
3.10 Eureka Server 的高可用
在前面,我们的服务提供者做了负载均衡,当一个服务提供者崩溃后,另一个提供者继续提供服务,
但是,当Eureka 本身崩溃呢?所以,我们很有必要做Eureka Server的高可用
3.10.1. Eureka Server 高可用的原理
Eureka 的高可用原理很简单,就是让Eureka相互之间注册,一个Eureka相对于另一个Eureka是的客户端。
Eureka Server在设计的时候就考虑了高可用设计,在Eureka服务治理设计中,所有节点既是服务的提供方,也是服务的消费方,服务注册中心也不例外。
Eureka Server的高可用实际上就是将自己做为服务向其他服务注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用的效果。
3.10.2. 构建服务注册中心集群
Eureka Server的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。
可以采用两两注册的方式实现集群中节点完全对等的效果,实现最高可用性集群,任何一台注册中心故障都不会影响服务的注册与发现
牵涉到的两个主要配置是:
eureka:
client:
register-with-eureka: true #是否向服务注册中心注册自己
fetch-registry: true #是否检索服务
service-url:
defauleZone: http://user:123@localhost:10000/eureka
2、创建一个项目 eureka 项目futurecloud-service-ha
3、配置三个yml配置文件:application-peer1.yml、application-peer2.yml、application-peer3.yml
application-peer1.yml
server:
port: 10001
spring:
profiles:
active: peer1
application:
name: futurecloud-service-ha
eureka:
instance:
hostname: peer1
client:
register-with-eureka: true #是否向服务注册中心注册自己
fetch-registry: true #是否检索服务
service-url:
defauleZone: http://peer2:10002/eureka,http://peer3:10003/eureka
application-peer2.yml
server:
port: 10002
spring:
profiles:
active: peer2
application:
name: futurecloud-service-ha
eureka:
instance:
hostname: peer2
client:
register-with-eureka: true #是否向服务注册中心注册自己
fetch-registry: true #是否检索服务
service-url:
defauleZone: http://peer1:10001/eureka,http://peer3:10003/eureka
application-peer3.yml
server:
port: 10003
spring:
profiles:
active: peer3
application:
name: futurecloud-service-ha
eureka:
instance:
hostname: peer3
client:
register-with-eureka: true #是否向服务注册中心注册自己
fetch-registry: true #是否检索服务
service-url:
defauleZone: http://peer1:10001/eureka,http://@peer3:10003/eureka
4、配置hosts
127.0.0.1 peer1 peer2 peer3
运行 http://localhost:10001/eureka http://localhost:10001/eureka http://localhost:10001/eureka
正常情况下,每个eureka 服务器上都有peer1、peer2、peer3 实例
问题:实验没有成功,
1、首先是加入eureka的安全验证,配置用户名密码,使用curl风格配置了地址,访问浏览器后,重复出现登录界面,输入用户名密码,点击登录后,又跳出登录界面
2、后来将eureka的安全验证去掉后,能登录进去,但是eureka之间没有注册上去。