SpringCloud

SpringCloud

简介

用于微服务开发,是一系列框架的有序集合,整合其他微服务框架

微服务架构定义

	将一个独立的系统拆分成若干个小的服务,比如订单、用户管理等。这些小的服务独立部署,服务与服务之间采用http轻量协议传输数据,每个服务独立性强。这样的设计实现了单个服务的高内聚,服务于服务之间低耦合的效果,我们把这些一个一个小的服务成为微服务。
	服务可用不同的语言开发,使用不同的数据存储技术。

微服务优缺点

优点
1.降低耦合度
2.便于服务横向扩容 (如:网购服务 分为 订单、用户、交易等模块,双十一时只是订单会猛增,所以只要单独多部署订单就可以)
3.单个服务更易于开发、维护

缺点
多服务,随着服务的增加,运维困难越大
数据一致性

springCloud定义:是一些组件的集合

组件:注册中心配置中心熔断器网关负载均衡、消息总线、数据监控等

特点:

​ 1.基于spring boot 开发的 回顾视频,此处不完整

SpringCloud的两个事实

1. Feign 集成过 Ribbon 默认开启轮询

2. Feign 集成过 Hytricx 默认关闭 需要开启才能生效  

springcloud与dubbo区别❤️

(面试题)
1.dubbo基于RPC协议实现远程调用,要求所用语言必须是java
2.springcloud规定服务之间通过http协议通信,支持跨语言特性
3.都是微服务的工具,由于协议不同,RPC是基于socket,导致dubbo性能高但是功能少于cloud

服务治理(注册中心)

dubbo与eureka的区别

dubbo的远程调用是使用的@reference注解
eureka的远程调用是使用的RestTemplate模板对象调用方法传值

@SpringBootApplication功能:把这个入口方法类定义为一个核心配置类

@PathVariable(“xxx”) : 将访问路径中{xxx}占位符的值同步到方法参数上赋值

@GetMapping("/good/#{id}")
public void show(@PathVariable("id") int id ){
}

Eureka❤️

Eureka和ZK区别

1.ZooKeeper保证的是CP,Eureka保证的是AP

ZooKeeper在选举期间注册服务瘫痪,虽然服务最终会恢复,但是选举期间不可用的
Eureka各个节点是平等关系,只要有一台Eureka就可以保证服务可用,而查询到的数据并不是最新的

自我保护机制会导致:
    Eureka不再从注册列表移除因长时间没收到心跳而应该过期的服务
    Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点(高可用)
    当网络稳定时,当前实例新的注册信息会被同步到其他节点中(最终一致性)

Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像ZooKeeper一样使得整个注册系统瘫痪

2.ZooKeeper有Leader和Follower角色,Eureka各个节点平等
3.ZooKeeper采用过半数存活原则,Eureka采用自我保护机制解决分区问题
4.Eureka本质上是一个工程,而ZooKeeper只是一个进程
基础介绍

​ Netflix公司开源的一个服务注册与发现的组件

远程对象RestTemplate 封装了三个网络请求 是spring提供的简单便捷的模板类。用于在java代码中访问restful服务。开机自启

如果要切换为其他请求。则new 一个spring提供的对应请求工厂类。由于okttp和httpclient是三方,所以还需要导包!

RestTemplate作用:提供了统一的封装

1.默认 URLConnection

2.Okhttp 是安卓上的协议,性能最好

3.HttpClient apache最早提供的协议
Eureka配置原理

心跳默认30秒一次

服务器未收到心跳90s后才会删除对应客户端

在这里插入图片描述

入门案例

默认服务端口号8761

服务端:
1.导包 (netflix-rureka-server)

    <dependencies>
        <!--spring boot web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>
    
2.在客户端和服务器工程中添加@EnableEurekaClient/@EnableEurekaServer注解

3.在客户端和服务器工程中配置文件

4.启动类添加eureka启动注解

<!-- 注意:如果没有设置实例名 访问主页看到实例名字都是unkown,所以要设置实例名,将来要使用该名称来当作对应的访问路径 -->
<!--		名字不可以重复 -->

5.导入discoveryClient  使用@EnableDiscoveryClient来开启该功能

#结论:
 eureka 配置
 eureka 一共有4部分 配置
 1. dashboard:eureka的web控制台配置
 2. server:eureka的服务端配置
 3. client:eureka的客户端配置
 4. instance:eureka的实例配置
客户端
1.消费方

提供方与消费方导包都是客户端包

  <!-- eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
/**
 * 服务的调用方
 */

@RestController
@RequestMapping("/order")
public class OrderController {

    //此对象不会预读到ioc中
    //要自行定义核心配置类,存入@Bean存入ioc中
    @Autowired
    private RestTemplate restTemplate;

