20200523 尚硅谷2020最新版SpringCloud【笔记】1

尚硅谷2020最新版SpringCloud【笔记】1

2.从2.2.x和H版开始说起

技术 版本
Spring Cloud Hoxton.SR1
Spring Boot 2.2.2.RELEASE
Spring Cloud Alibaba 2.1.0.RELEASE

4.微服务架构编码构建

配置热部署Devtools

  1. 改 POM,添加依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    
  2. 在父工程中添加 Maven 插件

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.2.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
  3. IDEA 设置

    1. File | Settings | Build, Execution, Deployment | Compiler 中,全部勾选
    2. 快捷键 Ctrl+Shift+Alt+/ -> 1.Registry... -> 勾选 compiler.automake.allow.when.app.running 和 actionSystem.assertFocusAccessFromEdt
  4. 重启 IDEA

开启 Run Dashboard

Services 视图中添加 Run Configuration Type,选择 Spring Boot

遵循原则

约定 > 配置 > 编码

创建父工程 Project

创建步骤:

  1. New Project
  2. 聚合总工程名字
  3. Maven选版本
  4. 工程名字
  5. 字符编码
  6. 注解生效激活
  7. java编译版本选8
  8. File Type过滤(可选)

父工程 POM

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.springcloud</groupId>
    <artifactId>mycloud2020</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>cloud-provider-payment8001</module>
		...
    </modules>

    <!-- 统一管理jar包版本 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>

    <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version  -->
    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <optional>true</optional>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.2.RELEASE</version>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • 注意其中的 packaging 标签值为 pom

创建 cloud-provider-payment8001 微服务提供者支付Module模块,即生产者

创建步骤:

  1. 建 module,名为 cloud-provider-payment8001
  2. 改 POM
  3. 写 YML
  4. 主启动类
  5. 业务类

创建 cloud-consumer-order80 微服务消费者订单Module模块,即

工程重构

创建 cloud-api-commons Module模块

  1. 将重复代码放入此模块

  2. 打包此模块,maven命令clean install

  3. 在其他模块中删除重复代码,添加此模块依赖

    <dependency>
        <groupId>com.atguigu.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    

5.Eureka 服务注册与发现

定位

Eureka 类比物业公司,服务类比入驻企业

单机 Eureka 服务中心构建

  1. 建Module,cloud-eureka-server7001

  2. 改POM

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

    eureka:
      instance:
        hostname: localhost   # eureka服务端的实例名字
      client:
        register-with-eureka: false   # 表示不向注册中心注册自己
        fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        # 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
        service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    
  4. 主启动,添加 @EnableEurekaServer

业务模块配置 Eureka 客户端

  1. 改 POM

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

    eureka:
      client:
        # 表示是否将自己注册进EurekaServer默认为true。
        register-with-eureka: true
        # 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
        fetchRegistry: true
        service-url:
          defaultZone: http://localhost:7001/eureka
          # 集群版
          # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
    
  3. 主启动类,添加注解 @EnableEurekaClient

集群 Eureka 服务中心构建

  1. 新建 cloud-eureka-server7002 模块

  2. 修改 hosts 文件

    hosts 文件路径为 C:\Windows\System32\drivers\etc\hosts

    127.0.0.1       eureka7001.com
    127.0.0.1       eureka7002.com
    
  3. 改 YML

    eureka:
      instance:
        hostname: eureka7001.com		# eureka服务端的实例名字
      client:
        register-with-eureka: false   # 表示不向注册中心注册自己
        fetch-registry: false   #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        service-url:
    #    7001 配置 7002,7002 配置7001
         defaultZone: http://eureka7002.com:7002/eureka/
    
  4. 业务模块改 YML

    defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
    

生产者模块配置集群

  1. 复制生产者模块,cloud-provider-payment8002

  2. 注意 YML 配置中,应用名称保持一致

    spring:
      application:
        name: cloud-payment-service
    

消费者模块配置负载均衡

  1. 修改配置类

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
    
  2. 修改 Controller

    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
    
    return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    
  3. 测试负载均衡

actuator微服务信息完善

  1. 改 POM ,添加依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  2. 主机名称:服务名称修改

    eureka:
      instance:
      	# 服务实例 ID
        instance-id: payment8001
    
  3. 访问信息有ip信息提示

    eureka:
      instance:
      	# 访问路径可以显示IP地址
        prefer-ip-address: true
    

服务发现 Discovery

