Spring Cloud传参数+熔断器+负载均衡
| 课程回顾
1、配置应用程序名称的属性是什么?
spring.application.name
2、feign接口使用的注解是?
@FeignClient
| 预习检查
1、什么是熔断器?
熔断器就相当于电路中的保险丝、保护器,它可以实现快速失败,如果它在某一段时间里侦测到许多类似的错误,它将不再访问远程服务器,会强迫以后的访问都会快速失败,从而防止某个服务不断地尝试执行可能会失败的操作,它会使服务继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生,从而进入回路方法。
2、什么是负载均衡?
负载均衡是由多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,都可以单独对外提供服务而无须其他服务器的辅助
| 章节目标
- 传简单参数。
- 传对象参数。
- 熔断器。
- 客户端负载均衡。
| 章节重点、难点
1)、重点
传参数、熔断器、负载均衡。
2)、难点
熔断器、负载均衡、网关配置。
| 知识点讲解
传简单参数
1、修改提供者的控制器。
上节示例中我们只是讲解了消费者调用提供者的无参方法,接下来演示带参方法。
在dm-user-provider工程中修改UserController类
package com.dm.controller;
//导包省略
@RestController
public class UserController {
//此处方法加了参数
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(@RequestParam("userName") String userName) throw Exception{
return " 提供者1 登录成功 " +userName;
}
}
2、修改消费者的feign接口
在dm-user-comsumer工程中修改UserFeignClient类
@FeignClient(name="dm-user-provider")
public interface UserFeignClient {
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(@RequestParam("userName") String userName) throw Exception;
}
3、修改消费者的控制器类
在dm-user-comsumer工程中修改UserController类
@RestController
public class UserController{
@Resource
private UserFeignClient userFeignClient;
@RequestMapping("/userLogin")
public String login(String name) throw Exception{
return "收到结果:"+userFeignClient.login(name);
}
}
4、重新启动提供者和消费者测试
访问:
http://localhost:7501/userLogin?name=aa
页面提示如下表示成功
收到结果: 提供者1 登录成功 aa
传对象参数
1、修改提供者的控制器。
上节示例中我们只是讲解了消费者调用提供者的无参方法,接下来演示带参方法。
在dm-user-provider工程中增加User类
public class User implements Serializable {
private Integer id;
private String userName;
private String password;
//get set 省略
}
在dm-user-provider工程中修改UserController类
package com.dm.controller;
//导包省略
@RestController
public class UserController {
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestBody User user) throw Exception{
return " 提供者1 登录成功 " +user;
}
}
2、修改消费者的feign接口
在dm-user-comsumer工程中增加User类
public class User implements Serializable {
private Integer id;
private String userName;
private String password;
//get set 省略
}
在dm-user-comsumer工程中修改UserFeignClient类
@FeignClient(name="dm-user-provider")
public interface UserFeignClient {
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestBody User user) throw Exception
}
3、修改消费者的控制器类
在dm-user-comsumer工程中修改UserController类
@RestController
public class UserController{
@Resource
private UserFeignClient userFeignClient;
@RequestMapping("/userLogin")
public String login(User user) throw Exception{
return "收到结果:"+userFeignClient.login(user);
}
}
4、重新启动提供者和消费者测试
访问:
http://localhost:7501/userLogin?id=1&userName=aa&password=123
页面提示如下表示成功
收到结果: 提供者1 登录成功 com.szxs.entity.User$1111
熔断器
1、为什么需要熔断器
在分布式中,我们会根据业务或功能将项目拆分为多个服务单元,各个服务单元之间通过服务注册和订阅的方式相互依赖和调用功能,随着项目和业务的不断拓展,服务单元数量也逐渐增多,相互之间的依赖关系也越来越复杂,这时候,可能会有某个服务单元出现问题或网络原因依赖调用出错或延迟,此时如果调用该依赖的请求不断增加,那么要调用该服务的服务将都会等待或者出现故障,如果后续连锁反应越来越多,Servlet容器的线程资源会被消耗完毕,导致服务瘫痪。服务与服务的依赖会导致服务之间的故障传播,从而迎来"雪崩效应"。为了解决这种每个点或多个点的故障,就有了熔断器的出现。
2、什么是熔断器
熔断器就相当于电路中的保险丝、保护器,它可以实现快速失败,如果它在某一段时间里侦测到许多类似的错误,它将不再访问远程服务器,会强迫以后的访问都会快速失败,从而防止某个服务不断地尝试执行可能会失败的操作,它会使服务继续执行而不用等待修正错误,或者浪费CPU时间去等到长时间的超时产生,从而进入回路方法。熔断器也可以使服务能够诊断错误是否已经修正,如果已经修正,服务会再次尝试调用操作。
3、修改消费者工程
修改dm-user-comsumer中的application.yml文件
feign.hystrix.enabled=true 设置启用熔断器
server:
port: 7501
spring:
application:
name: dm-user-consumer
eureka:
client:
service-url:
defaultZone: http://root:dmw@172.16.2.1:7776/eureka/
feign:
hystrix:
enabled: true
在此工程中增加一个UserFeignClientFallback类实现UserFeignClient接口
@Component
public class UserFeignClientFallback implements UserFeignClient {
@Override
public String login(User user) {
return "登录1 异常 溶断器 处理 "+user;
}
}
接下来UserFeignClient接口中配置UserFeignClientFallback的实现,如下:
@FeignClient(name="dm-user-provider",fallback=UserFeignClientFallback.class)
public interface UserFeignClient {
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestBody User user) throw Exception
}
4、重新启动提供者和消费者测试
访问:
http://localhost:7501/userLogin?id=1&userName=aa&password=123
页面提示如下表示成功
收到结果: 提供者1 登录成功 com.szxs.entity.User$1111
接下来测试熔断器是否生效,可以把提供者(dm-user-provider)停止服务。继续访问测试
http://localhost:7501/userLogin?id=1&userName=aa&password=123
页面提示如下表示熔断器生效了
收到结果: 登录1 异常 溶断器 处理 com.szxs.entity.User$1111
客户端负载均衡
1、为什么需要负载均衡
在网站创立初期,我们一般都使用单台机器对台提供集中式服务,但是随着业务量越来越大,无论是性能上还是稳定性上都有了更大的挑战。这时候我们就会想到通过扩容的方式来提供更好的服务。我们一般会把多台机器组成一个集群对外提供服务。然而,我们的网站对外提供的访问入口都是一个的,比如www.xshiedu.com。那么当用户在浏览器输入www.xshiedu.com的时候如何将用户的请求分发到集群中不同的机器上呢,这就是负载均衡在做的事情。
针对以上情况的解决方案:
(1) 服务器进行硬件升级:采用高性能服务器替换现有低性能服务器。 该方案的弊端:
高成本:高性能服务器价格昂贵,需要高额成本投入,而原有低性能服务器被闲置,造成资 源浪费。
可扩展性差:每一次业务量的提升,都将导致再一次硬件升级的高额成本投入,性能再卓越 的设备也无法满足当前业务量的发展趋势。
(2)组建服务器集群,利用负载均衡技术在服务器集群间进行业务均衡
该方案的优势: 低成本
可扩展性:当业务量增长时,系统可通过增加服务器来满足需求,且不影响已有业务,不降 低服务质量
高可靠性:单台服务器故障时,由负载均衡设备将后续业务转向其他服务器,不影响后续业 务提供,保证业务不中断。
2、负载均衡有哪些
DNS域名解析负载均衡:利用DNS处理域名解析请求的同时进行负载均衡是另一种常用的方案。
数据链路层负载均衡:在通信协议的数据链路层修改mac地址进行负载均衡。
IP负载均衡:在网络层通过修改请求目标地址进行负载均衡。
HTTP重定向负载均衡:这种负载均衡方案的优点是比较简单,缺点是浏览器需要每次请求两次服务器才能拿完成一次访问,性能较差;使用HTTP302响应码重定向,可能是搜索引擎判断为SEO作弊,降低搜索排名。
反向代理负载均衡:反向代理服务器转发请求在HTTP协议层面,因此也叫应用层负载均衡。优点是部署简单,缺点是可能成为系统的瓶颈。
Spring cloud的ribbon是客户端负载均衡
Nginx是服务器端的负载均衡
3、负载均衡算法
随机算法、轮询及加权轮询、最小连接及加权最小连接、Hash(源地址散列)、IP地址散列、URL散列等算法
4、使用Spring Cloud的负载均衡Ribbon
首先要有多个提供者,提供者的服务名要相同。在同一机器上端口号要不一样。消费者可以用一个来调用提供者。
5、创建第二个提供者
只需要复制一个提供者,把端口号改成不一样就OK(二个提供者不在同一机器可以不改)。
修改第二个工程dm-user-provider的application.yml文件如下。
server:
port: 7102 #此处是第二个提供者的yml文件,要修改此端口号
spring:
application:
name: dm-user-provider #应用名称不用改
eureka:
client:
service-url:
defaultZone: http://172.16.2.1:7776/eureka/
第二个工程dm-user-provider中修改UserController类
package com.dm.controller;
//导包省略
@RestController
public class UserController {
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestBody User user) throw Exception{
return " 提供者2 登录成功 " +user;
}
}
6、修改消费者工程
打开可以看到很多算法类
https://github.com/Netflix/ribbon/tree/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer
常见的策略有:
- RoundRobinRule(轮询模式)
- RandomRule(随机策略)
- BestAvailableRule(并发量)
- AvailabilityFilteringRule(服务器状态)
- WeightedResponseTimeRule(根据响应时间)
- RetryRule(根据策略+重试)
- ZoneAvoidanceRule(Zone状态+服务状态)
在dm-user-comsumer工程的application.yml中增加策略
server:
port: 7501
spring:
application:
name: dm-user-consumer
eureka:
client:
service-url:
defaultZone: http://root:dmw@172.16.2.1:7776/eureka/
feign:
hystrix:
enabled: true
dm-user-provider: #提供者spring.application.name值 下面使用了轮询策略
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
7、重启测试
二个提供者,一个消费者重启。
访问:
http://localhost:7501/userLogin?id=1&userName=aa&password=123
首次页面提示如下表示成功
收到结果: 提供者1 登录成功 com.szxs.entity.User$1111
再次访问页面提示如下表示成功
收到结果: 提供者2 登录成功 com.szxs.entity.User$222