负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA (高用)。
有的时候可能请求量过大,后端一个服务器不足以支持程序运行,在后端放置多个服务
请求在访问这些服务的时候进行选择,根据规则找到和是的服务,进行使用。从而提升了整体的效率
ribbon是什么SpringCloudRibbon是居于NetFlixRibbon实现的一套客户端负载均衡工具
主要功能是提供客户端的软件负载均衡
ribbon的客户端提供一系列完整的配置项(连接超时)(重试)等
在配置文件中列出LoadBalancer(简称LB:负载均衡)
后面所有的及其,Ribbon会自动地帮助你基于某种规则,去连接这些及其。我们也容易使用Ribbon实现自定义地负载均衡算法
LB,及负载均衡(LoadBalaancer)
常见的负载均衡软件有 Nginx、Lvs 等等。
Dubbo、SpringCloud 中均给我们提供了负载均衡,SpringCloud 的负载均衡算法可以自定义。
负载均衡简单分类: 集中式LB即在服务的提供方和消费方之间使用独立的LB设施,如Nginx(反向代理服务器),由该设施负责把访问请求通过某种策略转发至服务的提供方!
进程式 LB将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器。
Ribbon 就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址!
Lvs介绍
LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。
Ribbon的架构 Ribbon在工作时分成两步- 第一步先选择 EurekaServer ,它优先选择在同一个区域内负载较少的server.
- 第二步再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址。
- 其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权。
刚刚在使用Ribbon时候发现一个错误
启动Eureka配置好的客户端报错:com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server报错位置出现在服务的提供者和消费者中
客户端报错:三个原因
一个可能是服务端没有跑起来
二可能defaultZone: 配置的URL有问题
三可能是服务端的端口被占用
这里我们的Eureka服务端的defaultZone:与提供者和消费者的defaultZone:不一致,导致的问题
具体操作 引入依赖
org.springframework.cloud
spring-cloud-starter-ribbon
但是发现很多的start中自带了Ribbon
我们在注册中心,通过Module2调用Module1的时候就已经使用了Ribbon
主启动使用依赖之后,在加载RestTemplate组件的时候进行使用注解 @LoadBalanced
@SpringBootApplication
@EnableDiscoveryClient //很多注册中心的启动注解
public class consummerconsul {
public static void main(String[] args) {
SpringApplication.run(consummerconsul.class,args);
}
@Bean
@LoadBalanced
// 注意使用RestTemplate进行注解中心必须要@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
服务提供者
因为服务提供者中使用Ribbon来处理负载均衡
服务消费者通过Eureka获取服务提供者时候如果只有一个服务提供者,也就没必要进行负载均衡。所以服务提供者要设置多个
这多个服务提供者只要服务的名称一致即可
并且存在相同的Restfull请求方法即可
#为微服务取名字
spring:
application:
name: provider
通过Eureka的注册中心进行观察
发现提供者确实存在两个,消费者在进行选择的时候,通过Ribbon的负载均衡规则进行选择
观察结果
因为Ribbon默认使用轮询规则,所以消费者的调用会进行循环的切换提供者,这样产生的结果
负载均衡规则 Ribbon的IRULE组件 替换Irule规则官方文档明确给出了警告:
这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,
否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,达不到特殊化定制的目的了。
- 因为不能被@ComponentScan扫描到所以新建一个文件夹
- 使用配置类的形式进行传入一个Irule类
- 在主启动类上进行@Ribbonclient指定配置类
首先使用Rundashboard进行copy服务提供者
在脱离@ComponentScan中添加一个配置类
@Configuration
public class RibbonIrule {
@Bean
public IRule rule(){
// 这里重新指定规则
return new RandomRule();
}
}
查看主程序类
@SpringBootApplication
@EnableDiscoveryClient
//指定服务提供者名,在指定设定的规则
@RibbonClient(name = "provider",configuration= RibbonIrule.class)
public class consummerconsul {
public static void main(String[] args) {
SpringApplication.run(consummerconsul.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
根据测试确实服务名为provider的调用改变了规则
脱离范围的配置类为了不把所有的提供者统一规则
负载均衡算法 想要自己写一个IRule规则-
根据Irule接口的抽象类
-
自定义类实现Irule抽象类,重写方法即可
-
在此方法中,存在通过注册中心获取服务的信息(服务个数)(服务对应的准确IP和端口)等在这些服务中进行比较和选择
官网解释:
https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/#spring-cloud-openfeign
Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。
它的使用方法是定义一个服务接口然后在上面添加注解。Feign也支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡
Feign旨在使编写Java Http客户端变得更容易。
前面在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模版化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上面标注一个Feign注解即可),即可完成对服务提供方的接口绑定,简化了使用Spring cloud Ribbon时,自动封装服务调用客户端的开发量。
Feign集成了Ribbon
利用Ribbon维护了Payment的服务列表信息,并且通过轮询实现了客户端的负载均衡。而与Ribbon不同的是,通过feign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
org.springframework.cloud spring-cloud-starter-feign
OpenFeign是Spring Cloud 在Feign的基础上支持了SpringMVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
openfeign的使用 导入依赖org.springframework.cloud spring-cloud-starter-openfeign
编写接口org.springframework.cloud spring-cloud-starter-openfeign
这个部分通过@FeignClient指定服务的名称
在使用SpringMVC的注解进行整合服务的控制器类方法。
@Component
@FeignClient("provider")
public interface feignProvider {
@RequestMapping("/consul/pro")
public String consulWp();
}
主程序类
开启openfeign
@SpringBootApplication
@EnableDiscoveryClient
//指定服务提供者名,在指定设定的规则
@RibbonClient(name = "provider",configuration= RibbonIrule.class)
@EnableFeignClients
public class consummerconsul {
public static void main(String[] args) {
SpringApplication.run(consummerconsul.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
消费者通过feign进行操作
@RestController
public class ConsummerWeb {
// 使用restTemplate进行消费者调用提供者
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consummconsul")
public String consummershow(){
System.out.println("sss");
String forObject = restTemplate.getForObject("http://provider/consul/pro", String.class);
System.out.println(forObject);
return "success"+forObject;
}
// 下面是通过feign进行的操作
// 引入feign接口,因为在feign接口中就已经调用了服务提供者
@Autowired
private feignProvider feignProvider;
// 像正常调用代码一样调用Service层
@RequestMapping("/feignConsumm")
public String consummershow01(){
String s = feignProvider.consulWp();
return "success"+s;
}
}
最后结果
两种方式都可以进行正常使用,feign的使用更加方便
超时控制openfeign在调用服务提供者的时候,默认服务提供者的时间是1秒钟,如果超过出出现timeout异常
在提供者中进行延迟控制
看到通过OpenFeign的调用是出现了异常
指定超时时间如何指定超时时间呢,我们可以在yaml中进行配置
注意这里的指定时间是来自于消费者调用提供者的提供者相关时间
#设置feign客户端超时时间(OpenFeign默认支持ribbon) ribbon: #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间 ReadTimeout: 5000 #指的是建立连接后从服务器读取到可用资源所用的时间 ConnectTimeout: 5000
查看结果,成功
Feign的日志Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节。
说白了就是对Feign接口的调用情况进行监控和输出
NONE:默认的,不显示任何日志;
BASIC:仅记录请求方法、URL、响应状态码及执行时间;
HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。
操作 通过配置类来@Bean来指定Feign的日志级别@Configuration
public class FeignConfig
{
@Bean
Logger.Level feignLoggerLevel()
{
return Logger.Level.FULL;
}
}
yaml中开启
logging:
level:
# feign日志以什么级别监控哪个接口
这里指定Feign的接口 : debug
logging:
level:
# feign日志以什么级别监控哪个接口
cn.service.feignProvider: debug
最终结果



