当前位置: 首页 > news >正文

SpringCloud学习笔记

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

1.1 微服务简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2 SpringCloud 简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 SpringCloud技术栈

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4 SpringBoot版本选择

1.4.1 git源码地址

git源码地址:https://github.com/spring-projects/spring-boot/releases/
在这里插入图片描述在这里插入图片描述
为了稳定起见,建议用Spring boot2.x

1.4.2 SpringBoot2.0新特性

git源码地址:https:github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Release-Notes
在这里插入图片描述
通过上面官网发现 Boot官方强烈建议你升级到2.X以上版本。

1.4.3 官网看Boot版本

  1. springboot(截止2019.10.26)
    在这里插入图片描述
  2. springboot(截止2020.2.15)
    在这里插入图片描述

1.5 SpringCloud版本选择

1.5.1 git源码地址

git源码地址:https://github.com/spring-projects/spring-cloud/releases/

1.5.2 官网

官网:https://spring.io/projects/spring-cloud
在这里插入图片描述

1.5.3 官网看Cloud版本

1.5.3.1 Cloud命名规则

SpringCloud采用了英国伦敦地铁站的名称来命名,并由地铁站名称字母A-Z依次类推的形式来发布迭代版本。
SpringCloud是一个由许多子项目组成的综合项目,各个项目有不同的发布节奏。为了管理SpringCloud与各子项目的版本依赖关系,发布了一个清单,其中包括了某个SpringCloud版本对应的子项目版本。为了避免SpringCloud版本号与子项目版本混乱,SpringCloud版本采用了名称而并非版本号的命名,这些版本的名字采用了伦敦地铁站的名字,根据字母表的顺序来对应版本时间顺序。例如Angel是第一个版本,Brixton是第二个版本。当SpringCloud的发布内容积累到列节点或者一个重大Bug被解决后,会发布一个’service releases’版本,简称SRX版本,比如Greenwich.SR2就是SpringCloud发布的Greenwich版本的第2个SRX版本。
在这里插入图片描述

1.5.3.2 springcloud(截止2019.10.26)

在这里插入图片描述

1.5.3.3 springboot(截止2020.2.15)

在这里插入图片描述

1.6 Springcloud和Springboot之间的依赖关系

1.6.1 官方文档

官方文档:https://spring.io/projects/spring-cloud#overview
在这里插入图片描述

1.6.2 依赖

在这里插入图片描述

1.6.3 更详细的版本对应查看方法

查询网址:https://start.spring.io/actuator/info
在这里插入图片描述

1.7 项目环境

工具版本
cloudHoxton.SR1
boot2.2.RELEASE
cloudalibaba 2.1.0.RELEASE
javaJava8
Maven3.5及以上

1.8 题外话

  1. boot版已经到3.0.0为最新,为什么选2.2.2?
    只用boot,可以直接用最新版,但是同时用boot和cloud,需要照顾,由cloud决定boot版本。
    在这里插入图片描述
  2. 2.x版本常用软件pom
    <dependencies>
      <!--  springboot 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.2.9.RELEASE    -->
      <!-- SpringCloudAlibaba有关依赖 -->
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.5.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

二 关于Cloud各种组件的停更/升级/替换

2.1 由停更引发的"升级惨案"

2.1.1 停更不停用

  1. 被动修复bugs。
  2. 不再接受合并请求。
  3. 不再发布新版本。

2.1.2 明细条目

  1. 之前
    在这里插入图片描述
  2. now
    1) 服务注册中心:Eureka(重度患者)、Zookeeper、Consul、Nacos(推荐)。
    2)服务调用: Ribbon(轻度患者)、LoadBalancer。
    3)服务调用:Feign,OpenFeign。
    4)服务降级:Hystrix、resilience4j(国外使用多)、alibaba Sentinel(国内使用多)。
    5)服务网关:Zuul、Zuul2(胎死腹中)、gateway。
    6)服务配置:Config、Nacos、apollo。
    7)服务主线:Bus、Nacos。

2.1.3 参考资料见官网

