Feign雪崩处理、Hystrix Dashboard简介与实现、Zuul简介、Zuul作为路由、Zuul作为网关过滤器

Feign的雪崩处理

在声明式远程服务调用Feign中,实现服务灾难性性雪崩效应处理也是通过Hystrix实现的

1. 降级实现

  1. 引入依赖:
    Feign启动器(spring-cloud-starter-openfeign)中是包含Hystrix相关依赖的,如果只是使用服务降级功能,则不需要引入独立依赖;如果需要使用Hystrix其他服务容错能力,则需要依赖spring-cloud-starter-netflix-hystrix依赖
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
  2. 配置参数:
    A、B、C版本默认开启Hystrix,之后版本默认关闭
    # 开启Hystrix
    feign.hystrix.enabled=true
    
    # 访问错误时是否调用fallback方法逻辑,默认为true
    hystrix.command.default.fallback.enabled=true
    
    # 开启熔断机制,默认开启
    hystrix.command.default.circuitBreaker.enabled=true
    
    # 多少错误请求数开启断路由 默认20
    hystrix.command.default.circuitBreaker.requestVolumeThreshold=20
    
    # 断路由开启后的睡眠时间窗,多少毫秒内不再访问服务 默认5000ms
    hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000
    
    # 时间窗内,错误请求百分比达到多少开启断路由 默认50%
    hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
    
    # 是否强制开启断路由,默认false
    hystrix.command.default.circuitBreaker.forceOpen=false
    
    # 是否强制关闭断路由,默认false
    hystrix.command.default.circuitBreaker.forceClosed=false
    
  3. 创建接口:定义一个与服务标准api相同的Application Client服务接口(该接口通过@FeignClient注解描述fallback方法所在类是什么)
    @FeignClient(name="feign-service-01" fallback=MyServiceConsumerImpl.class)
    public interface MyServiceConsumer extends MyService{}
    
  4. 创建接口实现类:实现的方法都修改为托底方法
    @Component
    public class MyServiceConsumerImpl implements MyServiceConsumer{
    	//实现的方法返回托底数据即可
    }
    

2. 请求合并

Feign不推荐使用请求合并

Hystrix Dashboard

针对Hystrix进行实时监控的工具,可以直观看到Hystrix Command的请求响应时间、请求成功率等数据

实现

依然在Client端实现

  1. 引入依赖
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.cloud</groupId>
    	<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
  2. 配置相关信息(不配置则监控不到,因为actuator用来采集被监控的数据,actuator考虑了安全问题,默认信息几乎没有,所以需要对其进行配置
    # 默认开启health和info,*表示全开(不推荐)
    management.endpoints.web.exposure.include=*
    
    # 添加hytrix信息
     management.endpoints.web.exposure.include=hystrix.stream
    
  3. 启动类添加EnabledHystrixDashboard注解开启,还需要开启@EnabledCircuitBreaker
    @SpringBootApplication
    @EnableHystrixDashboard
    @EnableCircuitBreaker
    public class SpringBootApp{
    	public static void main(String[] args){
    		SpringApplication.run(SpringBootApp.class,args);
    	}
    }
    
  4. 访问
    http:ip:port/actuator - 显示可访问的监控地址(spring-boot-starter-actuator提供)
    http:ip:port/hystrix - 显示Hystrix监控数据图形界面(spring-cloud-starter-netflix-hystrix-dashboard提供)
    http:ip:port/actuator/hystrix.stream - 显示Hystrix采集数据(spring-boot-strarter-actuator提供)
    在这里插入图片描述

Zuul

Zuul是Spring Cloud中的微服务网关,网关是一个网络整体系统中的前置门户入口,请求首先通过网关,进行路径的路由定位到具体的服务节点上
在这里插入图片描述

1. 作为路由使用

Zuul首先是一个微服务,也会在Eureka注册中心进行服务的注册和发现

路由表是一个Map<String,Map<String,Object>>
path代表请求路径
url代表Application Client地址(简单直观)
serviceId代表Application Client的名称(集群方便)

  1. 引入依赖(web、eureka-client、zuul)
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-cloud-starter-web</artifactId>
    </dependency>
    <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>
    
  2. 创建启动类,开启zuul网关(@EnableZuulProxy)
    @SpringBootApplication
    @EnableZuulProxy
    public class SpringBootApp{
    	public static void main(String[] args){
    		SpringApplication.run(SpringBootApp.class,args);
    	}
    }
    
  3. 配置
    # 应用名称
    spring.application.name=zuul-01
    
    # 开放端口
    server.port=80
    
    # Eureka注册中心
    eureka.client.serviceUrl.defaultZone=http://192.168.54.100:8761/eureka,http://192.168.54.100:8762/eureka
    
    # 基于路径映射的匹配规则(直观)
    zuul.routes.test.path=/test/**
    zuul.routes.test.url=http://localhost:8081/
    
    # 基于服务映射的匹配规则(集群方便,外层key为服务名称就可以省略服务配置)
    zuul.routes.test.path=/test/**
    zuul.routes.test.ServiceId=Application-Client-01
    # 等同于
    zuul.routes.Application-Client-01.path=/test/**
    

2. 作为网关过滤器使用

  1. 创建一个过滤器
    public class MyFilter extends ZuulFilter{
    	
    	/**判断当前的过滤器是什么类型
    	*前置【pre】			- 路由之前执行
    	*路由后【route】 	- 路由之后,未转发请求时执行
    	*异常【error】		- 发生异常(一定是过滤器异常)时执行
    	*后置【post】		- 转发请求响应后执行
    	*/
    	@Override
    	public Stirng filterType(){
    		//定义当前为前置过滤器
    		return "pre";
    	}
    
    	//判断当前过滤器的执行顺序
    	//同类过滤器,按顺序执行
    	//数值越小,越先执行
    	@Override
    	public int filterOrder(){
    		return 0;
    	}
    
    	//是否开启过滤器
    	@Override
    	public boolean shouldFilter(){
    		return true;
    	}
    	
    	//定义一个日志
    	private final Logger logger=LoggerFactory.getLogger(PreFilter.class);
    	
    	//过滤器具体执行内容
    	@Override
    	public Object run() throws ZuulException(){
    		//日志打印
    		logger.info();
    		return null;
    	}
    	
    	//zuul网关提供的请求上下文
    	//RequestContext是线程安全的,直接与线程绑定threadLocal.get()
    	RequestContext context=RequestContext.getCurrentContext();
    	//获取请求
    	HttpServletRequest request=context.getRequest();
    	//请求地址
    	request.getRequestURL();
    	//请求方法
    	request.getMethod();
    }
    