对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息

  1. 主启动类,添加注解 @EnableDiscoveryClient

  2. 业务代码

    @Autowired
    private DiscoveryClient discoveryClient;
    
    @GetMapping("/discovery")
    public Object discovery() {
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("service *** {}" + service);
    
            List<ServiceInstance> instances = discoveryClient.getInstances(service);
            for (ServiceInstance instance : instances) {
                log.error("instance *** {}", instance);
            }
        }
    
    
        return discoveryClient;
    }
    

Eureka自我保护

某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存

属于CAP里面的AP分支

禁止自我保护

  1. Eureka 服务中心配置

    eureka:  
      server:
        enable-self-preservation: false   # 关闭自我保护机制,保证不可用服务被及时踢除
        eviction-interval-timer-in-ms: 2000
    
  2. Eureka 客户端配置

    eureka:
      instance:
        # Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
        lease-renewal-interval-in-seconds: 1  
        #  Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
        lease-expiration-duration-in-seconds: 2   
    

6.Zookeeper服务注册与发现

结论

服务在 Zookeeper 中创建的是临时节点,一旦服务停止,一段时间后,节点被 Zookeeper 删除。

SpringCloud整合Zookeeper代替Eureka

注册中心Zookeeper

  1. 启动 Zookeeper

    1. 在 Windows 服务中开启 VMware DHCP Service 和 VMware NAT Service

    2. 关闭虚拟机中的防火墙

      systemctl stop firewalld.service
      
    3. 启动 Zookeeper

      # 启动服务
      ./zkServer.sh start
      # 验证状态
      ./zkServer.sh status
      # 启动客户端
      ./zkCli.sh
      

服务提供者

  1. 创建生产者服务

    1. 建 Module,cloud-provider-payment8004

    2. 改 POM

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

      如果启动时报错,可能是依赖的 ZooKeeper 的 jar 包与使用的 ZooKeeper 版本不一致,可以通过调整依赖解决:

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
          <!--先排除自带的zookeeper3.5.3-->
          <exclusions>
              <exclusion>
                  <groupId>org.apache.zookeeper</groupId>
                  <artifactId>zookeeper</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      <!--添加zookeeper3.4.9版本-->
      <dependency>
          <groupId>org.apache.zookeeper</groupId>
          <artifactId>zookeeper</artifactId>
          <version>3.4.9</version>
      </dependency>
      
    3. 改 YML

      #8004表示注册到zookeeper服务器的支付服务提供者端口号
      server:
        port: 8004
      
      
      #服务别名----注册zookeeper到注册中心名称
      spring:
        application:
          name: cloud-provider-payment
        cloud:
          zookeeper:
            connect-string: 192.168.181.128:2181
      
    4. 主启动类,添加注解 @EnableDiscoveryClient

  2. 验证

    1. 启动无报错
    2. Zookeeper 客户端中查看,会产生新的节点 servicesservices 下有 cloud-provider-payment 节点

服务消费者

  1. 建 Module ,cloud-consumerzk-order80
  2. 改 POM,同上
  3. 改 YML,同上
  4. 主启动类,同上
  5. 测试
    1. Zookeeper 客户端中查看,services 节点下有新的节点 cloud-consumer-order

7.Consul服务注册与发现

Consul简介

官网地址

功能

  • 服务发现
    提供HTTP和DNS两种发现方式
  • 健康监测
    支持多种协议,HTTP、TCP、Docker、Shell脚本定制化
  • KV存储
    key , Value的存储方式
  • 多数据中心
    Consul支持多数据中心
  • 可视化Web界面

安装并运行Consul

  1. 下载 Windows 64位程序;

  2. 查看版本信息

    .\consul.exe --version
    
  3. 使用开发模式启动

    consul agent -dev
    
  4. 访问Consul的首页

    http;//localhost:8500
    

服务提供者

  1. 建 Module,cloud-providerconsul-payment8006

  2. 改 POM

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
    
  3. 改 YML

    ###服务端口号
    server:
      port: 8006
    
    spring:
      application:
        name: consul-provider-payment
    ####consul注册中心地址
      cloud:
        consul:
          host: localhost
          port: 8500
          discovery:
            #hostname: 127.0.0.1
            service-name: ${spring.application.name}
    
  4. 主启动类,添加注解 @EnableDiscoveryClient

  5. 测试

    1. Consul 的图形化界面中出现新的 Service,consul-provider-payment

服务消费者

  1. 建 Module ,cloud-consumerconsul-order80
  2. 改 POM,同上
  3. 改 YML,同上
  4. 主启动类,同上
  5. 测试
    1. Consul 的图形化界面中出现新的 Service,cloud-consumer-order