Spring Cloud:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
Spring Cloud中文文档:https://www.bookstack.cn/read/spring-cloud-docs/docs-index.md
Spring Boot:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/

三 微服务架构编码构建

在这里插入图片描述

3.1 IDEA新建project工作空间

3.1.1 父工程步骤

  1. New Project
    在这里插入图片描述

  2. 聚合总父工程名字
    在这里插入图片描述

  3. Maven选版本
    在这里插入图片描述

  4. 字符编码
    文件–>设置–>文本编码
    在这里插入图片描述

  5. 注解生效激活
    文件–>设置–>构建,执行,部署–>Compiler–>Annotation processors
    在这里插入图片描述

  6. java编译版本选8
    文件–>设置–>构建,执行,部署–>Compiler–>Java Compiler
    在这里插入图片描述

  7. File Type过滤
    文件–>设置–>编辑器–>文件类型
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/359562f9ddc3402a8d73053ce3d33840.png在这里插入图片描述

3.1.2 父工程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.tedu.java</groupId>
  <artifactId>cloud2022</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>

  <name>Maven</name>
  <!-- FIXME change it to the project's website -->
  <url>http://maven.apache.org/</url>
  <inceptionYear>2001</inceptionYear>

  <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.12</log4j.version>
    <lombok.version>1.18.16</lombok.version>
    <mysql.version>8.0.26</mysql.version>
    <druid.version>1.2.11</druid.version>
    <mybatis.spring.boot.version>2.1.4</mybatis.spring.boot.version>
  </properties>

  <!-- 子模块继承之后,提供作用:锁定版本+子模块不用写groupId和version  -->
  <dependencyManagement>
    <dependencies>
      <!--  springboot 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.2.9.RELEASE    -->
      <!-- SpringCloudAlibaba有关依赖 -->
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.5.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>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.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.6.7</version>
        <configuration>
          <fork>true</fork>
          <addResources>true</addResources>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

3.1.3 Maven工程落地细节复习

  1. Maven中的DependencyManagement和Dependencies?
    父项目中 不使用dependencyManagement,直接使用 dependencies,则子项目会继承引入父项目中的依赖。而父项目中使用dependencyManagement,则子项目不会引入依赖,需要显式的自行添加依赖。但可以不用添加版本号,直接继承父项目的版本号。
    说明:dependencyManagement一般用在maven构建的聚合项目的父项目中,只是用来声明和锁定版本(通常用语有多个子项目,但是不是每个子项目都需要引入同一种依赖的场景),所以使用dependencyManagement元素提供了一种管理依赖版本号的方式,通常会在一个组织或者项目的最顶层父POM中看到dependencyManagement元素。
  2. maven中跳过单元测试?
    在这里插入图片描述

3.1.4 父工程创建完成执行mvn:insall将父工程发布到仓库方便子工程继承

在这里插入图片描述

3.2 Rest微服务工程搭建

3.2.1 Cloud-provider-payment8001 微服务提供者Module模块

3.2.1.1 建module

在这里插入图片描述
创建完成后回到父工程查看pom文件变化?
在这里插入图片描述

3.2.1.2 改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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>Cloud-provider-payment8001</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

3.2.1.3 写YML

application.yml

server:
  port: 8001
spring:
  application:
    name: cloud-payment-service8001
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
    url: jdbc:mysql://localhost:3306/db2022_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tedu.java.pojo   #所在pojo别名类所在包

3.2.1.4 主启动

package com.tedu.java;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


/**
 * @author 47132
 */
@SpringBootApplication
public class PayMentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PayMentMain8001.class,args);
    }
}

3.2.1.5 业务类

1) 建表SQL
在数据库中新增数据库db2022_cloud,在db2022_cloud新增表payment。

CREATE TABLE `payment`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `serial` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '支付流水号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '支付表' ROW_FORMAT = Dynamic;

2)pojo
主实体Payment:

package com.tedu.java.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @author 47132
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id;
    private String serial;
}

Json封装体CommonResult类

package com.tedu.java.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author 47132
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    //404 not_found
    private Integer code;
    private String message;
    private T data;
    public CommonResult(Integer code,String message){
        this(code,message,null);
    }
}

