Springcoud-netflix 笔记

SpringCloud_Netflix

微服务一代(Netflix)学习前提:

  1. JAVASE、

  2. 数据库(MySQL)、

  3. 前端(HTML+CSS+JavaScript||JQuery、Bootstrap、LayUI、EasyUi、VUE+ElementUI2/3 )

  4. JQuery - AJAX || Axios || Json

  5. (JavaWEB-Tomcat):JSP&Servlet、HTTP

  6. Mybatis、Hibernate

  7. Spring、SpringMVC、Struts2

  8. Springboot 2.x

  9. Dubbo+Zookeeper+Springboot、分布式基础

  10. 项目构建与打包:Maven、版本控制:GIt

本阶段学什么:

 第一次学习的架构:三层架构  +  MVC
 框架:
  Spring :IOC + AOP :解决企业开发的复杂性,简化开发。
 
  SpringBoot:   约定大于配置 || 自动装配 新一代Java开发标准起步
 
  模块化开发: ALl in One   ====》 微服务架构
 
 
 微服务架构四个核心问题:
  1.服务那么多,客户端如何去访问(API网关)
  2.服务之间如何通信(HTTP、RPC)
  3.服务如何治理(服务注册与发现)
  4.微服务出现问题了(挂了),怎么容灾
 解决方案:SpringCLoud就是分布式生态,主要是解决微服务引起的问题。
  1.SpringCloud——Netflix:一站式解决方案!
  2.Dubbo+Zookeeper :半自动需要整合其他的技术!
  3.SpringCloud--Alibaba:最新的一站式解决方案!
 

image-20210527172138053

SpringCloud:组件

image-20210527174024210

(一):SpringCLoud——Netflix

停更的一站式解决微服务方案:

API网关:Zuul组件

服务通讯:Feign -- HTTPClient-----Http通讯方式、同步、阻塞。

服务注册与发现: Eureka

熔断机制:Hystrix

(二):Dubbo + Zookeeper

API网关:自身没有----》》》》整合第三方组件或者自己实现

服务通讯:Dubbo 》》》基于RPC的高性能通讯框架

服务注册与发现:Zookeeper

熔断机制:自身没有借助 SpringCLoud——Netflix熔断组件》》》》》 Hystrix

(三):SpringCLoud——Alibaba

最新更方便的一站式解决微服务方案:

API网关:Gateway

服务通讯:OpenFeign

Spring Cloud 默认的服务调用依赖 OpenFeign 或 RestTemplate 使用 REST 进行调用。

使用 @DubboTransported 注解可将底层的 Rest 协议无缝切换成 Dubbo RPC 协议,进行 RPC 调用。

服务注册与发现:Nacos

Spring Cloud Alibaba 基于 Nacos 提供

spring-cloud-alibaba-starter-nacos-discovery & spring-cloud-alibaba-starter-nacos-config

实现了服务注册 & 配置管理功能。

依靠 @EnableDiscoveryClient 进行服务的注册,

兼容 RestTemplate & OpenFeign 的客户端进行服务调用。

熔断机制:Hystrix

服务限流降级 :Sentinel

作为稳定性的核心要素之一,服务限流和降级是微服务领域特别重要的一环,Spring Cloud Alibaba 基于 Sentinel,对 Spring 体系内基本所有的客户端,网关进行了适配,

默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入。

Sentinel应用比较简单,只需引入 starter,即可生效,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。

微服务消息驱动:RocketMQ

支持为微服务应用构建消息驱动能力,基于 Spring Cloud Stream 提供 Binder 的新实现: Spring Cloud Stream RocketMQ Binder,

也新增了 Spring Cloud Bus 消息总线的新实现 Spring Cloud Bus RocketMQ。

分布式事务:Seata

使用 Seata 解决微服务场景下面临的分布式事务问题。

使用 @GlobalTransactional 注解,在微服务中传递事务上下文,可以对业务零侵入地解决分布式事务问题。

阿里云提供的商业能力:

