SpringCloud 尚硅谷 微服务简介以及Eureka使用

写在前面

该系列博客仅用于本人学习尚硅谷课程SpringCloud笔记,其中的错误在所难免,如有错误恳请指正。
官方源码地址:https://github.com/zzyybs/atguigu_spirngcloud2020

什么是SpringCloud

   Spring Cloud是微服务一站式服务解决方案,微服务全家桶。它是微服务开发的主流技术栈。SpringCloud 和 SpringCloud Alibaba 目前是最主流的微服务框架组合。

   Spring Cloud包含了许多功能强大的组件,例如服务注册与发现、负载均衡、断路器、配置管理、消息总线等,这些组件可以帮助开发者构建弹性、可靠、可扩展的分布式系统。
来源:尚硅谷

   微服务是一种理念。程序员可以将应用程序拆分为多个微服务,每个微服务负责实现一个特定的功能,并通过Spring Cloud提供的组件进行协调和管理。这样,程序员可以更加灵活地组织和扩展应用程序,同时提高系统的可维护性和可靠性。

前期准备

父工程

首先创建一个父工程。maven版本使用3.5,不要使用idea自带的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Java编译版本选择JDK8。
在这里插入图片描述
修改pom:找到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>cloud2020</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 统一管理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>
                <configuration>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
  • <properties></properties>:后序需要创建子工程,在父亲工程这统一管理jar包。
  • <dependencyManagement></dependencyManagement>:通过该标签管理子模块的版本号。要注意的是,该标签只是声明了依赖,但是不是实现引入。如果要引入,需要将放到该标签外面,刷新等待引入后再放回该标签里面。
  • <dependencies></dependencies>dependencyManagement只是声明一个依赖,而不实现引入,故需要子模块中也需要对依赖进行声明,倘若不声明子模块自己的依赖,是不会从父模块中继承的;只有子模块中也声明了依赖。并且没有写对应的版本号它才会从父类中继承;并且version和scope都是取自父类;此外要是子模块中自己定义了自己的版本号,是不会继承自父类的。

里面的部分依赖并不是当前需要的,如果发现有的依赖导致了报错,可以先将相关依赖注释。

创建微服务 cloud-provider-payment8001

该微服务用于客户端服务的提供者。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment8001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

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


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

        <dependency>
            <!-- 引入自己定义的api通用包,可以使用Payment支付Entity 当前不需要,主要注释掉 -->
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <!--这个和web要写到一块-->
            <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>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </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>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

yml

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

启动类

在这里插入图片描述
可以直接通过spring初始化一步到位。

常规操作

数据库建表

create table `payment`(
    `id` bigint(20) not null auto_increment comment 'ID',
    `serial` varchar(200) default '',
    PRIMARY KEY (`id`)

)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

select * from payment;

数据可以随意添加两条。本人数据如下
在这里插入图片描述
entities

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

import java.io.Serializable;

@Data   //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor  //无参构造器
public class Payment implements Serializable {
  private long id;//数据库是bigint
  private String serial;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

//返回给前端的通用json数据串
@Data   //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor  //无参构造器
public class CommonResult<T> {
  private Integer code;
  private String message;
  private T data; //泛型,对应类型的json数据

  //自定义两个参数的构造方法
  public CommonResult(Integer code, String message){
      this(code, message, null);
  }
}

dao

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

resource下创建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.atguigu.springcloud.dao.PaymentDao">
    <resultMap id="BaseResultMap" type="com.atguigu.springcloud.entities.Payment">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <id column="serial" property="serial" jdbcType="VARCHAR"/>
    </resultMap>

    <insert id="create" parameterType="com.atguigu.springcloud.entities.Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial) values (#{serial})
    </insert>

    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
        select * from payment where id = #{id}
    </select>
</mapper>

Controller && Service

Service层

public interface PaymentService {
  int create(Payment payment);

  Payment getPaymentById(@Param("id") Long id);
}
@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);
    }
}

Controller层

@RestController
@Slf4j
public class PaymentController {

    @Resource
    private PaymentService paymentService;

    @PostMapping(value = "/payment/create")
    // 注意这里的 @RequestBody  是必须要写的,虽然 MVC可以自动封装参数成为对象,
    // 但是当消费者项目调用,它传参是 payment 整个实例对象传过来的, 即Json数据,因此需要写这个注解
    public CommonResult<Integer> create(@RequestBody Payment payment) {
        int result = paymentService.create(payment);
        log.info("****插入结果:" + result);
        if (result > 0) {
            return new CommonResult<>(200, "插入数据库成功", result);
        }
        return new CommonResult<>(444, "插入数据库失败", null);
    }

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

目录结构如下
在这里插入图片描述

启动项目