    //通过此对象在eureka中获取远程连接的必要信息,此对象会被springboot通过依赖预读到IOC中
    //所以自动注入即可
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/goods/{id}")
    public Goods findGoodsById(@PathVariable("id") int id){
        System.out.println("findGoodsById..."+id);


        /*
            //远程调用Goods服务中的findOne接口
            使用RestTemplate
            1. 定义Bean  restTemplate
            2. 注入Bean
            3. 调用方法
         */

        /*
            动态从Eureka Server 中获取 provider 的 ip 和端口
             1. 注入 DiscoveryClient 对象.激活
             2. 调用方法
         */

        //演示discoveryClient 使用
        List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");//通过提供方名获取

        //判断集合是否有数据
        if(instances == null || instances.size() == 0){
            //集合没有数据
            return null;
        }

        ServiceInstance instance = instances.get(0); //获得实例对象
        String host = instance.getHost();//获取ip
        int port = instance.getPort();//获取端口

        //打印输出
        System.out.println(host);
        System.out.println(port);

        //拼接url
        String url = "http://"+host+":"+port+"/goods/findOne/"+id;
        
        // 3. 调用方法
        Goods goods = restTemplate.getForObject(url, Goods.class); //到那个地方去访问,以什么类来封装结果

        //回传
        return goods;
    }
}

核心配置类

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

启动类


@EnableDiscoveryClient // 激活DiscoveryClient 此注解用于从服务器上获取远程调用所必要的信息
@EnableEurekaClient	   // 开启此注解表示该工程为客户端(可省略)
@SpringBootApplication // 启动类
public class ConsumerApp {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class,args);
    }
}

yml配置文件

server:
  port: 9000  # 端口号

eureka:
  # 实例主机名可省略
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-consumer # 设置当前应用名称。会在eureka中Application显示。

# 综合归纳:
	#   1.指定默认的服务器连接地址,以获取提供方信息
	#	2.定义该工程名,在服务器中以显示
	#	3.指定端口号(端口号的指定是由于在同一台电脑上模拟,生产时由于分布式所以不需要指定)

Goods对象

package com.itheima.consumer.domain;

/**
 * 商品实体类
 */
public class Goods {

    private int id;
    private String title;//商品标题
    private double price;//商品价格
    private int count;//商品库存

//构造器已省略
// getter/setter 已省略
}

2.提供方

控制层

