一、SpringCloud简介

1.1SpringCloud简介

它是用来完成微服务开发的重要框架,我们做微服务会有各种问题,SpringCloud就提供了各种组件来解决这些问题组件,SpringCloud没有重复造轮子,而是将各个厂商已经开发好的服务框架,拿过来进行整合,利用SpringBoot屏蔽了复杂的配置,从而简化了分布式系统的基础设施的开发,如服务的注册和发现,配置中心,消息总线,负载均衡、断路器、数据监控等。(所以SpringCloud就是提供了一系列的微服务开发组件
SpringCloud简介.jpg

1.2SpringCloud版本要求

SpringCloud采用伦敦地铁站的命名方式(GA表示稳定版本类似于release),通过首字母的字典顺序表示版本的时间循序,例如最早的版本是Angel,第二release版本是Brixton版本等
注意SpringCloud是基于SpringBoot进行开发,所以SpringBoot的版本要和SpringCloud的版本对应
SpringBoot和SpringCloud版本对应表.jpg

1.3SpringCloud和Dubbo对比

SpringCloud和double的对比.jpg
Springcloud他和Dubbo都是实现微服务的有效工具,但是dubbo只提供了服务治理,而SpringCloud除了服务治理还提供其他的服务主键,例如熔断器,网关等
SpringCloud服务调用的方式是RestFul风格的,是基于Http协议的,而Dubbo的调用方式是RPC,它的底层是使用Scoket,Socket它是底层协议,效率更高

二、SpringCloud服务组件


2.1、SpringCloud服务治理组件—服务治理介绍

我们通过注册中心来完成服务治理的功能,也就是说这些组件是用来当做注册中心,实现服务治理,我们将服务注册到注册中心去,服务的调用方去注册中心发现服务,这样如果服务的IP和端口变了,但是注册到注册中心时都是统一的服务,调用方不用变,实现解耦

  • Eureka

Eureka介绍.jpg
Eureka注册中心需要导入Server坐标自己搭建,需要注册和发现的服务需要导入Client坐标

  • Consul
  • Nacos

    三、Eureka的使用

    3.1、RestTemplate的使用

    RestTemplate它是Spring提供的简单便捷的模板类,用于在java代码里访问restFul风格的服务,也就是发送Http请求,他是用来发送Http请求的工具类,它的功能和HttpClient工具类功能类似,但是比它使用起来更加方便
    使用步骤:
    1.配置RestTemplate作为Bean交给Spring管理
    2.注入Bean使用
    3.调用方法发送请求
    RestTemplate提供了很多RestFul风格的方法,根据请求类型,调用对应方法,可以返回对应的实体

    3.2、EurekaServer的搭建(注册中心)

    第一步导入坐标
    SpringCloud有很多组件,他们的坐标版本我们需要同一控制,所以需要在父工程导入SpringCloud的版本控制坐标
    1. <dependencyManagement>
    2. <dependencies>
    3. <dependency>
    4. <groupId>org.springframework.cloud</groupId>
    5. <artifactId>spring-cloud-dependencies</artifactId>
    6. <version>Greenwich.RELEASE</version>
    7. <type>pom</type>
    8. <scope>import</scope>
    9. </dependency>
    10. </dependencies>
    11. </dependencyManagement>
    在EurekaServer中导入坐标
      <dependencies>
    <!--        SpringBoot-web的坐标-->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
    <!--Eureka-Server的坐标-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
          </dependency>
      </dependencies>
    
    第二步:编写启动类,注意EurekaServer一定要加@EnableEurekaServer注解,表示开启EurekaServer功能
    @SpringBootApplication
    //开启EurekaServer服务
    @EnableEurekaServer
    public class EurekaApplication {
      public static void main(String[] args) {
          SpringApplication.run(EurekaApplication.class,args);
      }
    }
    
    第三步:便器配置文件 ```yaml server: port: 8761

Eureka的配置

Eureka的配置一共有4个方面

dashboard(控制台配置),Eureka的图形化界面可以看到注册上面的服务

server:Eureka服务端的配置

client:Eureka客户端的配置

instance:eureka实例的配置

eureka: dashboard: enabled: true #是否开启控制台默认是true path: /test #eureka控制的虚拟目录,默认是/, instance: hostname: localhost #主机名 client: service-url: defualtZone: http://${server.port}:${eureka.instance.hostname}/eureka

  #defualtZone: http://localhost:8761/eureka #这是将来client注册到EurekaServer的地址(http://主机名:端口号)
  #eureka服务默认值也是http://localhost:8761/eureka
fetch-registry: false #是否从Eureka中抓取路径,默认是true,EurekaServer不需要抓取
registry-with-eureka: false #是否将自己注册到Eureka,默认是true,但是只有客户端才注册,服务端不需要注册
启动项目即可,Eureka的项目访问路径默认是localhost:8761
<a name="AG7Bq"></a>
#### 3.3EurekaClient客户端的搭建(服务治理)
第一步:导入坐标
```xml
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

<!--        eurekaClient的坐标-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

第二步:开启EurekaClient服务,在启动类加上注解

package com.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

/**
 * @author zbw
 * @describe
 * @email 1030184932@qq.com
 * @create 2021-10-18-22:10
 */
@SpringBootApplication
//开启EurekaClient服务注解,新版本可以省略,GreenWich
@EnableEurekaClient
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

第三步:编写配置类

server:
  port: 8000

eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defualtZone: http://localhost:8761/eureka #eurekaServer配置服务地址

spring:
  application:
    name: testName #配置当前应用的名称,注册到Eureka时,控制台显示的就是这个名称,这个名称很重要,将来服务调用时,需要使用这个名字来获取服务地址

3.4、获取注册到EurekaServer服务上的IP端口等信息

使用DiscoveryClient对象需要在启动类上加@EnableDiscoveryClient注解,来激活对象,新版本可以省略

package com.study.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author zbw
 * @describe
 * @email 1030184932@qq.com
 * @create 2021-10-18-22:15
 */

@RestController("/test")
public class GoodController {

    //注意这个对象使用的SpringCloud提供的
    @Autowired
    private DiscoveryClient discoveryClient;

    @PostMapping("/test")
    public void test(){
        List<ServiceInstance> testApp = discoveryClient.getInstances("testApp");
        ServiceInstance instance = testApp.get(0);
        String host = instance.getHost();
        int port = instance.getPort();
    }
}

3.5、Eureka的相关配置(见文档服务配置)

常用的EurekaServer服务配置(instance)

eureka:
  instance:
    hostname: localhost #主机命
    prefer-ip-address: true #是否将客户端IP注册到Eureka中,默认是false,如果是false那么注册的是主机名,内网环境设置主机名就可以了,但是如果是公网环境需要配置IP地址,因为我们需要通过公网环境访问Eureka的客户端
    ip-address: #这个是配置prefer-ip-address使用的,我们将prefer-ip-address配置成true但是服务器可能不止一个网卡,所以有很多IP,Eureka官方文档指出注册的是非本地回环地址(127.0.0.1),第一个IP
    #但是这个第一个IP可能是内网的IP,所以会出错,这时我们可以通过ip-address来指定注册到Eureka上的IP,可以手动配置公网IP
    instance-id: #修改instanceId显示,控制台默认显示的主机名:+applicationName+端口,在实际生产中我们不显示主机名,都是
    #显示IP地址+applicationName+端口号
    lease-expiration-duration-in-seconds: 30 #每多少秒EurekaClient向Server发送心跳包
    lease-renewal-interval-in-seconds: 90 #多少秒Eureka-server没有收到心跳包,则剔除该服务

常用的EurekaServer服务配置(server)

eureka:
    server:
    #是否开启Eureka的自我保护,如果服务没有发心跳包,Eureka也不会剔除服务进入保护模式,生产环境需要开启,开发时需要关闭
    enable-self-preservation: true
    #清理的时间间隔
    eviction-interval-timer-in-ms: 60000

3.6、Eureka高可用(集群的搭建)

高可用要保证各个集群节点的数据是一样的
步骤一、
准备两个或多个EurekaServer
步骤二、
相互注册(如果有多个,要注册到每一个节点上去)
步骤三、
EurekaClient分别注册到EurekaServer
最重要的就是相互注册,即EurekaServer要把自己的地址注册到其他的节点

eureka:
  client:
      service-url:
        defualtZone: http://localhost:8761/eureka #eurekaServer配置服务地址,如果有多个中间用逗号隔开

同时主机名不能是一样的,否则无法构成集群

四、Consul注册中心

consul简介.jpg
直接下载安装包然后启动即可 启动命令:consul agent -dev 表示使用开发环境
控制台是localhost:8500
使用步骤:

1.导入坐标:springboot监控的坐标是必须要导入的

<!--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-actuator</artifactId>
        </dependency>

第二步:配置客户端注册到Consul的配置

spring:
  cloud:
    consul:
      host: localhost #consul服务的IP
      port: 8500 #consul服务的端口
      discovery:
        service-name: testName #注册到Consul的服务名称,将来用来获取信息
        prefer-ip-address: true #是否注册IP
  application:
    name: testName

第三步:通过DisconverClient对象使用

使用和Eureka的使用是一样的激活DiscoverClient对象,更具服务名称获取实例对象,然后获取IP和端口进行调用

五、Nacos注册中心(配置中心)

5.1、nacos简介

nacos简介.jpg
他的使用可以在官网中去查看,更加的全面
使用和上面相同也是通过@DiscoverClient对象来进行调用使用

六、客户端负载均衡

负载均衡介绍.jpg
ribbon是客户端负载均衡工具,ngix是服务端负载均衡工具,区分是客户端还是服务端负载均衡就看负载均衡算法和服务地址列表有谁维护,ribbon可以作为负载均衡器,同时可以简化远程调用

6.1、ribbon简化远程调用

在我们使用EurekaClient的时候,坐标包含ribbon,所以我们不需要导入坐标,使用的时候,在创建restTamplate的Bean对象时加上@LoadBalanced注解,在使用RestTemplate对象进行远程调用的时候将url位置换成注册到注册中的服务名集合

6.2、ribbon实现负载均衡

ribbon的负载均衡策略.jpg
我们在使用ribbon在做远程调用的时候,默认使用的策略是轮询,同时Ribbon还提供其他的负载均衡策略
策略介绍:
过滤:会将挂掉的节点剔除不再调用
响应时间:ribbon会给节点丢一个很小的数据包,谁先响应访问谁
轮询重试:轮询默认是轮询10次,如果第一个挂了会找第二个,如果10个都没有响应就会响应失败,轮询重试是在重新轮询一次

6.3、配置ribbon的负载均衡

方式一、编码的方式
步骤一:配置Bean均衡策略的Bean

package com.study.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zbw
 * @describe
 * @email 1030184932@qq.com
 * @create 2021-10-24-21:08
 */
@Configuration
public class MyRule {

    /**
     * 这个IRule是所有策略的顶级接口
     * @return
     */
    @Bean
    public IRule rule(){
        //使用随机的负载均衡策略
        return new RandomRule();
    }
}

步骤二:在启动类上声明这个策略是针对那个服务的(因为有多个服务都会搭建集群,要声明给那个服务使用的)

package com.study;

import com.study.config.MyRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

/**
 * @author zbw
 * @describe
 * @email 1030184932@qq.com
 * @create 2021-10-18-22:10
 */
@EnableDiscoveryClient
@SpringBootApplication
//开启EurekaClient服务注解,新版本可以省略,GreenWich
@EnableEurekaClient
//name表示给那个服务集群使用,写服务的应用名,configuration表示使用那个策略
@RibbonClient(name = "testApp",configuration = MyRule.class)
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

方式二、配置的方式

server:
  port: 8845

testApp: #这个指定的是服务的应用名,即要给那个服务配置这个策略
  ribbon:
    NFloadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #要配置策略全类名

七、声明式服务调用-feign

7.1、feign的概述

feign的概述.jpg

7.2、Feign的使用

第一步:引入依赖

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

第二步:编写feign的调用接口

package com.study.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

/**
 * @author zbw
 * @describe
 * @email 1030184932@qq.com
 * @create 2021-10-24-21:51
 */
//value表示服务提供方的应用名
@FeignClient(value = "testApp")
public interface TestFeignClients {

    //提供的声明式接口和服务的提供方接口保持一致
    @PostMapping("/findOne/{id}")
    public void test(@PathVariable("id") Long id);
}

第三步:在启动类上加@EnableFeignClients注解,开启Feign功能
第四步:测试调用
注入我们编写的声明式接口,调用方法
注意:Feign的远程调用底层是依赖Ribbon进行服务调用,所以Ribbon的功能Feign都是有的(远程调用和负载均衡)

7.3、Feign的超时设置

客户端调用服务端服务使用Feign,默认是等待1秒,如果一秒后没有接收到响应就算超时,我们可以根据实际业务来配置超时时长,feign它底层是依赖于ribbon,所以我们对ribbon进行配置超时时长,fegin就是这样的配置

server:
  port: 8080

ribbon:
  ConnectTimeout: 1000 #连接超时时长,客户端与服务端建立连接默认是1秒
  ReadTimeout: 3000 #逻辑连接时长,也就是获取数据的超时时长,默认也是1秒

7.4、Feign的日志记录

Feign的远程调用是通过发送请求的方式,Feign提供了抓请求中的数据包的功能,实现调用监控的功能
注意:Feign只能监控Debug级别的日志
开启feign日志.jpg
Logger.Level一共有四个值:NONE表示不记录,BASIC只记录基本的请求行,和响应状态码,HEADERS记录BASIC在加头信息,FULL表示记录完整的请求响应数据

八、Hystrix熔断器

注意:在微服务中,由于各个服务之间相互调用,极容器出现级联调用失败,导致雪崩现象的发生,Hytrix提供相关功能可以预防雪崩现象的发生,我们在服务调用一般都是返回一个Result对象,里面有code、message等,对于调用失败的服务方法可以根据业务返回code

8.1简介

Hystrix是NetFilx公司开源的一个延迟和容错库,用于隔离访问远程服务,第三方库,防止级联失败(雪崩)
级联失败:在微服务中各个服务相互调用,如果一个服务挂了,导致其他调用服务失败,以此类推导致所有服务都挂了,出现雪崩现象

8.2Hystrix的功能

  • 隔离

1.线程池隔离:在进行服务调用的时候,会从线程池里取一个线程去调用,如果失败了线程没有还回来,还是继续取新的线程继续调用导致线程池耗尽,线程池隔离就可以给每个服务规定线程,超过这个线程就不会分配新的线程,这样其他服务就不会受到影响,Hystrix默认的是线程池隔离
2.信号量隔离:给单个服务设置访问次数(并发次数??)进行限制,超过这个次数就不允许访问

  • 降级

在微服务中,服务之间的调用肯定会存在调用失败或者调用超时的情况,作为服务的开发者应该要提前想到调用失败的情况,所以我们要针对这个失败的调用提供一个降级的方案,即一个友好的提示或者默认值,服务的调用方能收到降级方案的前提是网络通畅,如果网络不通畅,不仅调用会失败,而且也收不到降级方案,所以服务的调用方 也需要提供降级方案

  • 熔断

在一定时间内,服务的提供方一直没法调用成功,那么Hystrix就会启动熔断机制,会隔离该服务所有的接口,过时间可以恢复接口功能

  • 限流

限流的功能就相当于隔离,需要配置

8.3、服务端降级方案

Hystrix会对异常和超时的服务走降级方法,默认的超时时长是1秒

  • 引入Hystrix坐标

        <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
          </dependency>
    
  • 提供服务端降级方案方法

注意:这个降级方法要求,方法的参数和返回值都要和原方法一样(需要降级的方法),

  • 使用@HystrixCommand来引用降级方法,fallbackMethod用来指定失败后调用的降级方法

@HystrixCommand(fallbackMethod = “降级方法名”),当服务调用出异常或者超时(默认是1秒),那么就会走降级方法,
@HystrixCommand(fallbackMethod = “test”,commandProperties={@HystrixProperty(name = “execution.isolation.thread.timeoutInMilliseconds”,value = “3000”)})
该注解的属性:
fallbackMethod:降级方法名
commandProperties:配置超时时长或者其他的,可以通过CommandProperties这个类来查询相关属性配置

  • 在启动类上加@EnableCircuitBreaker,来开启熔断器

    8.4、客户端降级

    客户端降级可以和服务端一模一样的去写,可以正常执行,但是一半客户端都是使用Feign组件进行调用,Feign内部集成了Hystrix,所以我们可以简化客户端降级(可以不用引入Hystrix的依赖)
    Feign调用的降级步骤:

  • 我们Feign的调用是基于接口的,我们只需要书写接口的实现类(该实现类一定要加入到Spring的IOC容器中),然后给对应抽象方法提供实现,那么实现的方法就是降级方法

  • 配置开启Feign的服务降级feign.hystrix.enabled=true
  • 在@FeignClient注解中指定实现类,fallback=类名.class

    8.5、Hystrix的熔断

    Hystrix熔断机制,用于监控服务的调用情况,当失败情况达到预定的阈值(默认是5秒失败20次),会打开断路器,拒绝所有的请求,直到服务恢复为止
    断路器工作机制.jpg
    Hystrix导入坐标默认就是开启熔断器,降级也算是调用失败,虽然会有降级结果,但是超过熔断器阈值也会熔断,服务一旦熔断就会拒绝所有的请求
    熔断器的配置也是@HystrixCommand里的属性配置
    @HystrixCommand(fallbackMethod = “test”,commandProperties={
    @HystrixProperty(name = “execution.isolation.thread.timeoutInMilliseconds”,value = “3000”),
    //默认失败时间5秒
    @HystrixProperty(name = “circuitBreaker.sleepWindowInMilliseconds”,value = “5”),
    //默认失败次数20次
    @HystrixProperty(name = “circuitBreaker.requestVolumeThreshold”,value = “20”),
    //默认失败百分比50%
    @HystrixProperty(name = “circuitBreaker.errorThresholdPercentage”,value = “50”)
    })

    8.6、Hystrix熔断监控

  • Hystrix监控:提供hystrix-dashboard的功能用于实时监控微服务的运行状态

  • 但是Hystrix只能监控一个微服务
  • NetFliex公司还提供了Turbine,实现聚合监控

Turbine实现监控,Turbine也是一个服务,需要我们自己搭建服务进行监控
补:

九、gateway网关

9.1、简介

网关旨在为服务架构提供一种简单有效而有效的统一的API管理方式
在服务架构中,前端需要调用的数据可能在多个微服务中,如果前端挨个去调用,前端复杂度变高,而且需要发送多次请求,前端性能不高。在微服务认证中,每个微服务都需要写认证规则,认证复杂。
网关出现可以解决这些问题
实现网关的方式:
nginx+lua脚本,netfilx公司的zuul,SpringCloud gateway

9.2、网关服务配置-静态路由

网关配置静态路由:
由于uri是写死的,所以这是静态路由的配置

server:
  port: 80
spring:
  application:
    name: gateway-server

  #springcloud的配置
  cloud:
    #网关的配置--静态路由配置(uri是写死的)
    gateway:
      #网关路由的配置,配置路由规则
      routes: #routes的配置需要一个集合,
        #配置id,唯一表示,入股不配置,默认是是UUID
        - id: consumer-server
          uri: http://localhost:8081/ #配置uri:转发路径,也就是要转发给那个服务,所以这里写服务地址
          predicates: #配置predicates:
          - Path: /goods/**  #用于请求网关路径的规则,也就是如果请求网关路径uri中去掉IP和端口剩下的是uri,和这个-Path匹配了就说明满足规则
              #那么就会把path评上uri就是路由的地址
        #由于配置网关,所有的请求都会请求网关,所以而网关会根据请求的uri和配置的predicates中的path进行匹配,如果满足规则,就会找到对应规则的uri拼上请求的uri得到
        #一个新的地址,就是路由地址,也就是说网关这边uri维护的是服务的地址,我根据你请求的uri配置规则,满足规则,就说明你要请求这个服务,就把这个服务的地址拼上你请求的
        #uri,得到路由地址,将请求路由过去,所以path最好写项目的虚拟路径
       #第二服务配置
        - id: consumer-provider
          uri: http://localhost:8081/ #配置uri:转发路径,也就是要转发给那个服务,所以这里写服务地址
          predicates: #配置predicates:
          - Path: /order/**

9.3、网关服务配置-动态路由

静态路由配置的缺点就是服务地址是写死的,一旦服务地址发生改变,网关需要改变,服务的地址,eureka知道,所以让网关成为eureka的客户端就可以从eureka中拉取服务地址实现动态路由
实现方式:让网关成为eureka的客户端,然后改变uri的配置让它从eureka中拉取配置

server:
  port: 80
spring:
  application:
    name: gateway-server

  #springcloud的配置
  cloud:
    #网关的配置--静态路由配置(uri是写死的)
    gateway:
      #网关路由的配置,配置路由规则
      routes: #routes的配置需要一个集合,
        #配置id,唯一表示,入股不配置,默认是是UUID
        - id: consumer-server
#          uri: http://localhost:8081/ #配置uri:转发路径,也就是要转发给那个服务,所以这里写服务地址
          uri: lb://USER-CONSUMER  #这里不区分大小写
          predicates: #配置predicates:
          - Path: /goods/**  #用于请求网关路径的规则,也就是如果请求网关路径uri中去掉IP和端口剩下的是uri,和这个-Path匹配了就说明满足规则
              #那么就会把path评上uri就是路由的地址
        #由于配置网关,所有的请求都会请求网关,所以而网关会根据请求的uri和配置的predicates中的path进行匹配,如果满足规则,就会找到对应规则的uri拼上请求的uri得到
        #一个新的地址,就是路由地址,也就是说网关这边uri维护的是服务的地址,我根据你请求的uri配置规则,满足规则,就说明你要请求这个服务,就把这个服务的地址拼上你请求的
        #uri,得到路由地址,将请求路由过去,所以path最好写项目的虚拟路径
        #网关动态路由的配置--eureka
        - id: consumer-provider
#          uri: http://localhost:8081/ #配置uri:转发路径,也就是要转发给那个服务,所以这里写服务地址
          uri: lb://GOODS-CONSUMERS #这里写lb://后面加的是eureka的注册的服务名
          predicates: #配置predicates:
          - Path: /order/**

#eureka的配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

9.4、微服务名称的配置

我们在访问网关的时候多个服务存在,请求地址上没法区分,如果服务多了,会出现问题这个时候就需要在请求网关的时候可以加上路由目标的服务名,这样就可以区分服务,且网关也不会将这个名称进行路由规则匹配
添加方式:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #设置为true表示请求地址可以添加服务名
          lower-case-service-id: true #允许为小写(服务名是大写,加上这个配置可以使用小写请求地址)

这样在请求地址后加上请求的服务名,依然可以正常请求,不加也行

9.5、网关的过滤器

gateway支持过滤的功能,他可以对请求进行拦截,完成一些通用的操作
gateway提供两种过滤器:pre(前置过滤器)和post(后置过滤器)

  • pre过滤器:转发之前执行,可以做参数校验,权限校验,流量监控,日志输出,协议转换等
  • post过滤器:在响应之前执行,可以做响应头响应内容的修改,日志输出流量监控等

gateway可以提供:全局过滤器(所有链路)和局部过滤器(针对单个链路)

9.6、gateway的局部过滤器(GatewayFilter)

GatewayFilter是局部过滤器,针对单个链路进行过滤操作,SpringCloudGateWay提供大量的局部过滤器
过滤器的使用是基于约定大于配置的思想,只需要在配置文件指定过滤器名称,并指定响应的值就可以生效

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #设置为true表示请求地址可以添加服务名
          lower-case-service-id: true #允许为小写(服务名是大写,加上这个配置可以使用小写请求地址)
      routes:
      - id: test
        uri: http://localhost:8089/
        predicates:
        - Path=/good/**
        filters: #配置局部过滤器,他是一个集合,下面填的是SpringCloud提供的局部过滤器名
        - AddRequestParamter=username,password #添加请求参数key=username value=password

这是配置的局部过滤器,实在某个路由规则下(predicates)配置的过滤器,所以这个过滤器只针对这个路由规则有效
局部过滤器可以自定义,但是官方提供的很全面的局部过滤器,当不满足使用的时候可以自己自定义全局过滤器

9.7、gateway的全局过滤器(GlobalFilter)

全局过滤器不需要在配置文件中配置,系统初始化的时候加载,针对所有路由都生效
SpringCloudGateway的核心功能也是通过多个核心过滤器完成的
自定义全局过滤器:

  • 定义一个类实现GlobalFilter和Ordered接口
  • 复写方法完成逻辑 ```java package com.study.studygateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;

@Component public class MyGlobalFilter implements GlobalFilter, Ordered { /**

 * |
 * GlobalFilter中的方法
 *
 * @param exchange:这个对象封装了请求对象可以对请求做处理
 * @param chain:这个对象用来放行
 * @return
 */
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpRequest request = exchange.getRequest();
    return chain.filter(exchange);//方法的操作,如果不调用filter()方法将这个参数传进去,那么就是不放行
}

