(转)Spring Cloud(二)
【课程23】熔断器-Hystrix.xmind0.1MB
【课程23】微服务...zuul.xmind0.2MB
在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。
如下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
- 为网络其请求设置超时时间
- 使用断路器模式
- 统计一段时间内的失败次数来决定正常访问还是直接返回
- 断路器处于半开状态,应许一个请求进入,如果请求正常,就关闭断路器。
在这种情况下就需要整个服务机构具有故障隔离的功能,避免某一个服务挂掉影响全局。
在Spring Cloud 中Hystrix组件就扮演这个角色。 一个实现了超时机制和断路器模式的工具类库。
Hystrix会在某个服务连续调用N次不响应的情况下,立即通知调用端调用失败,避免调用端持续等待而影响了整体服务。Hystrix间隔时间会再次检查此服务,如果服务恢复将继续提供服务。
Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提高系统的可用性与容错性。
Hystrix主要通过以下几点实现延迟和容错:
- 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用到了设计模式中的“命令模式”。
- 跳闸机制:当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间。
- 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。
- 监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等。
- 回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
- 自我修复:断路器打开一段时间后,会自动进入“半开”状态。断路器打开、关闭、半开的逻辑转换,上文已经详细探讨过,不再赘述。
服务降级
优先核心服务,非核心服务不可用或弱可用。
- 通过HystrixCommand注解
- fallbackMethod回退函数
- 1:Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。
- 2:可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可.当调用超时时,直接返回或执行fallback逻辑。
- 3:为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。
- 4:依赖调用结果分:成功,失败(抛出异常),超时,线程拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行fallback(降级)逻辑。
- 5:提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行。
- 6:提供近实时依赖的统计和监控
第一步:导入hystrix坐标
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
第二步、启动application添加注解@EnableHystrix启动断溶处理
@EnableHystrix
或者
@EnableCircuitBreaker
第三步、使用@HystrixCommand注解,在对应的接口上添加容灾方法
@HystrixCommand(fallbackMethod = "getUsernameFallback")
@GetMapping("/username")
public Object getUsername() {
return restTemplate.getForObject("http://EUREKA-CLIENT-2/username", String.class);
}
public Object getUsernameFallback() {
return "fall back";
}
默认提示:@HystrixCommand可以和@DefaultProperties配合使用
@hystrixCommand注解参数详解
定义一个实现类,接口端使用@FeignClient的fallback指向要回退的类。
/**
* Feign的fallback测试类
* 使用@FeignClient的fallback属性指定回退类
*/
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
public interface UserFeignClient {
@GetMapping(value = "/{id}")
User findById(@PathVariable("id") Long id);
}
/**
* 回退类FeignClientFallback需实现Feign Client接口
* FeignClientFallback也可以是public class,没有区别
*/
@Component
class FeignClientFallback implements UserFeignClient {
@Override
public User findById(Long id) {
User user = new User();
user.setId(-1L);
user.setUsername("默认用户");
return user;
}
}
同时在yml配置文件中配置:
feign:
hystrix:
enabled: true
第一步、feign接口使用fallbackFactory属性
@FeignClient(name = "eureka-client-2", fallbackFactory = Demo2ClientFallbackFactory.class)
public interface Demo2Client {
@GetMapping("/username")
public String getUsername();
}
第二步、定义fallbackFactory的实现类。重写create方法,使用Throwable cause查看回退原因。
@Component
public class Demo2ClientFallbackFactory implements FallbackFactory<Demo2Client> {
public Demo2Client create(Throwable cause) {
return new Demo2Client() {
@Override
public String getUsername() {
System.out.println(cause.toString());
return "hello world fallbackfactory";
}
};
}
}
在实际开发中,并不是所有的请求都要提前预备好服务降级问题,如果我就是要将服务调用失败的信息展示给用户,那么此时就没有必要添加断路器了。
关闭服务B端:
访问 http://localhost:8010/actuator/health,结果如下,此时Hystrix的状态依然是 UP,这是因为我们的失败率还没有达到阈值(默认是5秒返回20次失败)
断路器的状态也会暴露在Actuator提供的 /actuator/health 端口中,这样就可以直观地了解断路器的状态。
<!--actuator用于应用监控管理-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
yml配置
management:
endpoint:
health:
show-details: always
如果控制台输出:
#说明断路器已经打开
Hystrix circuit short-circuited and is OPEN
https://www.cnblogs.com/java-synchronized/p/7927726.html
- 线程隔离
- 它将在单独的线程上执行,并发请求受线程池中的线程数量的限制。
- 把执行依赖代码的线程与请求线程(如:jetty线程)分离,请求线程可以自由控制离开的时间(异步过程)。
- 通过线程池大小可以控制并发量,当线程池饱和时可以提前拒绝服务,防止依赖问题扩散。
- 线上建议线程池不要设置过大,否则大量堵塞线程有可能会拖慢服务器。
- 信号量隔离
- 它将在调用线程上执行,开销相对较小,并发请求收到信号量个数的限制。
- 信号隔离也可以用于限制并发访问,防止阻塞扩散, 与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请)
- 当n个并发请求去调用一个目标服务接口时,都要获取一个信号量才能真正去调用目标服务接口,但信号量有限,默认是10个,可以使用maxConcurrentRequests参数配置,如果并发请求数多于信号量个数,就有线程需要进入队列排队,但排队队列也有上限,默认是 5,如果排队队列也满,则必定有请求线程会走fallback流程,从而达到限流和防止雪崩的目的。
在微服务架构模式下,后端服务的实例数一般是动态的,对于客户端而言很难发现动态改变的服务实例的访问地址信息。因此在基于微服务的项目中为了简化前端的调用逻辑,通常会引入API Gateway作为轻量级网关,同时API Gateway中也会实现相关的认证逻辑从而简化内部服务之间相互调用的复杂度。
Spring Cloud体系中支持API Gateway落地的技术就是Zuul。Spring Cloud Zuul路由是微服务架构中不可或缺的一部分,提供动态路由,监控,弹性,安全等的边缘服务。Zuul是Netflix出品的一个基于JVM路由和服务端的负载均衡器。
它的具体作用就是服务转发,接收并转发所有内外部的客户端调用。使用Zuul可以作为资源的统一访问入口,同时也可以在网关做一些权限校验等类似的功能。
第一步、
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
第二步、yml配置
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
第三步、配置路由规则,链接可以不用添加应用名称。可以配置前缀调整规则
# 路由规则配置
zuul:
routes:
api-a:
path: /usernameByFeign
serviceId: eureka-client-1
第三步、application添加注解@EnableZuulProxy
启动项目之后可以看到在注册中心已经Zuul的注册了。
第一步继承网关路由。
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
- ROUTING:这种过滤器将请求路由到微服务。这种过滤器用于构建发送给微服务的请求,并使用Apache HttpClient或Netfilx Ribbon请求微服务。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器。
- 除了默认的过滤器类型,Zuul还允许我们创建自定义的过滤器类型。例如,我们可以定制一种STATIC类型的过滤器,直接在Zuul中生成响应,而不将请求转发到后端的微服务。
public class PreLogFilter extends ZuulFilter {
/**
* pre请求之前
* route用于将请求路由转到微服务
* post路由到微服务以后执行
* error在其他阶段发生错误的时候执行
* @return
*/
@Override
public String filterType() {
return "pre";
}
/**
* 执行顺序
* @return
*/
@Override
public int filterOrder() {
return 0;
}
/**
* true返回一个boolean判断该过滤器是否要执行
* @return
*/
@Override
public boolean shouldFilter() {
return true;
}
/**
* 过滤器执行具体内容
* @return
* @throws ZuulException
*/
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println("---》路由获取所有参数值" + request.getParameterMap().toString());
System.out.println(request.getHeader("cookie"));
return null;
}
}
@Bean
PreLogFilter preLogFilter() {
return new PreLogFilter();
}
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0-jre</version>
</dependency>
import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
/**
* 限流
*/
public class RateLimiterFilter extends ZuulFilter {
//guava的令牌桶算法
private static final RateLimiter RATE_LIMITER = RateLimiter.create(100);
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return -5;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run(){
if(!RATE_LIMITER.tryAcquire()) {
throw new RuntimeException("占坑失败~~");
}
System.out.println("-------->没限流");
return null;
}
}
@Bean
RateLimiterFilter rateLimiterFilter() {
return new RateLimiterFilter();
}
前置过滤器
- 限流
- 鉴权
- 参数校验
后置过滤器
- 统计
- 日志
多个zuul节点同时注册到euraka上,节点名称保持一致。与其他客户端方法一致。这时候,有多个zuul对外暴露接口,外层就可以弄个nginx搞负载均衡。
项目
文档中心
(转)Spring Cloud(二)的更多相关文章
- spring cloud(二)服务(注册)中心Eureka
Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组 ...
- Spring Cloud(二):Spring Cloud Eureka Server高可用注册服务中心的配置
前言 Eureka 作为一个云端负载均衡,本身是一个基于REST的服务,在 Spring Cloud 中用于发现和注册服务. 那么当成千上万个微服务注册到Eureka Server中的时候,Eurek ...
- spring cloud(二) zuul
spring cloud 网关 zuul 搭建过程 1. 新建boot工程 pom引入依赖 <dependency> <groupId>org.springframework. ...
- Spring Cloud(二):服务消费者
创建“服务消费者” 创建一个基础的Spring Boot工程,命名为springboot-consumer,并在pom.xml中引入需要的依赖内容: <dependency> <gr ...
- spring cloud (二) 服务提供者 EuekaClient
1 创建一个springboot项目 spring-cloud-service-a 注册到eureka服务注册中心中 项目添加依赖 <dependency> <groupId&g ...
- 从零开始学spring cloud(二) -------- 开始使用Spring Cloud实战微服务
1.准备工作 2.服务提供者与服务消费者 3.服务发现与服务注册 服务发现: 服务注册表: 服务注册表是一个记录当前可用服务实例的网络信息的数据库,是服务发现机制的核心.服务注册表提供查询API和管理 ...
- Spring Cloud(十四):Ribbon实现客户端负载均衡及其实现原理介绍
年后到现在一直很忙,都没什么时间记录东西了,其实之前工作中积累了很多知识点,一直都堆在备忘录里,只是因为近几个月经历了一些事情,没有太多的经历来写了,但是一些重要的东西,我还是希望能坚持记录下来.正好 ...
- spring boot / cloud (二) 规范响应格式以及统一异常处理
spring boot / cloud (二) 规范响应格式以及统一异常处理 前言 为什么规范响应格式? 我认为,采用预先约定好的数据格式,将返回数据(无论是正常的还是异常的)规范起来,有助于提高团队 ...
- spring cloud+dotnet core搭建微服务架构:服务发现(二)
前言 上篇文章实际上只讲了服务治理中的服务注册,服务与服务之间如何调用呢?传统的方式,服务A调用服务B,那么服务A访问的是服务B的负载均衡地址,通过负载均衡来指向到服务B的真实地址,上篇文章已经说了这 ...
- spring cloud 专题二(spring cloud 入门搭建 之 微服务搭建和注册)
一.前言 本文为spring cloud 微服务框架专题的第二篇,主要讲解如何快速搭建微服务以及如何注册. 本文理论不多,主要是傻瓜式的环境搭建,适合新手快速入门. 为了更好的懂得原理,大家可以下载& ...
随机推荐
- report源码分析——report_handle和report_server和report_catcher
report_handle主要实现对message的action,severity,file的设置,然后将message传递给server: 主要的function有两个:initial和proces ...
- 80x86的内存寻址机制
80x86的内存寻址机制 80386处理器的工作模式: 模式. 模式之间可以相互转换,而模式之间不可以相互转换. DOS系统运行于实模式下,Windows系统运行与保护模式下. 实模式: 80386处 ...
- Cacti的使用
前期准备 SNMP的安装,控制机和被控机,以及被控机的配置 1.SNMP的安装参考:http://www.cnblogs.com/smallcoderhujin/p/3785731.html 2.被控 ...
- Sitecore 8.1 - 特性和功能
营销基础 一个新的Sitecore品牌术语取代了体验营销(以前的Sitecore DMS),这是Sitecore体验数据库(xDB)现在所在的位置. Sitecore 7.5和Sitecore 8.0 ...
- 激活win10
网盘地址 http://pan.baidu.com/s/1nvc5I1V 里面是2个东西,一个是rar解压缩软件,一个是激活工具本体 一个解压缩软件,一个激活工具的压缩包 安装解压软件,就是WINRA ...
- 《nodejs开发指南》微博实例express4.x版
之前一直执着于前端开发,最近几天,开始学起了nodejs.作为一名前端开发者,见到这样一门用javascript写的后台自然是很激动的.但是,后台毕竟不同于前端,在学习的过程中,还是会遇到不少问题. ...
- flask 在模板中渲染表单
在模板中渲染表单 为了能够在模板中渲染表单,我们需要把表单类实例传入模板.首先在视图函数里实例化表单类LoginForm,然后再render_template()函数中使用关键脑子参数form将表单实 ...
- Linux基础命令---调整程序优先级renice
renice renice指令可以重新调整程序运行的优先级,可以通过进程id.用户id.组id来修改优先级.修改组的等级,影响组内所有用户的所有进程优先级:修改用户等级,影响该用户的所有进程优先级.除 ...
- linux下php中文UTF-8转换Unicode方法和注意事项
先说下遇到问题:1.php没有内置unicode_ecode函数可以直接使用 2.网上很多资料都是用$str = iconv($encoding, 'UCS-2', $str); window下转换出 ...
- 实例,C# 导出.dbf格式文件
using System; using System.Collections using System.Configuration; using System.Data; using System. ...