通过OSS,schedulerx等组件,开发者可以在阿里云上实现对象存储,分布式任务调度等功能。

Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。

Alibaba Cloud OSS:阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的云存储服务。

Alibaba Cloud SchedulerX:阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准的定时(基于 Cron 表达式)任务调度服务。

 Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
 
 Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
 
 RocketMQ:开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
 
 Dubbo:这个就不用多说了,在国内应用非常广泛的一款高性能 Java RPC 框架。
 
 Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
 
 Arthas:开源的Java动态追踪工具,基于字节码增强技术,功能非常强大。

SpringBoot 与 SpringCloud的版本对应详细版

image-20210528135659313

在实际开发过程中,我们需要更详细的版本对应:

image-20210528135736074

最新的SpringCloud:https://spring.io/projects/spring-cloud#learn

image-20210528204318589

Eureka<->RestTemplate微服务:

1.Eureka微服务服务端。

 <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
 </dependency>

2.配置Eureka基础 application.yml

 server:
 port: 7001
 #Eureka 配置 服务注册与发现
 eureka:
 server:
  enable-self-preservation: false # 关闭自我保护模式,
 instance:
  hostname: localhost   # 注册中心地址
 client:
  register-with-eureka: false   # 剔除自身注册到注册中心
  fetch-registry: false   # 默认是true,,,如果为false表示为注册中心
  service-url:    # 标识监控页面地址::默认是 defaultZone:http://localhost:8761/eureka/
    defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

开启微服务Eureka服务项目即可。。

3.生产者微服务 --本身是Eureka的客服端

         <!--加入Eureka依赖-->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-eureka</artifactId>
             <version>1.4.7.RELEASE</version>
         </dependency>
 
         <!--添加监控信息||actuator-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
         </dependency>

4.开启服务在Eureka的注册中心的自动注册

 @SpringBootApplication
 @EnableEurekaClient  //开启服务的Eureka中心自动注册自身
 public class ProdApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ProdApplication.class,args);
    }
 
 }