3)dao
PaymentDao 接口

package com.tedu.java.dao;

import com.tedu.java.pojo.Payment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * @author 47132
 */
@Mapper
public interface PaymentDao {
    public int create(Payment payment);
    public Payment getPaymentById(@Param("id") Long id);
}

mybatis的映射文件PaymentMapper.xml:
路径:src\main\resources\mapper\PaymentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tedu.java.dao.PaymentDao">

    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment (serial) values (#{serial});
    </insert>
    <resultMap id="BaseResultMap" type="Payment">
        <id column="id" property="id" jdbcType="BIGINT"></id>
        <id column="serial" property="serial" jdbcType="VARCHAR"></id>
    </resultMap>
    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
        select * from payment where id=#{id};
    </select>
</mapper>

4)service
接口PaymentService

package com.tedu.java.service;

import com.tedu.java.pojo.Payment;
import org.apache.ibatis.annotations.Param;

/**
 * @author 47132
 */
public interface PaymentService {
    public int create(Payment payment);
    public Payment getPaymentById(@Param("id") Long id);
}

实现类 PaymentServiceImpl

package com.tedu.java.service.impl;

import com.tedu.java.dao.PaymentDao;
import com.tedu.java.pojo.Payment;
import com.tedu.java.service.PaymentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class PaymentServiceImpl implements PaymentService {
    @Autowired
    private PaymentDao paymentDao;

    @Override
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}

5)controller
PaymentController

package com.tedu.java.controller;

import com.tedu.java.pojo.Payment;
import com.tedu.java.service.PaymentService;
import com.tedu.java.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 47132
 */
@RestController
@Slf4j
public class PaymentController {
    @Autowired
    private PaymentService paymentService;
    
    @PostMapping(value = "/payment/create")
    public CommonResult create(@RequestBody Payment payment) {
        int result = paymentService.create(payment);
        log.info("*******插入结果:" + result);
        if (result > 0) {
            return new CommonResult(200, "插入结果成功,serverPort:", result);
        } else {
            return new CommonResult(444, "插入结果失败!!serverPort:");
        }
    }

    @GetMapping(value = "/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id) {
        Payment paymentResult = paymentService.getPaymentById(id);
        log.info("*******插入结果为:" + paymentResult);
        if (paymentResult != null) {
            return new CommonResult(200, "查询结果成功,serverPort:"+serverPort, paymentResult);
        } else {
            return new CommonResult(444, "没有对应记录!!查询id为:"+id+",serverPort:"+serverPort);
        }
    }
}

3.2.1.6 测试

运行项目,先使用postman模拟post请求,添加数据,然后查询。
在这里插入图片描述

3.2.2 热部署Devtools

3.2.2.1 Adding devtools to your project(引入maven依赖)

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

3.2.2.2 Adding plugin to your pom.xml(添加插件到pom)

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

3.2.2.3 Enabling automatic build(开启自动编译)

在这里插入图片描述

3.2.2.4 Update the value of(idea中快捷键:ctrl+shift+alt+/)

在这里插入图片描述在这里插入图片描述

3.2.2.5 重启idea

3.2.3 cloud-consumer-order80 微服务消费者订单Module模块

3.2.3.1 新建cloud-consumer-order80在这里插入图片描述

3.2.3.2 改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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order80</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</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-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

3.2.3.3 写YML

server:
  port: 80
spring:
  application:
    name: cloud-comsumer-order80

3.2.3.4 主启动

package com.tedu.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author 47132
 */
@SpringBootApplication
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

3.2.3.5 业务类

  1. pojo
    主实体Payment:
package com.tedu.java.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @author 47132
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id;
    private String serial;
}

Json封装体CommonResult类

package com.tedu.java.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author 47132
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    //404 not_found
    private Integer code;
    private String message;
    private T data;
    public CommonResult(Integer code,String message){
        this(code,message,null);
    }
}
  1. 首说RestTemplate
    RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具类。
    在这里插入图片描述
  2. config配置类
    ApplicationContextConfig 类
package com.tedu.java.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @author 47132
 */