Zuul的生命周期

client - zuul - pre filter - routing filter - application - post filter - client
pre filet、routing filter有异常:- error filter - post filter - client
application异常 - sendErrorFilter - error filter - post filter -client
如果post filter异常,则直接由error filter直接响应client
在这里插入图片描述

Zuul网关的容错

在Spring Cloud中,Zuul启动器中包含了Hystrix的相关依赖,默认提供了Hystrix Dashboard服务监控数据与Hystrix无缝结合的

1. 服务降级处理

Zuul提供了FallbackProvider接口用于实现fallback处理,只针对timeout异常处理,只要服务有返回(包括返回异常),都不会触发Zuul的fallback容错逻辑,因为Zuul在做请求路由分发的时候,结果由远程服务运算,如果远程服务返回异常,而Zuul不能确定该异常是否是应用想要反馈给客户端的

  1. 创建FallbackProvider的实现类
    @Compoent
    public class My implements FallbackProvider{
    	//获取路由信息
    	@Override
    	public String getRoute(){
    		//可以使用通配符“*”,代表为全部的服务提供容错处理
    		return "application-name-*";//为服务名前缀为application-name-所有服务提供容错处理
    	}
    
    	//服务容错处理的具体逻辑,route是服务名称,cause是异常类型
    	public ClientHttpResponse fallbackResponse(String route,Throwable cause){
    		
    		return new ClientHttpResponse(){
    			
    			//返回响应状态对象(枚举类型)
    			@Override
    			public HttpStatus getStatusCode() throws IOException{
    				return HttpStatus.GATEWAY_TIMEOUT;//网关超时
    			}
    			
    			//返回响应状态码
    			@Override
    			public int getRawStatusCode() throws IOException{
    				return this.getStatusCode().value();
    			}
    			
    			//返回响应状态字符串描述
    			@Override
    			public String setStatusText() throws IOException{
    				retuen this.getStatusCode().getReasonPhrease();
    			}
    			
    			//获取响应输出的内容(以输入流方式返回)
    			@Override
    			public InputStream getBody() throws IOException{
    				Map<String,Object> result=new HashMap<>();
    				result.put("message","服务器繁忙,请稍后重试");
    				ObjectMapper mapper=new ObjectMapper();
    				Strng message=mapper.writeValueAsString(result);
    				InputStream in=new ByteArrayInputStream(message.getBytes("utf-8"));
    				return in;
    			}
    			
    			//返回响应头
    			@Override
    			public HttpHeader getHeader(){
    				HttpHeaders headers=new HttpHeaders();
    				headers.set("content-type","application/json;charset=utf-8");
    				return headers;
    			}
    
    			//回收资源的方法
    			@Override
    			public void close(){}
    		};
    	}
    }
    
  2. 配置Zuul的超时设定
    # zuul从接收到请求开始计时,到响应返回到浏览器为止(默认1000ms)
    zuul.host.socket-timeout-millis=4000
    
    # zuul从路由开始计时,到Application Client返回响应为止(默认)
    zuul.host.connect-timeou-millis=3000
    
    # 请求转发开始计时,到Application Client建立连接为止
    ribbon.ConnectTimeout=2000
    
    # 请求转发开始计时,到Application Client返回结果为止
    ribbon.ReadTimemout=2100
    
    注意:HTTP连接的超时设定必须大于ribbon的连接超时设定,这样才能避免在ribbon未超时直接就返回fallback结果
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值