/**
 * Goods Controller 服务提供方
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @GetMapping("/findOne/{id}")
    public Goods findOne(@PathVariable("id") int id){

        Goods goods = goodsService.findOne(id);  //调用业务层,业务层调用数据库。已省略

        return goods;
    }
}

yml配置文件

server:
  port: 8001

eureka:
  instance:
    hostname: localhost # 主机名 (默认名字。如果不该localhost可以不写)
    prefer-ip-address: true # 将当前实例的ip注册到eureka server中。默认是false 注册主机名
    ip-address: 127.0.0.1 # 设置当前实例的ip
    instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} # 设置web控制台显示的 实例id
   
    # 提供方才需要有这个配置,因为要向服务器传输数据
    lease-renewal-interval-in-seconds: 3 # 每隔3 秒发一次心跳包
    lease-expiration-duration-in-seconds: 9 # 如果9秒没有发心跳包,服务器呀,你把我干掉吧~(eureka有保护机制,如果开启则不会立即关闭,默认开启)
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

# 综合归纳:
# 		1.指定端口号(端口号的指定是由于在同一台电脑上模拟,生产时由于分布式所以不需要指定)
#		2.实例信息
#		3.心跳包(发送条件&超时判断)
#		4.访问服务器地址
#		5.项目名
服务器
       <!-- eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

启动类

@SpringBootApplication
// 启用EurekaServer
@EnableEurekaServer
public class EurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApp.class,args);
    }
}

yml配置文件

registry改为false 表示关闭所有与注册中心的功能

server:
  port: 8761  #(默认端口)

eureka:
  instance:
    hostname: localhost # 主机名
    
    #设置客户端与服务器的通信地址
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
      
    # 下列两句是可以省略的
    register-with-eureka: false # 是否将自己的路径注册到eureka上。eureka server 不需要的,eureka provider client才需要
    fetch-registry: false # 是否需要从eureka中抓取路径。同上,不需要。默认为true。所以消费方没有进行设置
  
  server:
    enable-self-preservation: false # 关闭自我保护机制(调试时才关闭,方便调试)
    eviction-interval-timer-in-ms: 3000 # 检查服务的时间间隔

# 综合归纳:
#	 1.对外访问端口号(有默认值)
#	 2.外部访问地址
#	 3.保护机制,检测服务间隔(有默认值)

Eureka相关配置及特性

一、instance
1.instance-id: 默认使用
spring:
	application:
		name:hello的配置
2.


二、server
生产环境使自我保护机制开启,测试环境可以选择关闭。默认开启
Eureka集群配置
相互注册即可搭建集群,相互注册即把自己当做客户端注册到对方服务端去

由于相互注册,所以resgister-with-euraka=true和fetch-registry: true(相互都要抓取对方信息)

注意:要修改win的system32文件修改本机默认访问名localhost,如果名字不为localhost

相互注册是使用,分割

由于是单机模拟

在C:\Windows\System32\drivers\etc\hosts 文件中 修改对应的主机名localhost1、localhost2 为127.0.0.1的回环地址

注意:1.由于是集群操作,当启动服务器的时候会有一定的连接信息报错,只要全部开启后就可以消除

2.单击模拟,端口不可以冲突,要修改。以后是以ip来区分,所以以后端口是一致的

3.集群操作每个服务器的defaultZone要配置所有的访问地址

配置服务器1
server:
  port: 8762 #(端口要不一致)

eureka:
  instance:
    hostname: localhost1 # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka, http://localhost:8762/eureka # 要配置自带的所有 如果是三台集群此处应为三台的地址

	#都要设置为true 因为对方都要注册到eureka上 并且拉取到对方的信息
    register-with-eureka: true 
    fetch-registry: true 
    
spring:
  application:
    name: eureka-server-ha # 应用名要相同

配置服务器2
server:
  port: 8761 #(端口要不一致)


eureka:
  instance:
    hostname: localhost2 # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8762/eureka,http://localhost:8761/eureka  # 要配置自带的所有 如果是三台集群此处应为三台的地址
      
      	#都要设置为true 因为对方都要注册到eureka上 并且拉取到对方的信息
    register-with-eureka: true 
    fetch-registry: true 

spring:
  application:
    name: eureka-server-ha  # 应用名要相同
客户端

只要是客户端,都要配置每一个服务器的访问地址,相互注册使用,隔开

server:
  port: 9000

eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone:  http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka  # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

项目中导入父工程两种方式

若工程只是使用SpringBoot那么仅使用即可将springBoot的依赖导入

由于一个工程只能有一个parent标签,所以当使用SpringCloud的时候,就要使用import的方式进行导入

    <!--spring boot 环境 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
        <relativePath/>
    </parent>


   <!--版本控制 -->
   <properties>
        <spring-boot-admin.version>2.1.5</spring-boot-admin.version>
    </properties>


<!--引入Spring Cloud 依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>  
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

Consul(历史项目)

由HashiCorp基于go语言开发

官网:www.consul.io

1.导包

消费方,提供方都要导入下包,且必须有actuator的包

<dependencies>
        <!--consul 客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

    </dependencies>
2.开启服务
1.解压consul的文件,在consul.exe存在的目录执行该服务器 consul.exe  
	.\consul agent -dev   由localhost:8500 访问主页
2.启动提供方,消费方
3.定义提供方和消费方yml文件

逻辑代码与上述eureka差不多

server:
  port: 8000
spring:
  cloud:
    consul:
      host: localhost # consul 服务端的 ip
      port: 8500 # consul 服务端的端口 默认8500
      discovery:
        service-name: ${spring.application.name} # 当前应用注册到consul的名称
        prefer-ip-address: true # 注册ip

  application:
    name: consul-provider # 应用名称

server:
  port: 9000


spring:
  cloud:
    consul:
      host: localhost # consul 服务端的 ip
      port: 8500 # consul 服务端的端口 默认8500
      discovery:
        service-name: ${spring.application.name} # 当前应用注册到consul的名称
        prefer-ip-address: true # 注册ip

  application:
    name: consul-consumer # 应用名称

Nacos

nacos包含eureka和spring config两个功能的整合。此处只使用注册中心功能

国产阿里出品,是erueka的替代品,eruka已停更

是注册地中心+配置中心

server-addr: ip:port
1.导包
 <dependencies>
               <!--nacos-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>0.2.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>1.1.0</version>
        </dependency>

    </dependencies>
2.开启
1.解压nacos的文件,在bin目录存在的startup文件,执行即可开启服务器。(进入账户密码 默认nacos)
http://192.168.14.28:8848/nacos/index.html 访问主页
2.启动提供方,消费方
3.定义提供方和消费方yml文件

与consul一致。只是server-addr处要配置ip和端口号

spring:
  cloud:
    nacos:
      discovery:
        server-addr:  127.0.0.1:8848 # 配置nacos 服务端地址
        
  application:
    name: nacos-consumer # 服务名称     此处要区分消费方和提供方

4.注意事项
1.子父工程中 不可有其他eureka的相关组件
2.出现依赖报错,优先删除依赖重新下载

Ribbon(负载均衡)

简介

Netflix 提供的一个HTTP和TCP的客户端负载均衡工具

定义:解决eureka客户端服务负载均衡算法处理器

作用:配置和使用负载均衡,简化代码写法(从端口和ip变量–>服务名称)。

ribbon依赖在eureka依赖中已经存在

注意:是在消费方模块中进行配置!!!


使用:
 1.在定义RestTemplate的@Bean处开启负载均衡功能 
 	@LoadBalanced
 2.编码时使用eureka的服务名称当作访问提供方的地址
 	http://服务名称/访问地址
 	例:http://provider/login
 3.选择算法
 4.启动类上方配置@RibbonClient注解或yml配置文件配置
修改负载均衡策略

配置负载均衡用哪种算法

//定义核心配置类,如果已经存在核心配置,则直接配置bean
@Configuration
public class MyRule{
    //配置bean
    @Bean
    public IRule rule(){
        return new RandomRule();
    }
}

启动类上方具体配置哪个服务器要指定负载均衡策略

1.代码方式

@RibbonClient(name="eureka服务名称",configuration=自定义类.class//省略启动类

2.yml配置方式

eureka服务名称1:
	ribbon:
		NFloadBalancerRuleClassName: 对应策略的全路径名
		
eureka服务名称2:
  ribbon:
   NFloadBalancerRuleClassName: com.netflix.loadbalancer.BestAvailableRule

在这里插入图片描述

//默认轮询
策略定义:
响应时间: 每个服务器都丢一个标识, 谁先响应就用谁
轮询重试: 轮询一次都失败的话,不慌响应失败。再次轮询一次,还失败则响应失败。

在这里插入图片描述

Feign(声明式服务调用)❤️

简介

方便实现客户端的调用,基于接口的注解方式

定义:是微服务之间通过http协议调用的工具

作用:简化消费方的restTemplat+ribbon的操作,连接

Feign是不兼容MVC注解的,所以Cloud对Feign进行了封装,为open-feign

使用方式

规范:所有的接口名、返回值和提供方一模一样。

1.导包(消费端集成openfeign)【哪里需要用远程调用就在哪里导包】此处在消费端导包
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2.配置(超时配置)
ribbon:
  ConnectTimeout: 1000 # 连接超时时间 默认1s
  ReadTimeout: 3000 # 逻辑处理的超时时间 默认1s

3.编码
	1) 入口类上开启Feign功能
		@EnableFeignClients //开启Feign的功能

	2) 编写feign接口,带返回值,告知feign用什么封装返回值
    3) 在此接口上添加@Feignlient("服务名称")
		作用:指定当前类的方法都从Eureka中对应的服务去调用
    4) 定义方法
	    作用:通过该方法,最终实现与提供方的连接
    
    	
     	//定义接口,配置注解
		@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class) //映射该核心类,其中可以指定日志
		public interface GoodsFeignClient {
    
    	//定义方法,方法名、参数、返回值要与提供方一致(规范)
   		 @GetMapping("/goods/findOne/{id}")
   		 public Goods findGoodsById(@PathVariable("id") int id);
		}
	
	   
	5) 在controller层定义接口对象,自动注入
		作用:调用提供方
        
        //在controller中自动注入,调用方法
         @Autowired
  		  private GoodsFeignClient goodsFeignClient;

编写Feign接口

//  指定当前类的方法都从Eureka中对应的服务去调用
@FeignClient("服务的名称")
public interface ProviderService {

	// 通过Controller的地址映射注解告诉Feign该类findOne2方法从服务提供者的/findOne/{id}地址获取信息
    // 通过Controller的参数获取注解告诉Feign的参数信息
    // 通过返回值告诉Feign应该返回的参数应该封装的格式
	@GetMapping("/goods/findOne/{id}")
	 public Goods findOne(@PathVariable("id") int id);
}



//启动类
@SpringBootApplication
@EnableFeignClients
@EnableEurekaClient
public class Consumer {
    public static void main(String[] args) {
        SpringApplication.run(Consumer.class,args);
    }
}
其他功能
1.超时设置

​ feign在调用远程调用提供方时,默认超时时间时1s(Ribbon提供)。如果超时则报错

修改超时时间

在yml文件中修改

要开启注解才生效

@EnableFeignClients

//不能与hystrix的配置同时使用,否则ribbon超时不生效,均默认1s
feign:
  hystrix:
    enabled: true   //此配置的含有是 在消费方使用降级处理,优先级大于ribbon
ribbon:
	#以下两个注解会显示警告错误的颜色。不用管
	connectTimeout: 1000 # 连接超时时间 消费与提供的连接时间
	ReadTimeout: 3000	 # 逻辑处理超时时间,连接后提供方处理时间
	
2.日志功能

feign只能记录debug级别的日志信息

使用

必须开启对应feign接口包的日志为debug

1.配置文件中定义日志是全部/部分开启
2.核心配置类中定义Logger.Level的@Bean对象
3.在启动类上定义@FeignClient(configuration=核心配置类.class)
开启全部(调试)
# 设置当前的日志级别 debug,feign只支持记录debug级别的日志
logging:
  level:
    root: debug
开启部分(生产)
logging:
	level:
	   com.XXX: debug # 指定某个包,仅对该包进行debug日志输出

编码

​ 1.定义日志级别(4个级别)

      /*
        NONE,不记录
        BASIC,记录基本的请求行,响应状态码数据
        HEADERS,记录基本的请求行,响应状态码数据,记录响应头信息
        FULL;记录完成的请求 响应数据
        所有等级都向上包含
     */
