(转)Spring Cloud(二)

(二期)23、微服务框架spring cloud(二)

【课程23】熔断器-Hystrix.xmind0.1MB

【课程23】微服务...zuul.xmind0.2MB

熔断器-Hystrix

雪崩效应

在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。

如下图所示: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回退函数

Hystrix如何解决依赖隔离

  • 1:Hystrix使用命令模式HystrixCommand(Command)包装依赖调用逻辑,每个命令在单独线程中/信号授权下执行。
  • 2:可配置依赖调用超时时间,超时时间一般设为比99.5%平均时间略高即可.当调用超时时,直接返回或执行fallback逻辑。
  • 3:为每个依赖提供一个小的线程池(或信号),如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。
  • 4:依赖调用结果分:成功,失败(抛出异常),超时,线程拒绝,短路。 请求失败(异常,拒绝,超时,短路)时执行fallback(降级)逻辑。
  • 5:提供熔断器组件,可以自动运行或手动调用,停止当前依赖一段时间(10秒),熔断器默认错误率阈值为50%,超过将自动运行。
  • 6:提供近实时依赖的统计和监控

Hystrix整合步骤

第一步:导入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注解参数详解

Feign使用Hystrix回退机制

定义一个实现类,接口端使用@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";
            }
        };
    }
}

在实际开发中,并不是所有的请求都要提前预备好服务降级问题,如果我就是要将服务调用失败的信息展示给用户,那么此时就没有必要添加断路器了。

Hystrix断路器模式的状态监控

关闭服务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

Hystrix的两种隔离方式

https://www.cnblogs.com/java-synchronized/p/7927726.html

  • 线程隔离
  • 它将在单独的线程上执行,并发请求受线程池中的线程数量的限制。
  • 把执行依赖代码的线程与请求线程(如:jetty线程)分离,请求线程可以自由控制离开的时间(异步过程)。
  • 通过线程池大小可以控制并发量,当线程池饱和时可以提前拒绝服务,防止依赖问题扩散。
  • 线上建议线程池不要设置过大,否则大量堵塞线程有可能会拖慢服务器。

  • 信号量隔离
  • 它将在调用线程上执行,开销相对较小,并发请求收到信号量个数的限制。
  • 信号隔离也可以用于限制并发访问,防止阻塞扩散, 与线程隔离最大不同在于执行依赖代码的线程依然是请求线程(该线程需要通过信号申请)
  • 当n个并发请求去调用一个目标服务接口时,都要获取一个信号量才能真正去调用目标服务接口,但信号量有限,默认是10个,可以使用maxConcurrentRequests参数配置,如果并发请求数多于信号量个数,就有线程需要进入队列排队,但排队队列也有上限,默认是 5,如果排队队列也满,则必定有请求线程会走fallback流程,从而达到限流和防止雪崩的目的。

服务网关-Zuul

在微服务架构模式下,后端服务的实例数一般是动态的,对于客户端而言很难发现动态改变的服务实例的访问地址信息。因此在基于微服务的项目中为了简化前端的调用逻辑,通常会引入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搞负载均衡。

Cloud-Admin项目

项目

文档中心

原文地址:https://www.cnblogs.com/free-wings/p/10095708.html

时间: 2024-11-01 18:28:49

(转)Spring Cloud(二)的相关文章

spring cloud(二)服务(注册)中心Eureka

Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组件之一. 背景介绍 服务中心 服务中心又称注册中心,管理各种服务功能包括服务的注册.发现.熔断.负载.降级等,比如dubbo admin后台的各种功能. 有了服务中心调用关系会有什么变化,画几个简图来帮忙理解 项目A调用项目B 正常调用项目A请求项目B 有了服务中心之后,任何一个服务都不能直接去掉用

spring cloud(二):spring boot技术总结

1.spring boot简化Spring应用的初始搭建以及开发过程,节省了开发成本及时间,提高了开发人员的生产力 2.含有诸多开箱即用微服务功能,可以和spring cloud联合部署项目能够独立运行,提供了应用监控,能够与微服务联合部署. 3.spring boot简化了配置文件,它使用"习惯优于配置"(项目中存在大量的配置,此外还内置一个习惯性的配置,让你无需手动进行配置) 的理念让你的项目快速运行起来. 3.1.项目中运用了很多默认的配置类,只要用相应的注解,就能引用相应的配置

Spring Cloud (二): 配置管理

使用Config Server,您可以在所有环境中管理应用程序的外部属性.客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用.随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切.服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具.很容易添加

spring cloud (二) 服务提供者 EuekaClient

1 创建一个springboot项目  spring-cloud-service-a  注册到eureka服务注册中心中 项目添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> 2 启动类添加注解 @

Spring Cloud(十四):Ribbon实现客户端负载均衡及其实现原理介绍

年后到现在一直很忙,都没什么时间记录东西了,其实之前工作中积累了很多知识点,一直都堆在备忘录里,只是因为近几个月经历了一些事情,没有太多的经历来写了,但是一些重要的东西,我还是希望能坚持记录下来.正好最近公司用到了一些本篇文章的知识点,所以就抽空记录一下. 本文代码github地址:https://github.com/shaweiwei/RibbonTest/tree/master 简介 ribbon 是一个客户端负载均衡器,它和nginx的负载均衡相比,区别是一个是客户端负载均衡,一个是服务

Spring Cloud 入门教程(二): 配置管理

使用Config Server,您可以在所有环境中管理应用程序的外部属性.客户端和服务器上的概念映射与Spring Environment和PropertySource抽象相同,因此它们与Spring应用程序非常契合,但可以与任何以任何语言运行的应用程序一起使用.随着应用程序通过从开发人员到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切.服务器存储后端的默认实现使用git,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具.很容易添加

Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin【Finchley 版】

Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版] 发表于 2018-04-24 | 随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请求可能最终需要调用很多次后端服务才能完成,当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些后端服务引起的,这时就需要解决如何快读定位服务故障点,以对症下药.于是就有了分布式系统调用跟踪的诞生. 现今业界分布式服务跟踪的理论基础主要来自于 Google 的一篇论文<Dapper, a Larg

java B2B2C电子商务平台分析之十二-----Spring Cloud Sleuth

一.简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可.愿意了解源码的朋友直接求求交流分享技术:二一四七七七五六三三 二.服务追踪分析 微服务架构上通过业务来划分服务的,通过REST调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败.随着业务的不断扩张,服务之间互相调用会越来越复杂. 三.术语 Spr

java版spring cloud+spring boot+redis多租户社交电子商务平台(十二)断路器监控(Hystrix Dashboard)

b2b2c电子商务社交平台源码请加企鹅求求:一零三八七七四六二六.在我的第四篇文章断路器讲述了如何使用断路器,并简单的介绍了下Hystrix Dashboard组件,这篇文章更加详细的介绍Hystrix Dashboard. 一.Hystrix Dashboard简介在微服务架构中为例保证程序的可用性,防止程序出错导致网络阻塞,出现了断路器模型.断路器的状况反应了一个程序的可用性和健壮性,它是一个重要指标.Hystrix Dashboard是作为断路器状态的一个组件,提供了数据监控和友好的图形化