@Configuration
public class ApplicationContextConfig {
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}


  1. controller
    OrderController 类
package com.tedu.java.controller;

import com.tedu.java.pojo.Payment;
import com.tedu.java.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author 47132
 */
@RestController
@Slf4j
public class OrderController {
    public static final String PAYMENT_URL="HTTP://localhost:8001";
    
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment, CommonResult.class);
    }
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

3.2.3.6 测试

先启动8001,再启动80,然后浏览器访问http://localhost/consumer/payment/get/1
在这里插入图片描述

3.2.4 工程重构

3.2.4.1 观察问题

在这里插入图片描述系统中有重复部分,重构。

3.2.4.2 新建cloud-api-common

在这里插入图片描述

3.2.4.3 改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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-api-commons</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.6</version>
        </dependency>
    </dependencies>
</project>

3.2.4.3 pojo

主实体Payment:

package com.tedu.java.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @author 47132
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment implements Serializable {
    private Long id;
    private String serial;
}

Json封装体CommonResult类

package com.tedu.java.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author 47132
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult<T> {
    //404 not_found
    private Integer code;
    private String message;
    private T data;
    public CommonResult(Integer code,String message){
        this(code,message,null);
    }
}

3.2.4.4 maven命令clean install

在这里插入图片描述

3.2.4.5 订单80和支付8001分别改造

  1. 删除各自的原先的pojo和utils文件夹。
  2. 各自粘贴POM内容:
<dependency>
            <groupId>com.tedu.java</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

3.2.5 目前工程样图

在这里插入图片描述

四 Eureka服务注册与发现

4.1 Eureka基础知识

4.1.1 什么是服务治理

Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理。
在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务与服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。

4.1.2 什么是服务注册

Erueka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server 来监控系统中各个微服务是否正常运行。
在微服务注册与发现中,有一个注册中心。当服务器启动的时候,就会把当前自己服务器的信息,比如服务地址通讯地址等以别名的形式注册到注册中心上。另一方(消费者|服务者提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想;在于注册中心,因为使用注册中心管理每一个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))。
在这里插入图片描述

4.1.3 Eureka两组件

  1. Eureka Server:提供服务注册功能。
    各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册列表将会存储所有可用服务节点的信息,服务节点的信息可以再界面中直观看到。
  2. EurekaClient:通过注册中心进行访问。
    是一个java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮循(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)。

4.2 单机Eureka构建步骤

4.2.1 IDEA生成EurekaServer端服务注册中心

  1. 建Module(cloud-eureka-server7001)
    在这里插入图片描述
  2. 改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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.tedu.java</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
  1. 写YML
server:
  port: 7001
spring:
  application:
    name: cloud-eureka-server7001

eureka:
  instance:
    hostname: eureka7001.com #eureka服务端的实例名称
  client:
    #false表示自己断就是注册中心,职责就是维护服务实例,并不是区检索服务
    fetch-registry: false  #不注册自己
    #fasle表示不向注册中心注册自己
    register-with-eureka: false # 不检索自己
    service-url:
      #设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka
  1. 启动类EurekaMain7001
package com.tedu.java;

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

