SpringCloud:学习笔记

236 阅读7分钟

微服务架构

微服务主旨是将一个原本独立的系统拆分成多个小型服务,并且每个服务都能独立运行。 因为每个服务可以独立运行,所以都有属于自己的数据库。

SpringCloud

SpringCloud是一系列框架的有序集合,基于SpringBoog开发,需要版本对应。

Eureka

Eureka包含两个组件:EurekaServer(注册中心)EurekaClient(服务提供者、服务消费者)

基础使用:

1. 搭建Eureka-Server服务模块

  • 引入SpringCloud和eureka-server依赖
<dependencies>
        <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>
  • 创建配置文件Application.yml
server:
  port: 8761 #默认端口

#eureka 配置
eureka:
  instance:
    hostname: localhost #主机名
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka #eureka服务端地址
    register-with-eureka: false #是否将自己的路径注册到eureka上
    fetch-registry: false #是否要从eureka中抓取路径
  • 创建启动类,在启动类上添加注解@EnableEurekaServer启动模块
@SpringBootApplication
//启用EurekaServer
@EnableEurekaServer
public class EurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApp.class,args);
    }
}

2. 创建Provider和Consumer模块

  • 引入eureka-client依赖
<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  • 在启动类上添加@EnableEurekaClient注解,表示是客户端。(可省略)
  • 配置文件中添加Eureka相关配置,name配置是注册到eureka上的应用名称
server:
  port: 9000
eureka:
  instance:
    hostname: localhost #主机名
  client:
    service-url:
      defaultZone: http://eureka-server1:8761/eureka #eureka服务端地址
spring:
  application:
    name: eureka-consumer #设置当前应用的名称,会在eureka中显示。将来需要使用该名称获取路径

3. Consumer服务从eureka中抓取Provider地址完成远程调用

  • 在要抓取地址的类中注入DiscoveryClient对象,调用其方法获得host和port,拼接成url
@Autowired
    private DiscoveryClient discoveryClient;
    
 //从eureka中获取provider数据
 //名称是Provider服务注册到Eureka上的应用名称
        List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");
        
        ServiceInstance instance = instances.get(0);
        String host = instance.getHost();//获取ip
        int port = instance.getPort();//获取端口
        String url = "http://"+host+":"+port+"/goods/findOne/"+id;
        restTemplate.getForObject(url, Goods.class);

Eureka自我保护机制

如果Eureka在15分钟内未收到超过85%客户端节点的正常心跳,则开启自动保护。保护期间不剔除任何一个服务,但可接收新服务的注册,等到网络稳定时将新服务同步到其他服务中。
Eureka中默认开启自我保护机制,可通过配置文件将其关闭

eureka:
  server:
    enable-self-preservation: false #关闭自我保护机制

Eureka高可用

Eureka将自己作为服务注册到其他的Eureka上,进行相互注册。实现客户端数据的共享,避免单个Eureka异常导致整体无法运行。

Ribbon客户端负载均衡

Ribbon是基于Http和TCP的客户端负载均衡工具
功能:

  • 简化远程调用
  • 负载均衡

简化远程调用

  1. 在RestTemplate的Bean注解上添加@LoadBalance注解
@Configuration
public class RestTemplateConfig {
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
  1. 编写provider的url地址时直接使用Eureka中的应用名代替host:port处
String url = "http://FEIGN-PROVIDER/***";

负载均衡

客户端对于服务端集群调用规则

负载均衡策略:

  • 随机
  • 轮询
  • 最小并发
  • 过滤
  • 响应时间
  • 轮询重试
  • 性能可用性 设置负载均衡策略:
  1. 创建一个类作为负载均衡规则类。定义一个方法,返回值类型为IRule,方法内部直接返回上述负载均衡类型的对象。
  2. 在配置类中添加配置
user-service: #生产者服务名称
	ribbon:
    	NFloadBalancerRuleClassName:XXX #负载均衡类型
  1. 启动类上添加注解@RibbonClient(name="应用名称",configuration=自己创建的负载均衡规则类.class)

Feign声明式服务调用

  • Feign的时一个声明式的web service客户端,便于客户端的设置。
    使用方法
  1. Consumer客户端导入依赖
<!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  1. Consumer启动类上添加注解@EnableFeignClients,开启Feign的功能
  2. 创建Feign的声明接口。在接口类上添加注解@FeignClient,设置Value属性,值为Provider服务提供者的应用名称。接口方法的声明规则服务提供方接口保持一致
@FeignClient(value = "FEIGN-PROVIDER")
public interface GoodsFeignClient {


    @GetMapping("/goods/findOne/{id}")//自动会拼接为FEIGN-PROVIDER/goods/findOne/{id}
    public Goods findGoodsById(@PathVariable("id") int id);

}
  1. 调用Provider时直接注入Feign接口方法,调用其中方法。

    超时设置

    日志记录

Hystrix熔断器