   找到启动类,然后点击运行启动。启动过程中出现了异常暂时不要管。打开浏览器,访问http://localhost:8001/payment/31(注意这里的31是本人的id数据)访问已经添加的数据。如果需要插入数据,可以使用postman传入Json。
在这里插入图片描述

创建模块 cloud-api-commons

后面的80需要和前面的8001相同的内容。为了方便管理,将相同的类放在该模块并进行打包。

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>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</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>

        <!-- hutool 工具包 -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>
    </dependencies>
</project>

将8001中entities包下的类复制到该模块,删除8001下的entities包。
在这里插入图片描述
在这里插入图片描述
等待成功后,找到8001,7001中的该依赖然后加载。
在这里插入图片描述

创建微服务 cloud-consumer-order80

该微服务用于客户端服务的消费者。

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>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- <dependency>&lt;!&ndash; 引入自己定义的api通用包,可以使用Payment支付Entity &ndash;&gt; -->
        <!--     <groupId>com.atguigu.springcloud</groupId> -->
        <!--     <artifactId>cloud-api-commons</artifactId> -->
        <!--     <version>${project.version}</version> -->
        <!-- </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.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>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

yml

server:
  port: 80 # 默认 80 端口,只需要输入网址即可

eureka:
  client:
    service-url:
       defaultZone: http://localhost:7001/eureka
    # 将自己注册进去 true
    register-with-eureka: true
    #是否从Eureka server抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true

spring:
  application:
    name: cloud-order-service

controller && config

config

@Configuration
public class ApplicationContextConfig {
	// RestTemplate是Spring框架提供的一个用于发送HTTP请求的类。它简化了与RESTful服务的交互,可以方便地发送GET、POST、PUT、DELETE等请求,并且支持处理响应结果。
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

controller

@RestController
@Slf4j
public class OrderController {

    //远程调用的 地址
    public static final String PAYMENY_URL = "http://localhost:8001";

    @Resource
    private RestTemplate restTemplate;

    @PostMapping("customer/payment/create")
    public CommonResult<Payment> create (Payment payment){

        return restTemplate.postForObject(PAYMENY_URL + "/payment/create",//请求地址
                                          payment,//请求参数
                                          CommonResult.class);//返回类型
    }

    @GetMapping("customer/payment/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id")Long id){
        return restTemplate.getForObject(PAYMENY_URL + "/payment/" + id,//请求地址
                                         CommonResult.class);//返回类型
    }
}

   整个过程,通过浏览器调用order中的controller层,然后order80微服务发送http请求给payment8001微服务获取相关信息后返回。

到这里,所有的准备工作就完成了,接下来,进行eureka的正式使用。

Eureka

是什么

   Eureka用于服务的注册与发现,用于管理和监控各个微服务。

   比如,使用微服务后,不同的微服务在不同的机器上,为了简单方便管理,可以使用Eureka进行注册。

机制简介

   Eureka包括两个组件:Eureka ServerEureka Client

  • Eureka Server:服务器,里面有一个注册表,保存了不同的服务所在的机器和端口号。
  • Eureka Client:客户端,负责将服务注册到Eureka Server中。

   Eureka Client组件告诉Eureka Server自己在哪台机器上,监听着哪个端口;Eureka Client需要调用其他微服务的时候,通过Eureka Server寻找其他服务客户端,然后将这些相关信息从Eureka Server的注册表中缓存到自己的本地。

服务在Eureka上注册,然后定期发送心跳来更新它们的续约。如果客户端不能多次续订,那么它将在大约90秒内从服务器注册表中剔除。

服务提供者向注册中心注册服务,并每隔30秒发送一次心跳,如果Eureka长时间后还未收到服务提供者发来的心跳时,那么它就会认定该服务已经死亡就会注销这个服务。这里注销并不是立即注销,而是会在60秒以后对在这个之间段内“死亡”的服务集中注销,如果立即注销,势必会对Eureka造成极大的负担。这些时间参数都可以人为配置。

Eureka还有自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,所以不会再接收心跳,也不会删除服务。

客户端消费者会向注册中心拉取服务列表,因为一个服务器的承载量是有限的,所以同一个服务会部署在多个服务器上,每个服务器上的服务都会去注册中心注册服务,他们会有相同的服务名称但有不同的实例id,所以拉取的是服务列表。我们最终通过负载均衡来获取一个服务,这样可以均衡各个服务器上的服务。

使用Eureka

   刚刚我们创建了一个微服务 cloud-provider-payment8001。当前的项目比较简单,管理起来不困难。但是如果项目比较多,而且分布在不同的机器上,管理就比较麻烦了,可以使用eureka进行服务的注册。现在将该微服务进行注册。