/**
 * @author 47132
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class,args);
    }
}

  1. 修改host文件
    在这里插入图片描述
  2. 启动7001测试
    http://eureka7001.com:7001
    在这里插入图片描述

No application available没有服务被发现 因为没有注册服务进来当前不可能有服务被发现。

4.2.2 EurekaClient端cloud-provider-payment8001 将注册进EurekaServer成为服务提供者provider

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

在这里插入图片描述

  1. 写YML
eureka:
  client:
    #表示是否将自己注册进eurekaServer,默认为true
    register-with-eureka: true
    #是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
      defaultZone: http://eureka7001.com:7001/eureka
  1. 主启动类
@SpringBootApplication
@EnableEurekaClient
public class PayMentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PayMentMain8001.class,args);
    }
}
  1. 测试
    先启动EurekaServer,然后再浏览器输入:http://eureka7001.com:7001,然后再启动8001。
    在这里插入图片描述

4.2.3 自我保护机制

在这里插入图片描述

4.3 集群Eureka构建步骤

在这里插入图片描述

4.3.1 Eureka集群原理说明

在这里插入图片描述
解决办法: 搭建Eureka注册中心集群,实现负载均衡+故障容错。

4.3.2 Eureka集群环境构建步骤

4.3.2.1 参考cloud-eureka-server7001新建cloud-eureka-server7002

4.3.2.2 改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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7002</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>com.tedu.java</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

4.3.2.3 修改映射配置

找到C:\Windows\System32\drivers\etc路径下的hosts文件:

127.0.0.1	eureka7001.com
127.0.0.1	eureka7002.com

刷新hosts文件:ipconfig /flushdns
在这里插入图片描述

4.3.2.4 写YMl

cloud-eureka-server7001:

server:
  port: 7001
spring:
  application:
    name: cloud-eureka-server7001

eureka:
  instance:
    hostname: eureka7001.com #eureka服务端的实例名称
  client:
    #false表示自己断就是注册中心,职责就是维护服务实例,并不是区检索服务
    fetch-registry: false  #不注册自己
    #fasle表示不向注册中心注册自己
    register-with-eureka: false # 不检索自己
    service-url:
      #设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka

cloud-eureka-server7002:

server:
  port: 7002
spring:
  application:
    name: cloud-eureka-server7002

eureka:
  instance:
    hostname: eureka7002.com #eureka服务端的实例名称
  client:
    #false表示自己断就是注册中心,职责就是维护服务实例,并不是区检索服务
    fetch-registry: false  #不注册自己
    #fasle表示不向注册中心注册自己
    register-with-eureka: false # 不检索自己
    service-url:
      #设置与eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka

4.3.2.5 主启动

package com.tedu.java;

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

/**
 * @author 47132
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7002 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7002.class,args);
    }
}

4.3.3 将支付服务8001微服务发布到上面2台Eureka集群配置中

将Cloud-provider-payment8001中的application.yml修改:

server:
  port: 8001
spring:
  application:
    name: cloud-payment-service8001
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
    url: jdbc:mysql://localhost:3306/db2022_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tedu.java.pojo   #所在pojo别名类所在包
eureka:
  client:
    #表示是否将自己注册进eurekaServer,默认为true
    register-with-eureka: true
    #是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
      #defaultZone: http://eureka7001.com:7001/eureka

4.3.4 将订单服务80微服务发布到上面2台Eureka集群配置中

将cloud-consumer-order80中的application.yml修改:

server:
  port: 80
spring:
  application:
    name: cloud-comsumer-order80
eureka:
  client:
    #表示是否将自己注册进eurekaServer,默认为true
    register-with-eureka: true
    #是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
      #defaultZone: http://eureka7001.com:7001/eureka

4.3.5 测试

先要启动EurekaServer,7001/7002服务,再要启动服务提供者provider8001,再要启动消费者80;在浏览器中输入http://localhost/consumer/payment/get/1,观察结果。
在这里插入图片描述

4.3.6 支付服务提供者8001集群环境搭建

4.3.6.1 参考cloud-provider-payment8001新建cloud-provider-payment8002

4.3.6.2 改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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8002</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.tedu.java</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

4.3.6.3 写YMl

server:
  port: 8002
spring:
  application:
    name: cloud-payment-service8002
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource  #当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver #mysql驱动包
    url: jdbc:mysql://localhost:3306/db2022_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.tedu.java.pojo   #所在pojo别名类所在包
eureka:
  client:
    #表示是否将自己注册进eurekaServer,默认为true
    register-with-eureka: true
    #是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
      #defaultZone: http://eureka7001.com:7001/eureka

4.3.6.4 主启动

package com.tedu.java;


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


/**
 * @author 47132
 */
@SpringBootApplication
@EnableEurekaClient
public class PayMentMain8002 {
    public static void main(String[] args) {
        SpringApplication.run(PayMentMain8002.class,args);
    }
}

4.3.6.5 业务类

直接从8001粘

4.3.6.6 修改8001/8002的controller

在这里插入图片描述
在这里插入图片描述

4.3.6.7 修改80的controller