@Configuration
public class FeignLogConfig {

    @Bean
    public Logger.Level level(){
        return Logger.Level.FULL;
    }
}

​ 2.配置生效

// Feign接口上方配置 configuration属性
@FeignClient(value = "FEIGN-PROVIDER",configuration = 核心配置类.class)

Hystrix熔断器

简介

Netflix 开源的一个延迟和容错库

作用:用于隔离访问远程服务,用来在微服务中防止出现级联调用引起雪崩的技术工具(预防雪崩)

功能概述

1.隔离:防止被一锅端。隔离不同调用链之间相互不受影响

​ 线程池隔离:把线程池数量按照eureka客户端个数分为不同的小池子,即使一个池子线程用完不会影响其他小池子

在这里插入图片描述

​ 信号量隔离: 指定一个eureka客户端的可访问人数,全部挂掉则均不再对其进行访问

在这里插入图片描述

2.降级:封装友好的错误提示并返回。

​ 分为提供方降级方案(内部异常时给出的降级提示)和消费方自己的降级方案(网络不好时给出的降级提示)

​ 作用: 遇到异常,超时的时候,可以对请求有所返回

3.熔断:某一时间内,错误请求数量溢出,自动降级熔断

4.限流:合理分配每个调用的并发请求数量

主要使用