   eureka有两个组件;server和client。将cloud-provider-payment8001作为client,那么,需要一个server,为此,需要再写一个微服务cloud-eureka-server7001,表示eureka的服务中心,端口号是7001。

   按照上述方式,新建模块,选择maven工程。

创建微服务cloud-eureka-server7001

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>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

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

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
</project>

yml

server:
  port: 7001

eureka:
  instance:
    hostname: localhost  # eureka 服务端的实例名称
  
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      # 设置与 Eureka Server 交互的地址,查询服务 和 注册服务都依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

启动类

// exclude :启动时不启用 DataSource的自动配置检查
// 依赖中存在数据源,如果启动会提示找不到数据源
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer   // 表示它是服务注册中心
public class EurekaServerMain7001 {
    public static void main(String[] args){
        SpringApplication.run(EurekaServerMain7001.class, args);
    }
}

   启动类中需要格外注意的一个注解@EnableEurekaServer,用于在Spring Boot应用程序中启用Eureka服务器。通过使用@EnableEurekaServer注解,我们可以将 cloud-eureka-server7001 标记为Eureka服务器,以便其他微服务可以进行注册和发现。
   服务中心有了,使用@EnableEurekaClient注解在 cloud-provider-payment8001 的启动类上。通过@EnableEurekaClient可以将微服务标记为Eureka客户端,以便注册到Eureka服务器。同时要配置8001的yml。

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service # 项目名,也是注册的名字
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/cloud2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 123456
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.dkf.springcloud.entities  # 所有Entity 别名类所在包

eureka:
  client:
    # 注册进 Eureka 的服务中心
    register-with-eureka: true
    # 检索 服务中心 的其它服务
    fetch-registry: true
    service-url:
      # 设置与 Eureka Server 交互的地址
      defaultZone: http://localhost:7001/eureka/

启动该微服务,访问。
在这里插入图片描述
启动 cloud-provider-payment8001,cloud-consumer-order80
在这里插入图片描述
刷新7001网页,可以看到新注册了两个微服务。
在这里插入图片描述
   现在看这两个微服务后面的状态信息。我们想要知道该微服务来自哪个ip,来自哪个机器,可以进行配置来显示。

微服务信息完善

order80和payment8001分别修改yml,添加

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      # 新增部分
  instance: 
    instance-id: payment8001 # 提供者的id
    prefer-ip-address: true # 显示ip地址

就可以显示提供者的id和ip地址。
在这里插入图片描述

微服务发现Discovery

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

   先在8001的主启动类上添加@EnableDiscoveryClient,然后添加代码。

@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/customer/discovery")
public Object discovery(){
    //获得服务清单列表
    List<String> services = discoveryClient.getServices();
    for(String service: services){
        log.info("*****service: " + service);
    }
    // 根据具体服务进一步获得该微服务的信息
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-ORDER-SERVICE");
    for(ServiceInstance serviceInstance:instances){
        log.info(serviceInstance.getServiceId() + "\t" + serviceInstance.getHost()
                 + "\t" + serviceInstance.getPort() + "\t" + serviceInstance.getUri());
    }
    return this.discoveryClient;
}

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

Eureka自我保护

在这里插入图片描述
   看到该信息,说明eureka进入了自我保护。为了防止Eureka Client可以正常运行但是与Eureka Server网络不通情况下,Eureka Server不会立刻将Eureka Client服务剔除。

   保护模式主要用于一组客户和Eureka Server之间存在网络分区场景下保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中固定信息,也就是不会注销任何微服务。

   默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时、卡顿、拥挤)时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过"自我保护模式"来解决这个问题—当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。

   自我保护模式是一种应对网络异常的安全保护措施。设计理念是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

禁止使用自我保护

修改yml。
server:

eureka:
  instance:
    hostname: eureka7001.com  # eureka 服务端的实例名称
  client:
    # false 代表不向服务注册中心注册自己,因为它本身就是服务中心
    register-with-eureka: false
    # false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      defaultZone: http://localhost:7001/eureka/
#  server:
#    # 关闭自我保护机制,保证不可用该服务被及时剔除
#    enable-self-preservation: false
#    # eureka server清理无效节点的时间间隔
#    eviction-interval-timer-in-ms: 2000 

client:

eureka:
  client:
    service-url:
       defaultZone: http://localhost:7001/eureka
    # 将自己注册进去 true
    register-with-eureka: true
    #是否从Eureka server抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
  instance:
    instance-id: payment8001 # 提供者的id
    prefer-ip-address: true # 显示ip地址
      # Eureka客户端像服务端发送心跳的时间间隔,单位s,默认30s
    least-renewal-interval-in-seconds: 1
      # Eureka服务端在收到最后一次心跳后等待时间上线,单位为s,默认90s,超时将剔除服务
    least-expiration-duration-in-seconds: 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值