package com.tedu.java.controller;

import com.tedu.java.pojo.Payment;
import com.tedu.java.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author 47132
 */
@RestController
@Slf4j
public class OrderController {
    //public static final String PAYMENT_URL="HTTP://localhost:8001";
    // 通过在eureka上注册过的微服务名称调用
    public static final String PAYMENT_URL="http://CLOUD-PAYMENT-SERVICE";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment, CommonResult.class);
    }
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

4.3.6.8 使用@LoadBalanced注解赋予RestTemplate负载均衡的能力

修改80端口的ApplicationContextConfig :

package com.tedu.java.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @author 47132
 */
@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

4.3.6.9 测试

先要启动EurekaServer,7001/7002服务,再要启动服务提供者provider,8001/8002服务再启动consumer;80,在浏览器输入:http://localhost/consumer/payment/get/1
在这里插入图片描述
修改8001和8002的application.yml,改为CLOUD-PAYMENT-SERVICE
在这里插入图片描述
结果:负载均衡效果达到,8001/8002端口交替出现。
因为Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号,且该服务还有负载功能了。

4.4 actuator微服务信息完善

4.4.1 主机名称:服务名称修改

  1. 当前问题
    在这里插入图片描述
  2. 修改cloud-provoder-payment8001
    yaml:
eureka:
  client:
    #表示是否将自己注册进eurekaServer,默认为true
    register-with-eureka: true
    #是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
      #defaultZone: http://eureka7001.com:7001/eureka
  instance:
    instance-id: payment8001

在这里插入图片描述
8002和80也是如此。
在这里插入图片描述

4.5 服务发现Discovery

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

4.5.1 修改cloud-provider-payment8001的Controller:

    @Autowired
    private DiscoveryClient discoveryClient;
    /**
     * 服务发现
     */
    @GetMapping("/payment/discovery")
    public Object discovery(){
        List<String> services = discoveryClient.getServices();
        for(String element : services){
            log.info("*********element:"+element);
        }
        //一个微服务小的全部实例
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance:instances){
            log.debug(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
        }
        return this.discoveryClient;
    }

在这里插入图片描述
在这里插入图片描述

4.5.2 8001的启动类:@EnableDiscoveryClient

package com.tedu.java;


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;


/**
 * @author 47132
 */
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PayMentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PayMentMain8001.class,args);
    }
}

4.5.3 测试

先要启动EurekaServer,再启动8001主启动类,需要稍等一会。在浏览器输入http://localhost:8001/payment/discovery
在这里插入图片描述

4.6 eureka自我保护

4.6.1 故障现象

概述:
保护模式主要用于一组客户端和Erueka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN 
THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES 
ARE NOT BEING EXPIRED JUST TO BE SAFE.

4.6.2 导致原因

  1. 为什么会产生Eureka自我保护机制?
    为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除。
  2. 什么事自我保护模式?
    默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurrekaServer之间无法正常通信,以上行为可能会变得非常危险----因为微服务本身其实时健康的,此时本不应该注销这个微服务。Eureka通过“自我保护机制”来解决这个问题----当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
    在这里插入图片描述
    它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何一个可能健康的服务实例,
    综上,自我保护模式是一种应对网络异常的安全保护措施。它的哲学架构是宁可同事保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目的注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
    一句话:某时刻 一个微服务不可用了,Eureka不会立刻清理,依旧会对该服务的信息进行保存,属于CAP里面的AP分支。

4.6.3 怎么禁止自我保护

4.6.3.1 注册中心eurekaServer端7001

出产默认,自我保护机制是开启的:eureka.server.enable-self-preservation=true,使用eureka.server.enable-self-preservation=false 可以禁用自我保护模式。
在这里插入图片描述

4.6.3.2 生产者客户端eurekaClient端8001

在默认情况下:

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

配置:

eureka:
  client:
    #表示是否将自己注册进eurekaServer,默认为true
    register-with-eureka: true
    #是否从eurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须为true,才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
      #defaultZone: http://eureka7001.com:7001/eureka
  instance:
    instance-id: payment8001
    ##Eureka服务端在收到最后一次心跳后等待时间上限 ,单位为秒(默认是90秒),超时剔除服务
    lease-expiration-duration-in-seconds: 2
    ##Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
    lease-renewal-interval-in-seconds: 1

