SpringCloud组件基本使用和介绍(一)

公众号springcloudAlibaba实战和源码分析正在火热更新中,更有17种Java生态技术面试宝典

 

组成:

  1. 服务注册与发现组件:Eureka,Zookeeper,Consul,Nacos等。Eureka基于REST风格的。

  2. 服务调用组件:Hystrix(熔断降级,在出现依赖服务失效的情况下,通过隔离 系统依赖服务 的方式,防止服务级联失败,同时提供失败回滚机制,使系统能够更快地从异常中恢复),Ribbon(客户端负载均衡,用于提供客户端的软件负载均衡算法,提供了一系列完善的配置项:连接超时、重试等),OpenFeign(优雅的封装Ribbon,是一个声明式RESTful网络请求客户端,它使编写Web服务客户端变得更加方便和快捷)。

  3. 网关:路由和过滤。Zuul,Gateway。

  4. 配置中心:提供了配置集中管理,动态刷新配置的功能;配置通过Git或者其他方式来存储。

  5. 消息组件:Spring Cloud Stream(对分布式消息进行抽象,包括发布订阅、分组消费等功能,实现了微服务之间的异步通信)和Spring Cloud Bus(主要提供服务间的事件通信,如刷新配置)

  6. 安全控制组件:Spring Cloud Security 基于OAuth2.0开放网络的安全标准,提供了单点登录、资源授权和令牌管理等功能。

  7. 链路追踪组件:Spring Cloud Sleuth(收集调用链路上的数据),Zipkin(对Sleuth收集的信息,进行存储,统计,展示)。

组件概述:

  1. Eureka:服务注册与发现,用于服务管理。

  2. Feign:web调用客户端,能够简化HTTP接口的调用。

  3. Ribbon:基于客户端的负载均衡。

  4. Hystrix:熔断降级,防止服务雪崩。

  5. Zuul:网关路由,提供路由转发、请求过滤、限流降级等功能。

  6. Config:配置中心,分布式配置管理。

  7. Sleuth:服务链路追踪

  8. Admin:健康管理