5.生产者服务的Eureka注册中心的配置

 #Eureka配置,服务注册到注册中心
 eureka:
  client:
    service-url: #指定注册中心地址
      defaultZone: http://localhost:7001/eureka/
  instance:
    instance-id: SpringCloud-ProdServer # 修改Eureka默认对本微服务描述信息
 info:
  app.name: guotong-springcloud
  company.name: study.gton.com
   
 server:
  port: 8888
 #配置Spring微服务项目名称,数据源配置,,,第三方入Druid是type配置
 spring:
  application:
    name: prodService
  datasource:
    driver-class-name: org.gjt.mm.mysql.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://localhost:3306/study?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
    username: root
    password: root
 
 #mybatis 配置 核心配置文件位置??和mapperxml位置
 mybatis:
  config-location: classpath:/maybati-config.xml
  mapper-locations: classpath:/mapper/*.xml
 #Property 'configuration' and 'configLocation' can not specified with together|不能一起指定|所以其余配置放置在配置文件中
 # configuration:
 #   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #日志
 #   map-underscore-to-camel-case: true # 驼峰自动转化

生产者的Mybatis-config.xml

 <?xml version="1.0" encoding="UTF-8" ?>
 <!DOCTYPE configuration
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
 
     <!--开启二级缓存-->
     <settings>
         <!--开启二级缓存-->
         <setting name="cacheEnabled" value="true"/>
         <!--配置日志输出-->
         <setting name="logImpl" value="STDOUT_LOGGING" />
         <!--开启驼峰字段自动转化-->
         <setting name="mapUnderscoreToCamelCase" value="true" />
     </settings>
 
     <!--配置别名-->
     <typeAliases>
         <package name="com.gton.pojo"/>
     </typeAliases>
 
 </configuration>

6.Eureka的自我保护机制。。

 Eureka server和client之间每隔30秒会进行一次心跳通信,告诉server,client还活着。
 保护状态实际上是考虑了client和server之间的心跳是因为网络问题,而非服务本身问题,不能简单删除注册信息。
 在此状态下,server不会删除注册信息,这就有可能导致在调用微服务时,实际上服务并不存在。
 解决自我保护机制:
 # 1、在生产上可以开自注册,部署两个server
 # 2、在本机器上测试的时候,可以把比值调低,比如0.49
 # 3、或者简单粗暴把自我保护模式关闭

Eureka集群

本质就是建立多个Eureka加服务,各个Eureka的服务相关挂载关联,即使崩掉了一个,还可以继续维持原业务功能。

image-20210605154254548

1.建立多个Eureka服务的maven项目。。

2.导入Eureka服务端依赖

  		<!-- netflix-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--热部署工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>

3.编写Eureka集群关联配置:

server:
  port: 7001
#Eureka 配置 服务注册与发现
eureka:
  instance:
    hostname: localhost   #  注册中心地址
  client:
    register-with-eureka: false   #  剔除自身注册到注册中心
    fetch-registry: false   # 默认是true,,,如果为false表示为注册中心
    service-url:    # 标识监控页面地址::默认是  defaultZone:http://localhost:8761/eureka/
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  # 单机
      #集群的话需要设计关联 (集群服务)
      defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/

3.开启以接受别的服务注册进入

@SpringBootApplication
@EnableEurekaServer //开启Eureka服务端注册授权
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

4.消费者集群挂载多个注册中心

#Eureka配置,服务注册到注册中心
eureka:
  client:
    service-url: #指定默认的注册中心地址
      #defaultZone: http://localhost:7001/eureka/  #单机一个
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/  #集群,关联多个
  instance:
    instance-id: SpringCloud-ProdServer # 修改Eureka默认描述信息

注意这里全写localhost是不能集群的,相互不会自动注册。需要到文件制定域名映射,不同得域名才可以生效。。

CAP原则:

  • 关系式数据库(MySQL,Oracle,Sqlserver)====》ACID(原子性、一致性、隔离性、持久性)

  • 非关系式数据库(Redis、MongoDB)====》CAP(强一致性、高可用性、分区容错性)

  • CAP无法保证同时都满足,只能三选二 ====》CP || AP || AC

CAP核心:一个分布式系统不能同时很好的满足一致性、可用性、分区容错性。

  1. CA :单点集群、满足一致性、可用性的系统,通常可扩展性比较差。

  2. CP :满足一致性、分区容错性的系统,通常性能不是很高 。

  3. AP :满足可用性、分区容错性的系统,通常可能对一致性要求偏低。

Eureka VS Zookeeper:

由于分区容错性P在分布式系统中要必须保证,只能在AP和CP中选择。

  • Zookeeper 保证的是CP {一致性+分区容错性}

  • Eureka 保证的是AP {可用性+分区容错性}

Zookeeper如何保证CP:

当向注册中心查询服务列表的时候,我们可以容忍注册中心返回的是几分钟前的注册信息。但是不能接受服务直接down掉不可用。所以服务注册功能对可用性的要求高于一致性。

Zookeeper会出现一种情况:当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。 问题在于leader选举稍长,20-120S,且选举期间整个Zookeeper集群不可用,所以选举期间导致了注册服务功能瘫痪。

在云部署环境下(核心:网络不可靠),因为网络问题使得zk集群失去master节点可能性比较大。虽然服务最终能恢复,但是漫长的选举时间导致注册长期不可用是非常恼火的(不能容忍)。

Eureka如何保证AP:

Eureka因为看到了Zookeeper的缺点,所以设计时候就优先保证了高可用性(A)。Eureka所有的节点都是平等关系.几个节点挂掉不会影响正常的节点工作,剩余节点依旧可以各行其职。

Eureka客户端向某个Eureka服务注册的时候,如果连接失败会自动切换其他的节点。只要有一台Eureka服务还在,就能保证注册服务功能的高可用。只不过查询的信息可能不是最新的。

Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没正常心跳,那么Eureka认为客户端与注册中心之间出现了网络故障,此时会出现一下几种情况:

  1. Eureka不会再从注册列表中移出因为长时间没有收到心跳而过期的服务。

  2. Eureka任然能够接收到新服务的注册和查询服务,但是不会同步到其他节点上(保证当前节点可用)

  3. 当前网络稳定时,当前实例新的注册信息会同步到其他节点上。

总结:Eureka很好的解决了网络故障导致的部分节点失去联系的情况,不会像Zookeeper的主节点(master)瘫痪而选举新的leader时候整个服务会不可用。

Eureka-负载均衡(RIbbon)

核心将用户的请求平摊到多个服务器上,让系统高可用

负载均衡{LoadBalance}理论:

负载均衡具体是干什么:

  • 负载均衡是高可用网络基础架构的关键组件,通常用于将工作负载分布到多个服务器来提高网站、应用、数据库或其他服务的性能和可靠性。

为什么要负载均衡:

  • 用户是直连到 web 服务器,如果这个服务器宕机了,那么用户自然也就没办法访问了。另外,如果同时有很多用户试图访问服务器,超过了其能处理的极限,就会出现加载速度缓慢或根本无法连接的情况。

负载均衡解决什么问题:

  • 而通过在后端引入一个负载均衡器和至少一个额外的 web 服务器,可以缓解这个故障。通常情况下,所有的后端服务器会保证提供相同的内容,以便用户无论哪个服务器响应,都能收到一致的内容。

负载均衡算法决定了后端的哪些健康服务器会被选中。几个常用的算法:

  • Round Robin(轮询):为第一个请求选择列表中的第一个服务器,然后按顺序向下移动列表直到结尾,然后循环。

  • Least Connections(最小连接):优先选择连接数最少的服务器,在普遍会话较长的情况下推荐使用。

  • Source:根据请求源的 IP 的散列(hash)来选择要转发的服务器。这种方式可以一定程度上保证特定用户能连接到相同的服务器。

    • 可以形成不同的负载均衡技术,常见的包括:

      • DNS轮询

      • CDN

      • IP负载均衡

常见的负载均衡软件·:::Nginx、LVS 、{Tomcat+Apache}

dubbo 、Springcloud中均给我们提供了负载均衡,Springcloud还支持自定义负载均衡算法

负载均衡(LB)分类:

  • 集中式LB =》Nginx:反向代理服务器(请求通过策略转发不同的服务器) ,服务的消费者和生产者之间独立使用的LB设施。

  • 进程式LB =》 RIbbon。将LB逻辑集成到消费者,消费者获取注册中心那些可用地址,再从这些可用服务选择一个合适的服务器。

  • Ribbon是一个进程内的负载均衡,它只是一个类库,集成于消费者进程,消费者通过它连接注册中心来获取服务站提供的地址。

项目集成Ribbon:

1.消费者引入Ribbon启动器和Eureka客户端的依赖

 
         <!--集成于消费者的客户端负载均衡 Ribbon|Eureka -->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-ribbon</artifactId>
             <version>1.4.7.RELEASE</version>
         </dependency>
         <!--加入Eureka依赖-->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-eureka</artifactId>
             <version>1.4.7.RELEASE</version>
         </dependency>

2.配置文件关联Eureka集群注册中心,还有不向Eureka注册中心注册消费者本身

 server:
  port: 80
 
 #Eureka 配置 消费者不注册,主要指集成负载均分Ribbon
 eureka:
  client:
    register-with-eureka: false # 不向Eureka中注册自己,
     #集群注册中心 消费者关联所有的注册中心,基于ribbon实现服务负载均衡
    service-url:
      defaultZone: http://eureka01.server.com:7001/eureka/,http://eureka02.server.com:7002/eureka/,http://eureka03.server.com:7003/eureka/
 

3.需要给restTemplate组件bean添加支持RIbbon的负载均衡支持。

   /**
      * Description: 本身RestTemplate未注册到Spring,手动注册 ----> @Bean
      * <p>
      * Description: 配置Ribbon负载均衡 ,实现基于RestTemplate的负载均衡即可 -----> @LoadBalanced
      * <p>
      * 服务间的调度基于RESTFUL方式可以通过RestTemplate 请求来完成
      * <p>
      * Ribbon 负载均衡是基于客户端|消费者来完成的   进程式:实现负载均衡,需要配置Eureka注册中心。
      *
      * @author: GuoTong
      * @date: 2021-05-28 23:19:14
      */
     @Bean
     @LoadBalanced
     public RestTemplate getRestTemplate() {
         return new RestTemplate();
    }
 

