精华内容
下载资源
问答
  • 熔断机制 概述 防止由于某一个服务的死亡导致整个系统的死亡,对该服务的调用执行熔断。对于后学请求,不在继续调用,该目标服务,而是直接返回。从而可以快速的释放资源,实现原理类似电路的断路器,调用超过...

    SpringCloud

    微服务设计

    服务拆分

    1. 纵向拆分
      1. 用界面层
      2. 应用层
      3. 领域层
      4. 基础设施层
    2. 横向查分
    3. 领域驱动设计

    服务注册\服务发现

    服务消费

    消费模式

    1. 服务直连模式,通过url直接访问
      1. 简单明了
      2. 平台语言无关性
      3. 无法保证服务的可用性
      4. 生产环境使用较少
    2. 客户端发现模式
      1. 运作流程
        1. 服务实例启动后,将自己的位置信息提交到服务注册表
        2. 客户端冲服务注册表进行查询,来获取可用的服务实例
        3. 客户端自行使用负载均衡算法从多个服务实例中选出一个
    3. 服务端发现模式
      1. 他的运作模式和客户端发现模式发现一样,但是**负载均衡是在注册表的服务端上实现的,客户端无序关心负载均衡**

    消费者框架

    Apache HttpClient

    通过url请求获取返回值

    依赖:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.3</version>
    </dependency>
    

    注入RestTemplate类

    @Configuration
    public class ConfigBean {
        @Autowired
        private RestTemplateBuilder restTemplateBuilder;
    
        @Bean
        public RestTemplate getRestTemplate(){
            return restTemplateBuilder.build();
        }
    }
    

    使用

    private void saveWeatherDate(String url) {
        ResponseEntity<String> restString = restTemplate.getForEntity(url, String.class);
        // . . .
    }
    
    Ribbon(后期重点研究负载均衡的实现原理)

    实现客户端复杂均衡的工具

    Feign

    依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
        <version>2.0.0.RELEASE</version>
    </dependency>
    

    配置

    #服务通信超时时间
    feign.client.config.feignName.connectTimeout=100
    feign.client.config.feignName.readtTimeout=100
    

    Spring boot 中激活该模块 @EnableFeignClients

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
    }
    

    配置service层

    @FeignClient("city") //指定服务名称  多层次路由 @FeignClient(name="服务名",path="路径名")
    public interface CityClient {
    
      	//指定服务中接口名
        @GetMapping("/citys")
        String cityList();
    
    }
    

    调用

    @Autowired
    private CityClient cityClient;
    
    @GetMapping("/index")
    @ResponseBody
    public String index(){
        return cityClient.cityList();
    }
    

    统一入口(API网关)

    意义

    1. 聚合多个API
    2. 统一api入口

    利弊

    1. 避免将内部的信息暴露给外部,将内部的微服务api和外部的访问api区分开来
    2. 为微服务提供单独的保护层,系统权限系统的实现
    3. 支持混合通信协议
    4. 降低构建服务的复杂性(api令牌,访问控制,网速限制,从代码层隔离这些功能)
    5. 微服务模拟和虚拟化
    6. 需要额外的编排和管理
    7. 路由逻辑配置需要进行统一的管理
    8. 引发单点故障,api网关的不可用会导致整个服务的不可用

    常见的实现方式

    nginx
    Kong(基于nginx)
    zuul

    maven依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-zuul -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        <version>2.1.2.RELEASE</version>
    </dependency>
    

    配置(简单使用)

    # 设置请求转发 将hi路径下的请求转发到名为city的微服务下
    zuul.routes.hi.path= /hi/**
    zuul.routes.hi.service-id=city
    

    功能列表:

    1. 认证
    2. 压力测试
    3. 金丝雀测试
    4. 动态路由
    5. 负载消减
    6. 安全
    7. 静态响应处理
    8. 主动/主动交还管理

    配置管理

    集中化配置的意义

    1. 微服务数量多,配置多
    2. 手工管理配置繁琐

    配置分类

    1. 配置来源划分:开发环境,测试环境,预发环境,生产环境
    2. 配置的集成阶段划分:编译时,打包时,运行时
    3. 配置的加载方式:启动加载,动态加载

    服务端实现

    依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>
    

    启用config-server

    通过注解启用spring-cloud-config-server: @EnableConfigServer

    配置

    spring.application.name=config
    server.port=8888
    #服务中心地址
    eureka.client.service-url.defaultZone= http://localhost:8761/eureka/
    
    #仓库地址
    spring.cloud.config.server.git.uri=https://github.com/luohengyi/springCloudConfig.git
    #指定仓库中的文件夹
    spring.cloud.config.server.git.search-paths=config-repo
    

    访问

    通过路径auther/dev(该url框架自带!) 来访问初始化页面http://localhost:8888/auther/dev

    客户端实现

    依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-config-server -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
        <version>2.1.3.RELEASE</version>
    </dependency>
    

    配置

    spring.application.name=config-client
    eureka.client.service-url.defaultZone= http://localhost:8761/eureka/
    
    server.port=8889
    
    #当前服务职会读取该服务名称+profile的配置文件
    spring.cloud.config.profile=dev
    #配置服务器的地址
    spring.cloud.config.uri=http://localhost:8888
    

    启用

    无需单独使用注解启动,配置服务器后自动调用配置

    熔断机制

    概述

    防止由于某一个服务的死亡导致整个系统的死亡,对该服务的调用执行熔断。对于后学请求,不在继续调用,该目标服务,而是直接返回。从而可以快速的释放资源,实现原理类似电路的断路器,调用超过负载的服务会通过断路器直接返回一个默认信息,断路器的状态分为:1.打开、2.关闭(当服务正常时关闭,但是会做一些失败次数的统计,当失败次数达到阀值时,断路器会打开,将异常信息直接返回给调用者)、3.半打开(关闭一段时间后,断路器会放开一些请求,当这些请求都能正常执行时,断路器会认为,服务已经恢复正常,这时断路器会关闭),

    功能

    1. 异常处理
    2. 日志记录
    3. 测试失败的操作
    4. 手动复位
    5. 并发
    6. 加速短路
    7. 重试失败请求

    熔断框架hystrix

    依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        <version>2.1.0.RELEASE</version>
    </dependency>
    

    启动

    1. 使用注解 @EnableCircuitBreaker

    2. @GetMapping
      //配置默认方法,当该服务接口无法使用时候,调用defaults返回给调用者
      @HystrixCommand(fallbackMethod = "defaults")
      public List<City> cityList() throws Exception{
          return cityDateService.listCity();
      }
      
      public List<City> defaults(){
          return  null;
      }
      
      

    制动扩展

    Cloud子项目

    配置管理 config

    服务注册/服务发现(Eureka)

    服务端

    依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server  注意soring 和cloud的版本对应问题 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        <version>1.4.7.RELEASE</version>
    </dependency>
    
    

    配置

    server.port=8761
    eureka.instance.hostname= localhost
    #禁用客户端
    eureka.client.registerWithEureka=false
    eureka.client.fetchRegistry=false
    
    
    #服务地址配置
    eureka.client.service-url.defaultZone= http://${eureka.instance.hostname}:${server.port}/eureka/
    
    

    注解方式 @EnableEurekaServer 注解启用Eureka server 可以通过访问localhost:8761查看 Eureka server信息

    @SpringBootApplication
    @EnableEurekaServer
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
    }
    
    

    客户端

    依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        <version>2.0.0.RELEASE</version>
    </dependency>
    
    

    配置

    #该客户端的名称,该服务注册到服务端后显示的名字
    spring.application.name=myeurekaclien
    
    #服务端地址配置,将该服务注册到该服务端上
    eureka.client.service-url.defaultZone= http://localhost:8761/eureka/
    
    

    注解方式启用客户端

    @SpringBootApplication
    @EnableDiscoveryClient
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    
    }
    
    

    客户端服务可以启动多个来实现分布式

    断路器

    负载均衡

    智能路由

    服务间调用

    一次性令牌

    微代理

    思维导图模版

    全局锁

    控制总线

    领导选举

    分布式会话

    集群状态

    分布式消息

    展开全文
  • SpringCloud的重试和熔断机制主要依赖Spring-Retry来实现,完整功能实现主要依赖以下几个对象: RetryOperation:接口,主要定义了重试的API; RetryTemplate: RetryOperation的模板实现,其将重试和熔断功能进行封装...

    简介

    SpringCloud的重试和熔断机制主要依赖Spring-Retry来实现,完整功能实现主要依赖以下几个对象:

    • RetryOperation:接口,主要定义了重试的API;
    • RetryTemplate: RetryOperation的模板实现,其将重试和熔断功能进行封装,提供健壮性和不易出错的API供大家使用;
    • RetryCallback:进行重试时的相关操作;
    • RecoveryCallback:所有重试都尝试后进行有状态的重试;
    • RetryState:用来记录有状态的重试;
    • RetryContext:重试上下文

    RetryTemplate逻辑实现

    RetryTemplate是熔断和重试的功能实现模板,其主要属性如下:

    • BackOffPolicy:回退策略,是立即重试还是等一段时间在重试,默认实现是NoBackOffPolicy,也就是失败后立即重试;
    • RetryPolicy:重试策略,重试时将采用何种方式重试;
    • RetryListener[]:重试监听器,业务方用来在重试进行补充操作;
    • RetryContextCache:重试上下文缓存,用于缓存RetryContext;

    重试具体逻辑如下:

    	protected <T, E extends Throwable> T doExecute(RetryCallback<T, E> retryCallback,
    			RecoveryCallback<T> recoveryCallback, RetryState state)
    			throws E, ExhaustedRetryException {
    
    		RetryPolicy retryPolicy = this.retryPolicy;
    		BackOffPolicy backOffPolicy = this.backOffPolicy;
    
    		// RetryPolicy进行初始化以及在state不为空的情况下进行相关缓存
    		RetryContext context = open(retryPolicy, state);
    		if (this.logger.isTraceEnabled()) {
    			this.logger.trace("RetryContext retrieved: " + context);
    		}
    
    		// 注册上下文,以便客户端可以使用该context
    		RetrySynchronizationManager.register(context);
    
    		Throwable lastException = null;
    
    		boolean exhausted = false;
    		try {
    
    			// 调用相关重试拦截器,以便clients能够进行上下文增强
    			boolean running = doOpenInterceptors(retryCallback, context);
    
    			if (!running) {
    				throw new TerminatedRetryException(
    						"Retry terminated abnormally by interceptor before first attempt");
    			}
    
    			// Get or Start the backoff context...
    			BackOffContext backOffContext = null;
    			Object resource = context.getAttribute("backOffContext");
    
    			if (resource instanceof BackOffContext) {
    				backOffContext = (BackOffContext) resource;
    			}
    
    			if (backOffContext == null) {
    				backOffContext = backOffPolicy.start(context);
    				if (backOffContext != null) {
    					context.setAttribute("backOffContext", backOffContext);
    				}
    			}
    
    			/*
    			 * 根据重试策略和重试上下文来判断是否需要进行重试;             
    			 */
    			while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {
    
    				try {
    					if (this.logger.isDebugEnabled()) {
    						this.logger.debug("Retry: count=" + context.getRetryCount());
    					}
    					// Reset the last exception, so if we are successful
    					// the close interceptors will not think we failed...
    					lastException = null;
    					return retryCallback.doWithRetry(context);
    				}
    				catch (Throwable e) {
    
    					lastException = e;
    
    					try {//注册重试异常,同时会在相关retryPolicy中进行ServerInstance替换,来保证下次重试
    						registerThrowable(retryPolicy, state, context, e);
    					}
    					catch (Exception ex) {
    						throw new TerminatedRetryException("Could not register throwable",
    								ex);
    					}
    					finally {
    						doOnErrorInterceptors(retryCallback, context, e);
    					}
    
    					if (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {
    						try {
    							backOffPolicy.backOff(backOffContext);
    						}
    						catch (BackOffInterruptedException ex) {
    							lastException = e;
    							// back off was prevented by another thread - fail the retry
    							if (this.logger.isDebugEnabled()) {
    								this.logger
    										.debug("Abort retry because interrupted: count="
    												+ context.getRetryCount());
    							}
    							throw ex;
    						}
    					}
    
    					if (this.logger.isDebugEnabled()) {
    						this.logger.debug(
    								"Checking for rethrow: count=" + context.getRetryCount());
    					}
    
    					if (shouldRethrow(retryPolicy, context, state)) {
    						if (this.logger.isDebugEnabled()) {
    							this.logger.debug("Rethrow in retry for policy: count="
    									+ context.getRetryCount());
    						}
    						throw RetryTemplate.<E>wrapIfNecessary(e);
    					}
    
    				}
    
    				/*
    				 * A stateful attempt that can retry may rethrow the exception before now,
    				 * but if we get this far in a stateful retry there's a reason for it,
    				 * like a circuit breaker or a rollback classifier.
    				 */
    				if (state != null && context.hasAttribute(GLOBAL_STATE)) {
    					break;
    				}
    			}
    
    			if (state == null && this.logger.isDebugEnabled()) {
    				this.logger.debug(
    						"Retry failed last attempt: count=" + context.getRetryCount());
    			}
    
    			exhausted = true;
    			return handleRetryExhausted(recoveryCallback, context, state);
    
    		}
    		catch (Throwable e) {
    			throw RetryTemplate.<E>wrapIfNecessary(e);
    		}
    		finally {
    			close(retryPolicy, context, state, lastException == null || exhausted);
    			doCloseInterceptors(retryCallback, context, lastException);
    			RetrySynchronizationManager.clear();
    		}
    
    	}
    

    RetryPolicy重试策略

    重试策略是用来定义怎么重试的?spring-retry是当抛出相关异常后执行重试策略,需要定义重试的异常(例如入参校验失败异常不允许重试,调用超时可以重试等)。一般情况下只读操作可以重试,幂等写操作可以重试,非幂等写不可以重试,因为可能会产生脏数据或者重复数据,重试策略分为以下几类:

    • NeverRetryPolicy:只允许调用RetryCallback一次,不允许重试;
    • AlwaysRetryPolicy:允许无线重试,直到成功,可能会导致死循环;
    • CircuitBreakerRetryPolicy:待有熔断功能的重试,需要设置RetryPolicy代理和resetTimeOut,openTimeOut三个参数;
    • CompositeRetryPolicy:组合熔断策略,可以将多个策略组合,有两种组合方式,乐观组合重试策略是指只要有一个策略允许重试即可以,悲观组合重试策略是指只要有一个策略不允许重试即可以,但不管哪种组合方式,组合中的每一个策略都会执行;
    • ExceptionClassifierRetryPolicy:根据异常分类的重试策略;
    • ExceptionRetryPolicy:根据指定异常进行重试策略;
    • SimpleRetryPolicy:固定次数重试机制,默认重试三次;
    • TimeOutRetryPolicy:超时重试机制,默认超时时间为1秒,在超时时间内进行重试;

    BackOffPolicy回退策略

    BackOffPolicy有以下几种回退策略:

    • NoBackPolicy:重试时立即重试;
    • FixedBackPolicy:固定时延回退策略,
    • UniformRandomBackOffPolicy:在指定[minBackOffPeriod,maxBackOffPeriod]之间随机选择时间回退策略;
    • ExponentialBackOffPolicy:指数回退策略,需设置参数sleeper、initialInterval、maxInterval和multiplier,initialInterval指定初始休眠时间,默认100毫秒,maxInterval指定最大休眠时间,默认30秒,multiplier指定乘数,即下一次休眠时间为当前休眠时间*multiplier;
    • ExponentialRandomBackOffPolicy:随机指数回退策略,引入随机乘数,来避免固定乘数可能导致很多服务同时进行重试导致DDos;

    RetryState重试状态

    重试状态分为:stateful(有状态)和stateless(无状态)两种:

    • 无状态:指的是重试时是在一个循环中执行重试策略,即重试上下文保持在一个线程上下文中,在一次调用中进行完整的重试策略判断;
    • 有状态重试:有两种场景需要进行有状态重试,事务回滚或者熔断器模式;事务回滚时,当整个操作中抛出的是数据库异常DataAccessException,则不能进行重试需要回滚,而抛出其他异常则可以进行重试,可以通过RetryState实现;熔断器模式时,重试不是在同一个线程上下文中进行重试,而是在全局进行重试;

    RetryContext

    重试上下文,用来缓存重试时需要的相关数据,例如用来缓存重试时的相关异常,有如下几种重试上下文:

    • LoadBalancedRetryContext:负载均衡重试上下文,继承RetryContextSupport,其内会维护HttpRequest和ServiceInstance两个属性;
    • RetryContextSupport:其内会维护父RetryContext,重试次数count,重试是否中断标志terminate,以及相关异常lastException;
      ##参考文章
      Spring之重试框架
    展开全文
  • 参考链接:SpringCloud的Hystrix(五) Hystrix机制 新需求列表 1、在线测试 根据定义,生成输入界面, 点击测试, 验证参数,发起调用,返回执行结果 2、熔断保护 两个实现类:  ...

     

    参考链接:SpringCloud的Hystrix(五) Hystrix机制

    新需求列表

    1、在线测试

     

            根据定义,生成输入界面,

            点击测试,

            验证参数,发起调用,返回执行结果

    2、熔断保护

     



     

    两个实现类:

      NoOpCircuitBreakerImpl,什么也不做的断路器实现

      HystrixCircuitBreakerImpl,实现类:

    HystrixCircuitBreakerImpl

    1. HystrixCommandProperties properties
    2. HystrixCommandMetrics metrics
    3. AtomicBoolean circuitOpen
    4. AtomicLong circuitOpenedOrLastTestedTime:断路器打开或是上一次测试时间戳

    HystrixCircuitBreakerImpl的方法

      isOpen 判断断路器的打开/关闭状态

               如果打开,直接返回true,表示断路器处于打开状态。否则,从度量指标metrics中获取healthcounts统计对象进一步判断(该对象记录了一个滚动时间窗内的请求信息快照,默认时间窗为10秒)

                      如果请求总数qps在预设的阈值范围内就返回false,表示断路器处于未打开状态,默认值20

                      如果错误百分比在阈值范围内就返回false,表示断路器处于未打开状态,默认值50

                      如果上述两个条件都不满足,就将断路器设置为打开状态(熔断/短路)。同时,如果从关闭状态切换到打开状态的话,就将时间记录到circuitOpenedOrLastTestedTime中。

           allowRequest 判断请求是否被允许

               判断是否强行打开,是则 return false 

               判断是否强行关闭,是则 isOpen & return true

               !isOpen()||allowSingleTest()::断开时的时间戳+配置中的circuitBreakerSleepWindowInMillseconds 是否 小于当前时间,如果是的话,就将当前时间更新到记录断路器打开的时间circuitBreakerOpenedOrLastTestedTime中,并允许该请求。

                      即设置了断路器打开后的休眠时间(默认为5秒),休眠时间达到之后,将再次允许请求尝试访问,此时断路器处于“”半开“”,

                               若此时请求继续失败,则断路器又进入打开状态,并等待下一个休眠窗口过去之后再尝试。

                               若请求成功, 则将断路器重新置于关闭状态。

                               所以,allowSingleTest()和isOpen()配合,实现了断路器的打开和关闭状态的切换。

           markSuccess 用来关闭断路器  在“半开”状态时使用。若调用命令成功,通过调用它将打开的断路器关闭,并重置度量指标对象。

    命令执行的四个结果:成功、失败、超时、拒绝,用来更新计时器

    3、性能测试

    4、调用计量

    转载于:https://www.cnblogs.com/lexiaofei/p/7687811.html

    展开全文
  • Spring Cloud 入门教程(七): 熔断机制 -- 断路器 对断路器模式不太清楚的话,可以参看另一篇博文:断路器(Curcuit Breaker)模式,下面直接介绍Spring Cloud的断路器如何使用。 SpringCloud Netflix实现了...

    Spring Cloud 入门教程(七): 熔断机制 -- 断路器

    对断路器模式不太清楚的话,可以参看另一篇博文:断路器(Curcuit Breaker)模式,下面直接介绍Spring Cloud的断路器如何使用。

    SpringCloud Netflix实现了断路器库的名字叫Hystrix. 在微服务架构下,通常会有多个层次的服务调用. 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图:

     

    一个微服务的超时失败可能导致瀑布式连锁反映,下图中,Hystrix通过自主反馈实现的断路器, 防止了这种情况发生。

     图中的服务B因为某些原因失败,变得不可用,所有对服务B的调用都会超时。当对B的调用失败达到一个特定的阀值(5秒之内发生20次失败是Hystrix定义的缺省值), 链路就会被处于open状态, 之后所有所有对服务B的调用都不会被执行, 取而代之的是由断路器提供的一个表示链路open的Fallback消息.  Hystrix提供了相应机制,可以让开发者定义这个Fallbak消息.

    open的链路阻断了瀑布式错误, 可以让被淹没或者错误的服务有时间进行修复。这个fallback可以是另外一个Hystrix保护的调用, 静态数据,或者合法的空值. Fallbacks可以组成链式结构,所以,最底层调用其它业务服务的第一个Fallback返回静态数据.

    下面,进入正题,在之前的两HELLO WORLD服务集群中加入断路器, 防止其中一个Hello world挂掉后, 导致系统发生连锁超时失败。

    1. 在maven工程(前面章节中介绍的Ribbon或者Feign工程)的pom.xml中添加hystrix库支持断路器

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>

    2. 在Ribbon应用中使用断路器

    1). 在Spring Boot启动类上添加@EnableCircuitBreaker注解

    复制代码
    1 @SpringBootApplication
    2 @EnableDiscoveryClient
    3 @EnableCircuitBreaker
    4 public class ServiceRibbonApplication {
    5 
    6     public static void main(String[] args) {
    7         SpringApplication.run(ServiceRibbonApplication.class, args);
    8     }
    。。。 。。。
    复制代码

    2). 用@HystrixCommand注解标注访问服务的方法

    复制代码
     1 @Service
     2 public class HelloService {
     3     @Autowired RestTemplate restTemplate;
     4 
     5     @HystrixCommand(fallbackMethod = "serviceFailure")
     6     public String getHelloContent() {
     7         return restTemplate.getForObject("http://SERVICE-HELLOWORLD/",String.class);
     8     }
     9 
    10     public String serviceFailure() {
    11         return "hello world service is not available !";
    12     }
    13 }
    复制代码

    @HystrixCommand注解定义了一个断路器,它封装了getHelloContant()方法, 当它访问的SERVICE-HELLOWORLD失败达到阀值后,将不会再调用SERVICE-HELLOWORLD, 取而代之的是返回由fallbackMethod定义的方法serviceFailure()。@HystrixCommand注解定义的fallbackMethod方法,需要特别注意的有两点:

    第一,  fallbackMethod的返回值和参数类型需要和被@HystrixCommand注解的方法完全一致。否则会在运行时抛出异常。比如本例中,serviceFailure()的返回值和getHelloContant()方法的返回值都是String。

    第二,  当底层服务失败后,fallbackMethod替换的不是整个被@HystrixCommand注解的方法(本例中的getHelloContant), 替换的只是通过restTemplate去访问的具体服务。可以从中的system输出看到, 即使失败,控制台输出里面依然会有“call SERVICE-HELLOWORLD”。

    启动eureka服务,只启动两个Helloworld服务,然后中断其中一个(模拟其中一个微服务挂起),访问http://localhost:8901/然后刷新, 由于有负载均衡可以看到以下两个页面交替出现。可以看到第二个被挂起的服务,被定义在Ribbon应该里面的错误处理方法替换了。

             

    4. 在Feign应用中使用断路器

    1). Feign内部已经支持了断路器,所以不需要想Ribbon方式一样,在Spring Boot启动类上加额外注解

    2). 用@FeignClient注解添加fallback类, 该类必须实现@FeignClient修饰的接口。

    1 @FeignClient(name = "SERVICE-HELLOWORLD", fallback = HelloWorldServiceFailure.class)
    2 public interface HelloWorldService {
    3     @RequestMapping(value = "/", method = RequestMethod.GET)
    4     public String sayHello();
    5 }

    3). 创建HelloWorldServiceFailure类, 必须实现被@FeignClient修饰的HelloWorldService接口。注意添加@Component或者@Service注解,在Spring容器中生成一个Bean

    复制代码
    1 @Component
    2 public class HelloWorldServiceFailure implements HelloWorldService {
    3     @Override
    4     public String sayHello() {
    5         System.out.println("hello world service is not available !");
    6         return "hello world service is not available !";
    7     }
    8 }
    复制代码

    4). Spring Cloud之前的Brixton版本中,Feign是缺省是自动激活了断路器的,但最近的Dalston版本已经将缺省配置修改为禁止。

    原因参见:  https://github.com/spring-cloud/spring-cloud-netflix/issues/1277, 这一点要注意。所以要在Feign中使用断路器, 必须在application.yml中添加如下配置:

    feign:
       hystrix:
         enabled: true

    5). 启动Feign应用, 访问http://localhost:8902/hello, 可以一看到和Ribbon一样的效果。

    转载于:https://www.cnblogs.com/wzb0228/p/10973149.html

    展开全文
  • 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图 一个微服务的超时失败可能导致瀑布式连锁反映,下图中,Hystrix通过自主反馈实现的断路器, 防止了这种情况发生。 图中的服务B因为某些原因失败...
  • 该项目提供了用于微服务体系结构的API网关,并基于反应式Netty和Project Reactor构建。它旨在提供一种简单而有效的方法来路由到API并解决诸如安全性,监视/度量和弹性之类的普遍关注的问题。 基于Redis限流 Spring ...
  • 对断路器模式不太清楚的话,可以参看另一篇博文:断路器(Curcuit Breaker)模式,下面...下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图: 一个微服务的超时失败可能导致瀑布式连锁反映,下...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 191
精华内容 76
关键字:

api熔断机制