降级、熔断功能

1.降级
消费方降级

导包

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

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

配置

//在核心配置类上开启降级功能
@EnableCircuitBreaker

编码

1.提供降级方法

2.在要降级的方法上配置对应降级方法注解


降级规则:
	1.降级方法必须和正常处理方法返回值和参数一致
	2.正常处理方法出现异常或超时时进行降级
	3.可以设置,不是所有的异常都要降级处理。注解中有一个ignoreException属性
	

/**
 * Goods Controller 服务提供方
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {

    //自动注入业务层对象
    @Autowired
    private GoodsService goodsService;

    @Value("${server.port}")
    private int port;

    /**
     * 降级:
     *  1. 出现异常
     *  2. 服务调用超时
     *      * 默认1s超时
     *
     *  @HystrixCommand(fallbackMethod = "findOne_fallback")
     *      fallbackMethod:指定降级后调用的方法名称
     */

    
    //定义次方法的@HystrixCommand注解,错误回调方法
    // 双击shitf中 搜索 HystrixCommandProperties 可以查看更多与timeoutInMilliseconds配置相关的定义
    @GetMapping("/findOne/{id}")
    @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
            //设置Hystrix的超时时间,熔断默认1s
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
    	    //监控时间 默认5000 毫秒
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
            //失败次数。默认20次
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"),
            //失败率 默认50%
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50")

    })
    public Goods findOne(@PathVariable("id") int id){

        //1.造个异常
        int i = 3/0;
        
        try {
            //2. 休眠2秒
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        //调用业务层
        Goods goods = goodsService.findOne(id);

        goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
        return goods;
    }


    /**
     * 定义降级方法:
     *  1. 方法的返回值需要和原方法一样
     *  2. 方法的参数需要和原方法一样
     */
    public Goods findOne_fallback(int id){
        Goods goods = new Goods();
        goods.setTitle("降级了~~~");
        return goods;
    }

}

提供方降级

由于提供方需要使用feign调用消费发,而feign内部已经集成了hystrix

如果未使用feign,那么使用上面的方法即可实现降级

yml文件开启降级处理(开启hystrix功能)

# 开启feign对hystrix的支持  默认为false
feign:
  hystrix:
    enabled: true

定义feign接口和实现类


注意:
    0.在核心配置类上开启降级功能@EnableCircuitBreaker
	1.实现类要@Component存入容器
	2.接口中定义实现类,定义注解属性
	3.如果提供方已经配置过降级策略,那么消费方就不会生效【优先在提供方配置降级】(因为已经在提供方处返回了一个正确结果对象)
	
//核心配置类
@EnableDiscoveryClient // 激活DiscoveryClient
@EnableEurekaClient	   //eureka客户端
@SpringBootApplication 
@EnableFeignClients //开启Feign的功能
public class ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class,args);
    }
}
    
    
    //定义feign接口
    //定义feign注解,指定从eruka中获取ip,错误时的回调
	@FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class) 
public interface GoodsFeignClient {

    //定义调用提供方方法,此处的路径是由前端调用的id--> {id}--> 通过该路径传输到提供方调用
    @GetMapping("/goods/findOne/{id}")
    public Goods findGoodsById(@PathVariable("id") int id);

}

//feign接口实现类
@Component  //存入ioc中方便自动注入
public class GoodsFeignClientFallback implements GoodsFeignClient {
    @Override
    public Goods findGoodsById(int id) {
        Goods goods = new Goods();
        goods.setTitle("又被降级了~~~");	
        return goods;
    }
}
2.熔断

熔断无需配置,底层已经自动封装配置成为一种机制。熔断后再来的请求会执行降级方法!

熔断机制概念

注意: 想要实现熔断机制,必须要开启hytrix注解

//在核心配置类上开启降级功能
@EnableCircuitBreaker
	当失败情况达到预定的阈值(5秒内20次请求,50%失败),会打开断路器,拒绝所有请求,以降级的方法返回(熔断器打开)默认5s,默认时间后会放行一些请求(熔断器半开)测试是否恢复正常,不正常继续拒绝请求5s,直到服务恢复正常为止(熔断器关闭)。
// XXXPorperties类中查看所有属性值(HystrixCommandProperties含有所有属性)

    @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
            //设置Hystrix的超时时间,默认1s
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
            //监控时间 默认5000 秒
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
            //失败次数。默认20次
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"),
            //失败率 默认50%
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50")

    })

在这里插入图片描述

熔断监控

用于实时监控微服务运行状态

dashboard 监控一个

Turbine 聚合监控

资料中有搭建步骤

gateway网关❤️

为微服务架构提供一种简单又有效的API路由管理方式