4.服务消费:消费者调生产者服务,是基于Ribbon的负载均衡了,所以不能使用准确的域名加IP完成。依赖于负载均衡策略自动调取某个注册中心的服务。

  /**
      * Description: 如果是集群的,并且负载均衡的话,通过RIbbon去负载均衡寻找的服务是动态变量
      * 所以通过服务名来访问。然后请求的服务有Ribbon 负载均衡到集群的某一个注册中心服务。
      * 由RestTemplate模板工具跨服务调用。消费功能
      *
      * @author: GuoTong
      * @date: 2021-06-05 17:51:54
      * @param: getProdServiceByRibbonInColony 获取基于集群的负载均衡的生产者服务
      * @return:
      */
     @RequestMapping("/getProdServiceByRibbon")
     public Object getProdServiceByRibbonInColony() {
         // CommonDataEntity.PROD_PREFIX || http://localhost:8888/ 不可用了,有集群的负载,所以通过服务名来访问{注意服务名是注册在Eureka的监控界面的名字,应该全部切换成大写了}
         String ribbonColonyProdService = "http://PRODSERVICE/";
         String URI = "getDataByMysql";
         ResultEntity forObject = restTemplate.getForObject(ribbonColonyProdService + URI, ResultEntity.class);
         return forObject;
    }