三个注册中心异同点

组件名 语言 CAP 健康检查 对外暴露接口 Spring Cloud 集成
Eureka Java AP 可配支持 HTTP 已集成
Consul Go CP 支持 HTTP/DNS 已集成
ZooKeeper Java CP 支持 客户端 已集成

8.Ribbon负载均衡服务调用

概述

是什么

客户端 负载均衡 的工具

主要功能是提供客户端的软件负载均衡算法和服务调用

Ribbon目前也进入维护模式,未来可以使用 Spring Cloud LoadBalancer 替代

能干吗

LB(负载均衡)
  • 集中式LB

    即在消费方和服务方之间使用独立的 LB 设施

    例如 Nginx,Nginx 是服务器负载均衡,客户端所有请求都会交给 Nginx ,然后由 Nginx 实现转发请求。即负载均衡是由服务端实现的。

  • 进程内LB

    将 LB 逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后从这些地址中选择一个合适的服务器。

    Ribbon 本地负载均衡,在调用微服务接口时,会在注册中心上获取注册信息服务列表之后缓存到 JVM 本地,从而在本地实现 RPC 远程服务调用技术。

    负载均衡+RestTemplate调用

Ribbon负载均衡演示

总结:Ribbon其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例。

POM

spring-cloud-starter-netflix-eureka-client 依赖中自带了 spring-cloud-starter-netflix-ribbon,所以无需手动引入

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

二说RestTemplate的使用

  • getForObject:返回对象

    CommonResult commonResult = restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    
  • getForEntity:返回 ResponseEntity

    ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    

Ribbon核心组件IRule

com.netflix.loadbalancer.IRule

IRule:根据特定算法从服务列表中选取一个要访问的服务

  • com.netflix.loadbalancer.RoundRobinRule
    轮询
  • com.netflix.loadbalancer.RandomRule
    随机
  • com.netflix.loadbalancer.RetryRule
    先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试
  • WeightedResponseTimeRule
    对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
  • BestAvailableRule
    会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
  • AvailabilityFilteringRule
    先过滤掉故障实例,再选择并发较小的实例
  • ZoneAvoidanceRule
    默认规则,复合判断server所在区域的性能和server的可用性选择服务器

替换负载均衡算法

注意:算法的配置类不能位于包扫描范围内,需要独立出来。例如,启动类在包 com.atguigu.springcloud 下,算法的配置类就不能位于此包及其子包下,可以位于包 com.atguigu.myrule 下。

替换步骤:

  1. 新建配置类,com.atguigu.myrule.MySelfRule

    @Configuration
    public class MySelfRule {
        @Bean
        public IRule myRule() {
            return new RandomRule();	//定义为随机
        }
    }
    
  2. 主启动类,配置

    @RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration= MySelfRule.class)
    

9.OpenFeign服务接口调用

概述

Feign是一个声明式的web服务客户端,让编写web服务客户端变得非常容易,只需创建一个接口并在接口上添加注解即可

OpenFeign 依赖 Ribbon,自带负载均衡功能

Github 地址

服务消费者使用 OpenFeign 步骤

  1. 建 Module,cloud-consumer-feign-order80

  2. 改 POM

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

  4. 主启动类,添加注解 @EnableFeignClients

  5. 业务类,Feign 接口类

    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    public interface PaymentFeignService {
        
        @GetMapping(value = "/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
    
    }
    
  6. 调用 Feign 接口类

    @Resource
    private PaymentFeignService paymentFeignService;
    
    @GetMapping(value = "/consumer/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
        return paymentFeignService.getPaymentById(id);
    }
    

OpenFeign超时控制

改 YML:

#设置feign客户端超时时间(OpenFeign默认支持ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间,默认为1s
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间,默认为1s
  ConnectTimeout: 5000

OpenFeign日志打印功能

日志级别

级别 描述
NONE 默认,不显示任何日志
BASIC 仅记录请求方法、URL、响应状态码及执行时间
HEADERS 除了 BASIC 中定义的信息之外,还有请求和相应的头信息
FULL 除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据

配置步骤

  1. 新建配置类

    @Configuration
    public class FeignConfig {
        @Bean
        Logger.Level feignLoggerLevel() {
            return Logger.Level.FULL;
        }
    }
    
  2. 改 YML

    logging:
      level:
        # feign日志以什么级别监控哪个接口
        com.atguigu.springcloud.service.PaymentFeignService: debug
    

参考资料

posted @ 2020-05-23 14:11  流星<。)#)))≦  阅读(1152)  评论(0编辑  收藏  举报