三次握手。四次挥手

文档网址

https://blog.csdn.net/sinat_41144773/article/details/88314735
 //两种协议的区别
	TCP 和 UDP是网络协议的传输层上的两种不同的协议。TCP的特点是面向连接的、可靠的字节流服务。客户端需要和服务器之间建立一个TCP连接,之后才能传输数据。数据到达之前对方就一直在等待,除非对方直接关闭连接,数据有序,先发先到。UDP是一种无连接、不可靠的数据发送协议。发送方根据对方的ip地址发送数据包,但是不保证接收发接包的质量,数据无序还容易丢包。虽然UDP协议不稳定但是在即时通讯(QQ聊天、在线视频、网络语音电话)的场景下,可以允许偶尔的断续,但是这种协议速度快。
//握手
第一次握手:
	客户端发送第一个包,其中SYN标志位为1, ACK=0,发送顺序号sequence=X(随机int)。客户端进入SYN发送状态,等待服务器确认。

第二次握手:
	服务器收到这个包后发送第二个包,其中包SYN、ACK标志位为1,发送顺序号seq=Y(随机int),接收顺序号ACK=X+1,此时服务器进入SYN接收状态。
	
第三次握手:
	客户端收到服务器传来的包后,向服务器发送第三个包,SYN=0, ACK=1,接收顺序号ACK = Y+1,发送顺序号seq=X+1。此包发送完毕,客户端和服务器进入ESTABLISHED建立成功状态,完成三次握手。


//挥手
四次握手是指终止TCP连接协议时,需要在客户端和服务器之间发送四个包
    第一次挥手:主动关闭方发送第一个包,其中FIN标志位为1,发送顺序号seq为X。
    第二次挥手:被动关闭方收到FIN包后发送第二个包,其中发送顺序号seq为Z,接收顺序号ack为X+1。
    第三次挥手:被动关闭方再发送第三个包,其中FIN标志位为1,发送顺序号seq为Y,接收顺序号ack为X。
    第四次挥手:主动关闭方发送第四个包,其中发送顺序号为X,接收顺序号为Y。至此,完成四次挥手。



为什么必须是三次握手,不能用两次握手进行连接?

       记住服务器的资源宝贵不能浪费!  如果在断开连接后,第一次握手请求连接的包才到会使服务器打开连接,占用资源而且容易被恶意攻击!防止攻击的方法,缩短服务器等待时间。两次握手容易死锁。如果服务器的应答分组在传输中丢失,将不知道S建立什么样的序列号,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
定义

是前端js页面与后台沟通的桥梁,由网关来进行通信

定义:前端统一访问微服务的入口
作用:提供认证、鉴权、日志、监控、缓存、负载均衡、流量控制功能
	(由于是入口,所以关系着网络请求速度,添加功能的时候要三思)
使用步骤

创建一个网关工程

​ 1.导包

 <dependencies>
        <!--引入gateway 网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <!-- eureka-client 从注册中心获取提供方信息-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

​ 2.配置

告诉网关哪些请求转发到哪儿去,ip从eureka获取

server:
  port: 80