/**
 * Ordered中的方法,用来过滤器排序的
 *
 * @return,返回值数值越小越先执行,0为最小值
 */
@Override
public int getOrder() {
    return 0;
}

}

**注意:自定义的全局过滤器需要加入IOC容器才能生效**
<a name="S63Ep"></a>
### 十、Config分布式配置中心
<a name="LgusF"></a>
#### 10.1、简介
SpringCloudConfig解决了分布式场景多环境配置文件的管理和维护,可以实现不需要重启服务即可更新服务配置,他和EurekaServer类似,也是需要我们搭建服务端,我们可以将配置文件放入远程仓库(gitee或者gitlab等),这个Config配置中心可以做到向远程仓库动态拉取配置,连接configServer的服务动态的更新服务,我们在上传配置文件到远程仓库时,这里的文件名应该是名字+环境,例如server-dev.yml(表示server这个服务的开发环境配置),这个在拉取的时候只需要写服务的名称,后面的-和环境名可以省略
<a name="spceP"></a>
#### 10.2、configServer服务搭建

- 导入坐标
```xml
    <dependencies>
      <!--configServer的坐标-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
    </dependencies>
<!--SpringCloud的版本控制坐标-->
    <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>
  • 启动类上加@EnableConfigServer注解,来开启ConfigServer
  • 写配置

    spring:
    cloud:
      #SpringCloudConfig的配置
      config:
        server:
          #git仓库的配置,这里填写的是https的地址
          git:
            uri: https://gitee.com/zhubowen1214/changgou.git
            username: test
            password: test
        label: master #配置拉取远程仓库的分支
    

    启动Server服务即可拉取配置,(可以通过访问搭建的configServer服务的地址/master/配置文件名来确定是否拉取成功)

    10.3、ConfigClient搭建

    搭建ConfigServer,可以去远程仓库拉取配置,其他微服务可以作为config的客户端去拉取配置文件,
    Config客户端的搭建

  • 导入坐标

    <!--configClient的坐标-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-config</artifactId>
          </dependency>
    
  • 编写配置文件,配置ConfigServer的地址(这里的配置文件名需要时bootstrap.yml)

    spring:
    cloud:
      config:
        #configServer的服务地址
        uri: http://localhost:9548
        name: config  #这里是要拉取的文件名(这个名字是去掉环境后的,例如文件名是test-dev.yml,那么这里应该是test
        profile: dev #指定环境,config会自动将name和profile拼接config-dev.yml
        label: master #指定分支名
    

    这样客户端就可以拿到配置文件,就相当于配置文件已经配置了这些信息,可以在其他地方进行引用或者使用@Value注入
    当git仓库配置发生变化,ConfigServer会获取配置,但是ConfigClient不会动态的拉取配置

    10.4、ConfigClient刷新配置

  • 客户端引入actuator坐标

  • 在需要刷新配置的类上加@RefreshScope注解
  • 监控平台暴露一个端点

    management:
    endpoints:
      web:
        exposure:
          include: refresh
    
  • 发送post请求到 http://客户端IP:端口:/actuator/refresh

    10.5、config集成eureka

    我们搭建configServer服务时,configclient需要去连接Server,在配置中写ConfigServer的地址是写死的,这样耦合度太高,可以将ConfigServer地址注册到Eureka中,这样可以动态的从EurekaServer获取ConfigServer的服务地址
    配置方式,将configServer注册到EurekaServer上:

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

    ConfigClient也是将自己注册到Eureka中,然后去Eureka中拉取服务地址

    spring:
    cloud:
      config:
        #configServer的服务地址
    #      uri: http://localhost:9548  这里不需要写configServer的uri了
        name: config  #这里是要拉取的文件名(这个名字是去掉环境后的,例如文件名是test-dev.yml,那么这里应该是test
        profile: dev #指定环境,config会自动将name和profile拼接config-dev.yml
        label: master #指定分支名
        #从Eureka中动态拉取configServer地址,
        discovery:
          enabled: true
          service-id: config-server #这是注册到EurekaServer上的ConfigServer的应用名称
    

    十一、Bus消息总线

    11.1、简介

    SpringCloudBus用轻量的消息中间件将分布式节点连接起来,可以用于广播配置文件的更改或服务的监控管理。关键的思想就是消息总线可以为微服务做监控,也可以实现程序之间的相互通信
    SpringCloudBus可选的消息中间件有rabbitMQ和kafka
    SpringCloudBus使用RabbitMQ它会在MQ自动创建一个topic类型的交换机

    11.2、Bus的配置

    bus内部将RabbitMQ封装好了,他需要我们自己写代码实现,只需要在需要发消息和接消息的服务上引入Bus的坐标然后配置即可

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

    configServer的配置,配置rabbitMq(发送消息到MQ)

    spring:
    cloud:
      config:
        #configServer的服务地址
    #      uri: http://localhost:9548  这里不需要写configServer的uri了
        name: config  #这里是要拉取的文件名(这个名字是去掉环境后的,例如文件名是test-dev.yml,那么这里应该是test
        profile: dev #指定环境,config会自动将name和profile拼接config-dev.yml
        label: master #指定分支名
        #从Eureka中动态拉取configServer地址,
        discovery:
          enabled: true
          service-id: config-server #这是注册到EurekaServer上的ConfigServer的应用名称
    rabbitmq:
      host: localhost #rabbitmq地址
      port: 5682  #rabbitMQ端口
      username: guest #用户名
      password: guest #密码
      virtual-host: /  #虚拟机
    

    注意configServer需要暴露bus-refresh断点,这是actuator的功能需要引入坐标配置

    management:
    endpoints:
      web:
        exposure:
          include: "bus-refresh"
    

    configClinet需要接收RabbitMQ的消息,所以mq的配置和configServer一样

    spring:
    rabbitmq:
      host: localhost #rabbitmq地址
      port: 5682  #rabbitMQ端口
      username: guest #用户名
      password: guest #密码
      virtual-host: /  #虚拟机
    

    十二、stream消息驱动

    12.1、简介

    springCloudStream是构建消息驱动的微服务框架,Stream对消息中间件进行封装,可以做到代码层对中间件无感知,甚至动态的切换消息中间件,实现微服务和消息中间件解耦
    但是目前Stream只支持RabbitMQ和kafka两种MQ
    略(….)

十三、Sleuth+Zipkin链路追踪

13.1、简介

SpringCloudSleuth是一个工具,它在整个分布式系统中能追踪一个用户请求的过程,捕获这些跟踪数据,就能构建微服务的整个调用链视图,可以用来调试和监控微服务的工具
例如:在一个请求和响应过程很慢,整个时候可以通过这个工具分析是调用链的那个调用耗时最多,从而快速定位
功能:

  • 耗时分析
  • 错误可视化
  • 链路优化

Zipkin是一个twitter的一个开源项目,它致力于收集服务的定时数据,已解决微服务架构中的延迟问题,包括收据的收集、存储、展现、查找
总结:通过sleuth来收集用户请求链路数据,通过zipkin来展示

13.2、zipkin的安装

zipkin就是一个jar包,去下载jar包,然后通过java -jar 来启动即可
通过localhost:9411/来访问

13.3配置sleuth

  • 引入sleuth和zipkin的坐标(消费方和服务方都需要引入),注意SpringCloud的版本,2版本以上没有对应的SpringCLoudZipkin ```xml org.springframework.cloud spring-cloud-starter-sleuth org.springframework.cloud spring-cloud-starter-zipkin 2.2.8.RELEASE

SpringCloud可以只引用这一个坐标 org.springframework.cloud spring-cloud-sleuth-zipkin

zipkin中包含了sleuth的坐标,所以sleuth的坐标可以不用引用
```yaml
spring:
  zipkin:
    base-url: http://localhost:9411/ #配置zipkin的服务的地址
  sleuth:
    sampler:
      probability: 1 #配置采集率默认是0.1(即百分之10),这里写1表示百分之百采集,性能损耗最严重

注意消费方和提供方都是这个配置,都需要这么配