在这里插入图片描述

4.6.3.3 测试

先启动EurekaServer,再启动8001,先关闭8001,看是否被删除。
在这里插入图片描述
在这里插入图片描述

五 Zookeeper服务注册与发现

Eureka停止更新了,你怎么办?
网址:https://github.com/Netflix/eureka/wiki

在这里插入图片描述

5.1 注册中心Zookeeper

Zookeeper是一个分布式协调工具,可以实现注册中心功能。
关闭Linux服务器防火墙后启动Zookeeper服务器。

5.2 服务提供者

5.2.1 新建cloud-provider-payment8004

5.2.2 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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8004</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.tedu.java</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

5.2.3 YML

#8004表示注册到zookeeper服务器的支付服务提供者端口号
server:
  port: 8004
spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 192.168.43.128:2181

5.2.4 主启动类

package com.tedu.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @author 47132
 */
@SpringBootApplication
//该注解用于向使用consul或者zookeeper作为注册中心时注册服务
@EnableDiscoveryClient
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class,args);
    }
}

5.2.5 Controller

package com.tedu.java.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/zk")
    public String paymentZk(){
        return "SpringCloud with Zookeeper:"+serverPort+"\t"+ UUID.randomUUID().toString();
    }
}

5.2.6 启动8004注册进zookeeper

启动zk:

zkServer.sh start

启动后问题:

在这里插入图片描述
解决zookeeper版本jar包冲突问题:
在这里插入图片描述
排除zk冲突后的新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">
    <parent>
        <artifactId>cloud2022</artifactId>
        <groupId>com.tedu.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8004</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.tedu.java</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--先排除自带的zookeeper-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--添加zookeeper3.7.1-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.7.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

相关文章:

  • 智慧校园-教务管理系统建设要素
  • 基于单片机的煤气泄漏报警系统设计
  • 【Hadoop】-Apache Hive使用语法与概念原理[15]
  • Chapter 1-16. Introduction to Congestion in Storage Networks
  • Nginx入门-01
  • 第59篇:创建Nios II工程之控制LED<一>
  • 力扣128. 最长连续序列(哈希表)
  • C 程序结构
  • Qt6.8 GRPC功能使用(2)标准 Qt实现客户端
  • PHP7.3 GD库报错imagecreatefromstring(): No JPEG support in this PHP build
  • 为什么ChatGPT预训练能非常好地捕捉语言的普遍特征和模式
  • [云原生] K8S声明式资源管理
  • FFT 快速傅里叶变换 NTT 快速数论变换
  • 王传福赚嗨了!比亚迪单季利润超50亿 还大量出口到欧洲
  • 带你趣学算法
  • 设计模式(四)—— 装饰者模式
  • [架构之路-48]:目标系统 - 系统软件 - Linux下的网络通信-4-快速数据平面开发套件DPDK-工作原理
  • 创意电子学00课:需要准备的材料汇总
  • 什么是轨到轨?这种运放和普通运放比有什么特点和优点?
  • 面试官:小伙子,说说C/C++是如何进行内存管理的?我:……
  • STL容器 —— map和set的模拟实现
  • 软考知识点---06文件管理与作业管理---01文件管理
  • API网关基础认知
  • 腾讯云Ubuntu18.04配置深度学习环境
  • 反常积分敛散性的比较判别法专题(及常用反常积分)
  • pythond大屏可视化
  • 知识图谱-生物信息学-医学论文(Chip-2022)-BCKG-基于临床指南的中国乳腺癌知识图谱的构建与应用
  • 力扣 每日一题 902. 最大为 N 的数字组合【难度:困难,rating: 1989】(数学 / 数位dp)
  • 奇迹mu服务器安全和优化设置
  • OC 基础 导航栏UITabBarController的使用(源码)
  • 人脸识别项目FFmpeg+OpenCV+虹软SDK
  • ITRS 与 GCRS 之间的坐标转换