spring:
  application:
    name: api-gateway-server   # 网关在服务器中显示的名字

  cloud:
    # 网关配置
    gateway:
      # 路由配置:转发规则
      routes: #集合。
      
      # id: 唯一标识。默认是一个UUID
      # uri: 当前路由转发的路径
      # predicates: 条件,用于请求网关路径的匹配规则
      # filters:配置局部过滤器的

      - id: gateway-provider
        # 静态路由
        # uri: http://localhost:8001/
        # 动态路由
        uri: lb://GATEWAY-PROVIDER
        predicates:
        - Path=/goods/**
        filters:
        - AddRequestParameter=username,zhangsan
#        - AddRequestParameter=age,23

      - id: gateway-consumer
        # uri: http://localhost:9000
        uri: lb://GATEWAY-CONSUMER
        predicates:
        - Path=/order/**

        # 微服务名称配置(了解) 【作用:在访问路径前加上自己的eureka服务器名称】
#      discovery:
#        locator:
#          enabled: true # 设置为true 请求路径前可以添加微服务名称
#          lower-case-service-id: true # 允许为小写




# 配置网关从eureka获取信息的地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
静动态路由
        # 静态路由
        uri: http://localhost:8001/  #  写死就是静态路由
        # 动态路由
        uri: lb://GATEWAY-PROVIDER  # 使用lb协议:// 服务名称  为动态路由
网关过滤器

作用:对请求做过滤增强(认证、设置凭证信息等)

具体配置方式在使用步骤中可以查看

注意:

网关过滤器的默认端口是80

如果要使用网关访问,那么必须用该端口来访问

localhost:80/goods/2
  • 局部过滤器:只对配置的路由进行生效

    • org.springframework.cloud.gateway.filter.factory.过滤器名称GatewayFilterFactory

       #在yml文件中,使用过滤器名称进行配置 
       # 过滤器 此处含义是为原始请求添加请求参数
       filters:				
              - AddRequestParameter=username,zhangsan  
              - AddRequestParameter=age,23
      
  • 全局过滤器:所有请求都生效(常用)

    • GlobalFilter
    • Ordered指定过滤器执行的顺序,越小越先执行)
    • 不放行如何?
实现接口  GloblFilter
		 Ordered    按照该接口的重写方法来判定那个过滤器先后执行
		 
步骤:
	1.定义实现类 实现 GlobalFilter, Ordered接口
	2.在重写方法中写代码逻辑
    3.将该实现类存入ioc中
    
	@Component
public class MyFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        System.out.println("自定义全局过滤器执行了~~~");

        return chain.filter(exchange);//放行   
    }

    /**
     * 过滤器排序
     * @return 数值越小 越先执行
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
官方文档

查看所有网关的过滤器

  • https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories
  • 查看笔记文档

config❤️

​ 定义: 在分布式场景下统一管理和维护配置的系统

​ 作用:1.通过配置文件动态更新配置的属性

​ 2.配置信息改变时,不需要重启即可更新配置信息

在这里插入图片描述

使用步骤

1.环境搭建

​ 1)导包

注意:如果是公有仓库,要使用http的传输格式,而不是SSH

		 <!-- 导包 -->
服务端 config-server
    <!-- config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

客户端	 provider/consumer    
	 <!--config client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

克隆到本地仓库

2)localrepository–>gitee

必须以此文件名格式定义: config-dev.yml 格式必须是yml

(config默认8888端口)
# 1.创建文件夹从远程仓库中克隆,使该文件夹成为初始化仓库。
	上传对应配置文件到码云中   # 文件名格式 config-dev.yml
#	访问: http://localhost:9527/master/config-dev.yml
2.客户端搭建

client–>config --> gitee 客户端启动时从config中获取文件,config根据客户端的bootstrap文件从gitee获取yml

# 1.在对应的客户端上导入 config依赖
# 2.配置bootstrap.yml文件( 读取顺序: bootstrap > application)
 	1.configserver的url
 	2.需要使用的文件名称 name: config
 	3.profile:  环境名 dev
 	4.lable: 分支名 master
 
 测试时,启动eureka,否则会报错
 	# 客户端
	# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
  cloud:
    config:
    
      # 配置config-server地址,客户端自动去该地址获取配置文件
      uri: http://localhost:9527
      
      # 配置获得配置文件的名称等信息
      # 文件名称 config-dev.yml 可以分解为如下信息  底层会对如下信息进行拼接处理
      name: config # 文件名
      profile: dev # profile指定
      label: master  # 分支名

# 暴露,此处*已经含有refresh的功能
management:
  endpoints:
    web:
      exposure:
        include: '*'
3.服务端搭建

配置文件

config --> gitee 服务端获取gitee仓库地址

	#服务端
server:
  port: 9527 # 默认8888

spring:
  application:
    name: config-server
    
  # spring cloud config
  cloud:
    config:
      server:
        # git 的 远程仓库地址
        git:
          uri: https://gitee.com/itheima_cch/itheima-configs.git
      label: master # 分支配置

开启服务

#  启动类上开启config服务
@EnableConfigServer 
4.客户端刷新

此刷新必须手动刷新,如果要自动刷新需要配合bus一起使用才能完成

如果不配置刷新功能,配置文件修改后,只更新config-server,不会更新客户端(除非重启)

可以刷新的必要条件

1.客户端必须导入actuator依赖
2.添加注解@RefreshScope(哪里需要从码云上获取配置,就在哪里加注解)
3.客户端暴露refresh配置 
4.输出指令 curl -X  POST htppt://ip名:客户端端口/actuator/fresh 【回车后出现一个数组[]的内容,则表示成功】
//在客户端启动类上开启刷新注解  
//(哪里需要从码云上获取配置,就在哪里加注解,此处是controller上加注解,因为需要用到配置中的常量信息)
@RequestMapping("/goods")
@RefreshScope // 开启刷新功能
public class GoodsController {

    @Autowired
    private GoodsService goodsService;

    @Value("${server.port}")
    private int port;


    @Value("${itheima}")
    private String itheima;
}

Bus❤️

定义:属于spring cloud 的一个组件,微服务之间进行通信的组件(用轻量的消息中间件将分布式的节点连接起来)

作用:用于广播配置文件的更改或者服务的监控管理(通过bus组件对所有下属模块进行操作)

Spring Cloud Bus 可选的消息中间件包括 RabbitMQ 和 Kafka

Bus与Feign的区别

bus基于http协议    feign是消息协议。消息协议有很多

通信原理

与config-server结合使用(运维发送消息给config,config传送信息给MQ–> 给bus 再全局对客户端进行更新操作)

在这里插入图片描述

此图中的ABC和Config-server都是被eureka所管理的

使用步骤

1.导包

该包已集成 MQ
只要是有配置文件的 都需要导入bus依赖

<!-- bus -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

2.客户端配置

在config的配置文件中中配置MQ信息、暴露endpoints

# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
  cloud:
    config:
      # 配置config-server地址
      # uri: http://localhost:9527    		由于已经被eureka所管理,所以直接从eureka获取地址
      # 配置获得配置文件的名称等信息
      name: config # 文件名
      profile: dev # profile指定,  config-dev.yml
      label: master # 分支
      # 从注册中心去寻找config-server地址
      discovery:
        enabled: true
        service-id: CONFIG-SERVER		# 根据在eureka中的应用名来获取config-server地址
  #配置rabbitmq信息
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /

# 暴露 含bus-refresh
management:
  endpoints:
    web:
      exposure:
        include: '*'

3.服务端配置
server:
  port: 9527

spring:
  application:
    name: config-server
    
  # spring cloud config
  cloud:
    config:
      server:
        # git 的 远程仓库地址
        git:
          uri: https://gitee.com/itheima_cch/itheima-configs.git
      label: master # 分支配置
      
  #配置rabbitmq信息
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /


# 将自己注册到eureka中
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka



# 暴露bus的刷新端点
management:
  endpoints:
    web:
      exposure:
        include: 'bus-refresh'

4.使用命令

作用:刷新消息总线

注意:在config-server服务器的地址中输入命令

 curl -X  POST htppt://ip名:客户端端口/actuator/bus-fresh 【回车后出现一个数组[]的内容,则表示成功】

Stream

定义

​ 一个SpringCloud的组件,是对消息中间件进一步的统一封装。构建消息驱动微服务应用的框架。

作用

​ 简化消息中间件的使用过程,使其标准统一。(JDBC也是一种对不同的数据库访问做的统一封装)。如果要更换消息中间件,可以无改动的实现与MQ和kafka的切换。因为Steam目前只对这两种中间件进行了封装

(由于要对消息中间件做不同程度的优化,所以在工作中会直接使用消息中间。【了解】)

Stream组成原理

在这里插入图片描述

使用binder绑定中间件服务Middleware,通过input读取消息,再使用output发送消息。通过NIO中的channel来通信,每一个channel就是途中的一个管道(input: source接口; output:sink接口)

Sleuth+Zipkin 链路追踪

定义与作用

​ sleuth是Sring Cloud的一个工具。根据捕获的数据,用Zipkin生成一个调用链的视图。

​ Zipkin是推特的一个开源项目。一款视图工具 ,把数据进行展示。

入门

服务端(zipkin)

java -jar  运行该zipkin的jar包
运行成功就可以进入  http://localhost:9411/ 

客户端(sleuth)

1.导zipkin包(其中已经依赖sleuth)
server:
  port: 9000

eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
spring:
  application:
    name: feign-consumer # 设置当前应用的名称。
    
    #以下是zipkin、sleuth配置信息
  zipkin:
    base-url: http://localhost:9411/  # 设置zipkin的服务端路径  在哪里找到zipkin

# sleuth的采样率(根据需求,批准请求能够进入zipkin内部转换为图表显示的占比)
  sleuth:
    sampler:
      probability: 1 # 采集率 默认 0.1 百分之十。

cloud:
config:
server:
# git 的 远程仓库地址
git:
uri: https://gitee.com/itheima_cch/itheima-configs.git
label: master # 分支配置

#配置rabbitmq信息
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /

将自己注册到eureka中

eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka

暴露bus的刷新端点

management:
endpoints:
web:
exposure:
include: ‘bus-refresh’




#### 4.使用命令 

作用:刷新消息总线

注意:在config-server服务器的地址中输入命令

```shell
 curl -X  POST htppt://ip名:客户端端口/actuator/bus-fresh 【回车后出现一个数组[]的内容,则表示成功】

Stream

定义

​ 一个SpringCloud的组件,是对消息中间件进一步的统一封装。构建消息驱动微服务应用的框架。

作用

​ 简化消息中间件的使用过程,使其标准统一。(JDBC也是一种对不同的数据库访问做的统一封装)。如果要更换消息中间件,可以无改动的实现与MQ和kafka的切换。因为Steam目前只对这两种中间件进行了封装

(由于要对消息中间件做不同程度的优化,所以在工作中会直接使用消息中间。【了解】)

Stream组成原理

[外链图片转存中…(img-G4YMfDB0-1602550851504)]

使用binder绑定中间件服务Middleware,通过input读取消息,再使用output发送消息。通过NIO中的channel来通信,每一个channel就是途中的一个管道(input: source接口; output:sink接口)

Sleuth+Zipkin 链路追踪

定义与作用

​ sleuth是Sring Cloud的一个工具。根据捕获的数据,用Zipkin生成一个调用链的视图。

​ Zipkin是推特的一个开源项目。一款视图工具 ,把数据进行展示。

入门

服务端(zipkin)

java -jar  运行该zipkin的jar包
运行成功就可以进入  http://localhost:9411/ 

客户端(sleuth)

1.导zipkin包(其中已经依赖sleuth)
server:
  port: 9000

eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
spring:
  application:
    name: feign-consumer # 设置当前应用的名称。
    
    #以下是zipkin、sleuth配置信息
  zipkin:
    base-url: http://localhost:9411/  # 设置zipkin的服务端路径  在哪里找到zipkin

# sleuth的采样率(根据需求,批准请求能够进入zipkin内部转换为图表显示的占比)
  sleuth:
    sampler:
      probability: 1 # 采集率 默认 0.1 百分之十。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值