  • Hystrix用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)。
  • Hystrix主要功能:
    • 隔离
    • 降级
    • 熔断
    • 限流 隔离
    1. 线程池隔离:给每个服务划分一个线程池
    2. 信号量隔离:给每个服务限制最多多少线程访问 降级
    3. 异常:当服务产生异常时,调用服务的降级方案,返回一个默认值
    4. 超时:当网络产生问题,连接超时时,客户端调用对该服务连接超时的降级方案 熔断
      当在某段时间内服务返回的异常超过其阈值,则产生熔断机制,停止对此服务的任何调用。熔断机制时间过去后,根据此服务运行是否还产生异常来判断是否恢复调用

    服务提供方降级

    1. 在服务提供方引入依赖
    <!-- hystrix -->
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
         </dependency>
    
    1. 定义降级方法
      • 方法返回值和原方法一致
      • 方法的参数值和原方法一致
      public Goods findOne_fallback(int id){
      Goods goods = new Goods();
      goods.setTitle("降级了~~~");
      
      return goods;
      }
      
    2. 在需要有降级方法上添加@HystrixCommand注解配置降级方法,属性fallbackMethod值为定义的降级方法名
     @GetMapping("/findOne/{id}")
     @HystrixCommand(fallbackMethod = "findOne_fallback")
    
    1. 启动类上添加@EnableCiruitBreaker注解开启Hystrix功能

    服务消费方降级

    1. 定义feign调用接口实现类,复写方法,即为降级方法
    2. 添加配置,开启hystrix服务
    # 开启feign对hystrix的支持
    feign:
    hystrix:
      enabled: true
    
    1. feign接口类上添加注解@FeignClient,属性Value指定对哪个服务降级,fallback指定降级类
    @FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
    

网关

  • 网关为微服务架构提供一种简单而有效的统一的API路由管理方式 使用方法
  1. 搭建网关模块,在网关模块中引入starter-gateway依赖。因为需要和eureka进行交互,所以得导入eureka依赖
<!--引入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>
  1. 配置文件
    • 将自己注册到Eureka中
    eureka:
    client:
      service-url:
        defaultZone: http://localhost:8761/eureka
    
    • 路由配置
    cloud:
    # 网关配置
    gateway:
      # 路由配置:转发规则
      routes: #集合。
      - id: gateway-provider
        # 动态路由,使用 uri:lb://应用名称 代替静态路径
        uri: lb://GATEWAY-PROVIDER # uri: 转发路径
        predicates: # predicates: 条件,用于请求网关路径的匹配规则
        - Path=/goods/**
      - id: gateway-consumer
        # uri: http://localhost:9000
        uri: lb://GATEWAY-CONSUMER
        predicates:
        - Path=/order/**
    

Gateway全局过滤器

  • 系统初始化时加载,作用在每一个路由上
  • 步骤:
    1. 定义类实现GlobalFilter和Ordered接口
      @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;
      }
    }
    

Config分布式配置中心

  • 用于管理分布式场景下的多配置文件管理和维护。配置信息改变时不需要重启即可更新配置信息到服务

基础操作

  1. 创建远程仓库。用的Gitee
  2. 搭建ConfigServer模块,导入Config-server依赖
<!-- config-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
  1. 编写启动类,添加@EnableConfigServer,启动configServer功能
  2. 编写配置文件,将自己注册到eureka中
 # spring cloud config
  cloud:
    config:
      server:
        # git 的 远程仓库地址
        git:
          uri: ***
      label: master # 分支配置
   eureka:
   client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  1. 在Provider和Consumer服务中导入starter-config依赖
<!--config client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
  1. 创建bootstrap.yml,配置Config server地址,读取远程配置文件
# 配置config-server地址
# 配置获得配置文件的名称等信息
spring:
  cloud:
    config:
      # 配置config-server地址
      uri: http://localhost:9527
      # 配置获得配置文件的名称等信息
      name: config 	# 文件名
      profile: dev 	# profile指定,config-dev.yml
      label: master 	# 分支
      # uri+name+profile+label自动组合为 http://localhost:9527/master/config-dev.ymml
      #从配置中心去寻找config-server地址
      discovery:
      	enable: true #是否从eureka中查找
        service-id: config-server #eureka中应用名称

  1. 获取远程配置文件时,使用@Value注入即可
@Value("${SpringCloud}")
    private String SpringCloud;

Bus消息总线

  • 使用消息中间件将分布式的节点连接起来。用于广播配置文件的更改。
  • 消息中间件可使用RibbitMQ和Kafka

基础使用

  1. 在provider和consumer中引入bus依赖:bus-amqp
 <!-- bus -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
  1. 在provider和consumer中的bootstrap配置RabbitMQ
spring:
  #配置rabbitmq信息
  rabbitmq:
    host: localhost
    port: 5672
    virtual-host: /
  1. 在config-server中的bootstrap设置暴露监控断点:bus-refresh
management:
  endpoints:
    web:
      exposure:
        include: '*'