RestTemplate + Eureka

  @Bean  RestTemplate restTemplate() {      return new RestTemplate();  }  @BeanRestTemplate restTemplate() {  RestTemplate restTemplate = new RestTemplate();  //自定义过滤器  restTemplate.getInterceptors().add(new LoggingClientHttpRequestInterceptor());  return restTemplate;}

调用http服务​​​​​​​

String url ="http://provider/sayHello";String respStr = restTemplate.getForObject(url, String.class);

Ribbon + Eureka

当系统面临大量的用户访问,负载过高的时候,通常会增加服务器数量来进行横向扩展(集群),多个服务器的负载需要均衡,以免出现服务器负载不均衡,部分服务器负载较大,部分服务器负载较小的情况。通过负载均衡,使得集群中服务器的负载保持在稳定高效的状态,从而提高整个系统的处理能力。​​​​​​​

@Bean// 开启负载均衡@LoadBalancedRestTemplate restTemplate() {    return new RestTemplate();}

Ribbon作为Spring Cloud的负载均衡机制的实现,

  1. Ribbon可以单独使用,作为一个独立的负载均衡组件。只是需要我们手动配置 服务地址列表。

  2. Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表(DiscoveryClient),并基于负载均衡算法,请求其中一个服务提供者实例。

  3. Ribbon与OpenFeign和RestTemplate进行无缝对接,让二者具有负载均衡的能力。OpenFeign默认集成了ribbon。

负载均衡算法

ZoneAvoidanceRule(区域权衡策略):复合判断Server所在区域的性能和Server的可用性,轮询选择服务器。

其他规则:

BestAvailableRule(最低并发策略):会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。逐个找服务,如果断路器打开,则忽略。

RoundRobinRule(轮询策略):以简单轮询选择一个服务器。按顺序循环选择一个server。

RandomRule(随机策略):随机选择一个服务器。

AvailabilityFilteringRule(可用过滤策略):会先过滤掉多次访问故障而处于断路器跳闸状态的服务和过滤并发的连接数量超过阀值得服务,然后对剩余的服务列表安装轮询策略进行访问。

WeightedResponseTimeRule(响应时间加权策略):据平均响应时间计算所有的服务的权重,响应时间越快服务权重越大,容易被选中的概率就越高。刚启动时,如果统计信息不中,则使用RoundRobinRule(轮询)策略,等统计的信息足够了会自动的切换到WeightedResponseTimeRule。响应时间长,权重低,被选择的概率低。反之,同样道理。此策略综合了各种因素(网络,磁盘,IO等),这些因素直接影响响应时间。

RetryRule(重试策略):先按照RoundRobinRule(轮询)的策略获取服务,如果获取的服务失败则在指定的时间会进行重试,进行获取可用的服务。如多次获取某个服务失败,就不会再次获取该服务。主要是在一个时间段内,如果选择一个服务不成功,就继续找可用的服务,直到超时。

Feign

OpenFeign是Netflix 开发的声明式、模板化的HTTP请求客户端。可以更加便捷、优雅地调用http api。

OpenFeign会根据带有注解的函数信息构建出网络请求的模板,在发送网络请求之前,OpenFeign会将函数的参数值设置到这些请求模板中。

feign主要是构建微服务消费端。只要使用OpenFeign提供的注解修饰定义网络请求的接口类,就可以使用该接口的实例发送RESTful的网络请求。还可以集成Ribbon和Hystrix,提供负载均衡和断路器。

是一个 Http 请求调用的轻量级框架,可以以 Java 接口注解的方式调用 Http 请求,而不用像 Java 中通过封装 HTTP 请求报文的方式直接调用。通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。Feign 封装 了HTTP 调用流程,面向接口编程。

Feign和OpenFeign的关系

Feign本身不支持Spring MVC的注解,它有一套自己的注解

OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口, 并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。​​​​​​​

@RequestMapping("/User")public interface RegisterApi {
    @GetMapping("/isAlive")    public String isAlive();}

//provider实现当前接口并实现​​​​​​​

package com.mashibing.UserProvider;
import com.mashibing.UserAPI.RegisterApi;@RestControllerpublic class UserController implements RegisterApi {
    @Override    public String isAlive() {        return "ok";    }
}

consumer调用​​​​​​​

@FeignClient(name = "user-provider")public interface UserConsumerService extends RegisterApi {
}
@RestControllerpublic class ConsumerController {
    @Autowired    UserConsumerService consumerSrv;        @GetMapping("/alive")    public String alive() {                return consumerSrv.isAlive();    }    }

Get和Post

Feign默认所有带参数的请求都是Post,想要使用指定的提交方式需引入依赖

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

并指明提交方式

@RequestMapping(value = "/alived", method = RequestMethod.POST)
@GetMapping("/findById")

带参请求

    @GetMapping("/findById")
    public Map findById(@RequestParam("id") Integer id);
    
    @PostMapping("/register")
    public Map<String, String> reg(@RequestBody User user);

原理

  1. 主程序入口添加@EnableFeignClients注解开启对Feign Client扫描加载处理。根据Feign Client的开发规范,定义接口并加@FeignClient注解。

  2. 当程序启动时,会进行包扫描,扫描所有@FeignClient注解的类,并将这些信息注入Spring IoC容器中。当定义的Feign接口中的方法被调用时,通过JDK的代理方式,来生成具体的RequestTemplate。当生成代理时,Feign会为每个接口方法创建一个RequestTemplate对象,该对象封装了HTTP请求需要的全部信息,如请求参数名、请求方法等信息都在这个过程中确定。

  3. 然后由RequestTemplate生成Request,然后把这个Request交给client处理,这里指的Client可以是JDK原生的URLConnection、Apache的Http Client,也可以是Okhttp。最后Client被封装到LoadBalanceClient类,这个类结合Ribbon负载均衡发起服务之间的调用。

超时

Feign默认支持Ribbon;Ribbon的重试机制和Feign的重试机制有冲突,所以源码中默认关闭Feign的重试机制,使用Ribbon的重试机制​​​​​​​

#连接超时时间(ms)ribbon.ConnectTimeout=1000#业务逻辑超时时间(ms)ribbon.ReadTimeout=6000

重试​​​​​​​

#同一台实例最大重试次数,不包括首次调用ribbon.MaxAutoRetries=1#重试负载均衡其他的实例最大重试次数,不包括首次调用ribbon.MaxAutoRetriesNextServer=1#是否所有操作都重试ribbon.OkToRetryOnAllOperations=false

使用ribbon重试机制,请求失败后,每个6秒会重新尝试

Hystrix

spring cloud 用的是 hystrix,是一个容错组件。

Hystrix实现了 超时机制和断路器模式。

Hystrix是Netflix开源的一个类库,用于隔离远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。主要有以下几点功能:

  1. 为系统提供保护机制。在依赖的服务出现高延迟或失败时,为系统提供保护和控制。

  2. 防止雪崩。

  3. 包裹请求:使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中运行。

  4. 跳闸机制:当某服务失败率达到一定的阈值时,Hystrix可以自动跳闸,停止请求该服务一段时间。

  5. 资源隔离:Hystrix为每个请求都的依赖都维护了一个小型线程池,如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。防止级联失败。

  6. 快速失败:Fail Fast。同时能快速恢复。侧重点是:(不去真正的请求服务,发生异常再返回),而是直接失败。

  7. 监控:Hystrix可以实时监控运行指标和配置的变化,提供近实时的监控、报警、运维控制。

  8. 回退机制:fallback,当请求失败、超时、被拒绝,或当断路器被打开时,执行回退逻辑。回退逻辑我们自定义,提供优雅的服务降级。

  9. 自我修复:断路器打开一段时间后,会自动进入“半开”状态,可以进行打开,关闭,半开状态的转换。

整合Feign

配置

feign.hystrix.enabled=true
@FeignClient(name = "user-provider",fallback = AliveBack.class)public interface ConsumerApi {
    @RequestMapping(value = "/User/alive",method = RequestMethod.GET)    public String alive();        @RequestMapping(value = "/User/getById",method = RequestMethod.GET)    public String getById(Integer id);}​​​​​​​
@Componentpublic class AliveBack implements ConsumerApi{
    @Override    public String alive() {        // TODO Auto-generated method stub        return "aaa";    }
    @Override    public String getById(Integer id) {        // TODO Auto-generated method stub        return null;    }
}

使用fallbackFactory检查具体错误​​​​​​​

@Componentpublic class WebError implements FallbackFactory<ConsumerApi> {
    @Override    public ConsumerApi create(Throwable cause) {        // TODO Auto-generated method stub        return new ConsumerApi() {                        @Override            public Person postPserson(Person person) {                // TODO Auto-generated method stub                return null;            }                        @Override            public String getById(Integer id) {                // TODO Auto-generated method stub                return null;            }                        @Override            public String alive() {                // TODO Auto-generated method stub                System.out.println(cause.getLocalizedMessage());                cause.printStackTrace();                return ToStringBuilder.reflectionToString(cause);            }                        @Override            public Map<Integer, String> postMap(Map<String, Object> map) {                // TODO Auto-generated method stub                return null;            }                        @Override            public Map<Integer, String> getMap3(Map<String, Object> map) {                // TODO Auto-generated method stub                return null;            }                        @Override            public Map<Integer, String> getMap2(Integer id, String name) {                // TODO Auto-generated method stub                return null;            }                        @Override            public Map<Integer, String> getMap(Integer id) {                // TODO Auto-generated method stub                return null;            }        };    }
}

针对不同异常返回响应​​​​​​​

@Overridepublic String alive() {    // TODO Auto-generated method stub    System.out.println(cause);    if(cause instanceof InternalServerError) {        System.out.println("InternalServerError");        return "远程服务报错";    }else if(cause instanceof RuntimeException) {                return "请求时异常:" + cause;    }else {        return "都算不上";    }}

信号量隔离与线程隔离

默认情况下hystrix使用线程池控制请求隔离

线程池隔离技术,是用 Hystrix 自己的线程去执行调用;而信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。

信号量隔离主要维护的是Tomcat的线程,不需要内部线程池,更加轻量级。​​​​​​​

hystrix.command.default.execution.isolation.strategy 隔离策略,默认是Thread, 可选Thread|Semaphorethread 通过线程数量来限制并发请求数,可以提供额外的保护,但有一定的延迟。一般用于网络调用semaphore 通过semaphore count来限制并发请求数,适用于无网络的高并发请求hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds 命令执行超时时间,默认1000mshystrix.command.default.execution.timeout.enabled 执行是否启用超时,默认启用truehystrix.command.default.execution.isolation.thread.interruptOnTimeout 发生超时是是否中断,默认truehystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。semaphore应该占整个容器(tomcat)的线程池的一小部分。

开启dashboard

启动类

@EnableHystrixDashboard
<dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>        spring-cloud-starter-netflix-hystrix-dashboard    </artifactId></dependency>
<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-actuator</artifactId></dependency>

健康上报

http://localhost:90/actuator/hystrix.stream

图形化

http://localhost:90/hystrix

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山竹之七语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值