5.流程图解:

image-20210606153958697

默认的负载均衡采用轮训机制。

基于Feign的远程调用和负载均衡

Feign本质集成了ribbon,本质还是基于ribbon的负载均衡。feign自改装了REST模板,进一步魔改基于接口的远程调用。

1.接口

 
 @Component
 @FeignClient(value = "PRODSERVICE")
 public interface FeginByService {
 
     @GetMapping("/getByFeignInUser")
     List<User> getListsByFeign();
     
     @GetMapping("/getByFeignInId/{userId}")
     User getUserById(@PathVariable("userId") int userId);
 }
 

2.引入接口

 
 @Autowired
 private FeginByService feginByService;
 
 @RequestMapping("/getALl")
 public List<User> getAllByFeign() {
    return this.feginByService.getListsByFeign();
 }
 
 @RequestMapping("/getById/{id}")
 public User getById(@PathVariable("id") int id) {
    return feginByService.getUserById(id);
 }

3.开启feign客户端注册

 @EnableFeignClients(basePackages = {"com.gton"})
 @ComponentScan("com.gton")

分布式系统面临的问题:

复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免的失败。

(一)服务雪崩

多个微服务之间的调用的时候,会有扇出的情况。如果扇出链上的某个微服务的调用响应时间过长或者不可用,对微服务调用会占用越来越多的系统资源,进而引起系统崩溃,就是雪崩效应。 对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几秒中内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统.

(二)Hystrix:

Hystrix 是一个用于处理分布式系统的延迟和容错的开源库。在分布式系统中,许多依赖不可避免的会调用失败,比如超时,异常等。Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置。当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的被选响应。而不是长时间的等待或者抛出调用方法无法处理的异常。这样的可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

  • 服务降级

  • 服务熔断

  • 服务限流

  • 接近实时的监控

。。。。。。。。。。待续

posted on 2021-06-07 10:54  白嫖老郭  阅读(190)  评论(0编辑  收藏  举报

导航