SpringCloud学习笔记(二)——Eureka(注册中心)

一、Eureka简介

 

二、Eureka快速入门

2.1 搭建Eureka-Server

首先新建一个maven项目:

 

 

 这里src删除掉就可以了。

 

 

 在项目下新建一个module(maven类型的):

 

 同样删除掉这个module下的src包。

然后再在当前module下新建一个module(springboot类型的):

 

 

 创建完成后,如果你因为Idea版本原因导致创建出来的不是一个maven项目(判断依据是pom.xml这个文件是否是蓝色的),只需要右键pom文件将其关联成maven文件。

  

 这里我们按照以前的版本进行学习,所以需要修改子pom.xml文件中的两个地方(springboot和springcloud)的版本信息:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 实质还是 springboot 项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>eureka-01</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-01</name>
    <description>eureka-01</description>
    <!-- 这里控制了 springcloud 的版本-->
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    </properties>
    <dependencies>
        <!-- eureka 注册中心的服务端-->
        <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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 依赖管理,cloud 的依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

修改启动类:

 

 

@SpringBootApplication
@EnableEurekaServer  //注解用于开启注册中心服务端
public class Eureka01Application {

    public static void main(String[] args) {
        SpringApplication.run(Eureka01Application.class, args);
    }

}

修改配置文件:

server:
  port: 8761 #为什么是 8761,其他端口就报错
spring:
  application:
    name: eureka-server #服务名称

然后我们运行这个子项目

 

 在浏览器中输入http://localhost:8761访问测试;

 

 

2.2 搭建Eureka-Client-A

创建一个与eureka-server同级的client module。

 

 选中如下两个依赖:

 

 同样修改pom.xml文件中的版本号:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>eureka-client-a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-client-a</name>
    <description>eureka-client-a</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- eureka的客户端的依赖 -->
        <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-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

修改启动类:

@SpringBootApplication
@EnableEurekaClient  //标记此服务为eureka的客户端
public class EurekaClientAApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaClientAApplication.class, args);
    }

}

修改配置文件:

服务器端端口必须得是8761,客户端的端口号没限制。

server:
  port: 8001
spring:
  application:
    name: eureka-client-a
eureka:
  client:
    service-url: #eureka 服务端和客户端的交互地址
      defaultZone: http://localhost:8761/eureka/

先启动服务器端,再启动这个客户端:

 

 2.3 再搭建一台客户端

过程同上,浏览器显示如下:

 

 2.4 为eureka-client-a创建集群

 

 

 

 

 然后直接run

 

然后运行成功:

 

 我们可以在浏览器中看到:

 

 三、eureka-server配置文件详解

 先来说明一下工作机制,进而好理解配置文件的含义。

 

 

 3.1 server中的配置分为三大类:server、client(因为server可以注册本身,所以也是客户端)、instance

server: 
  port: 8761
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: #eureka 服务端和客户端的交互地址,集群用,隔开
      defaultZone: http://localhost:8761/eureka
    fetch-registry: true #是否拉取服务列表
    register-with-eureka: true #是否注册自己(单机 eureka 一般关闭注册自己,集群注意打开)

  server:
    eviction-interval-timer-in-ms: 30000 #清除无效节点的频率(毫秒)--定期删除
    enable-self-preservation: true #server 的自我保护机制,避免因为网络原因造成误剔除,生产环境建议打开
    renewal-percent-threshold: 0.85 #85%,如果在一个机房的 client 端,15 分钟内有 85%的 client 没有续约,那么则可能是
                            网络原因,认为服务实例没有问题,不会剔除他们,宁可放过一万,不可错杀一个,确保高可用
  instance:
    hostname: localhost # 服务主机名称
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 实例 id,由主机名+实例名+端口名,之所以用表达式拼接而不是直接写成链接形式,是因为localhost会被自动识别成电脑的名字
    prefer-ip-address: true # 服务列表以 ip 的形式展示
    lease-renewal-interval-in-seconds: 10 # 表示 eureka client 发送心跳给 server 端的频率
    lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该实例

3.2 client中的配置分为两大类:client和server

server: 
  port: 8080
spring:
  application:
    name: eureka-client
eureka:
  client:
    service-url: #eureka 服务端和客户端的交互地址,集群用,隔开
      defaultZone: http://localhost:8761/eureka
    register-with-eureka: true #注册自己
    fetch-registry: true #拉取服务列表,即将server中的服务列表缓存到本地
    registry-fetch-interval-seconds: 5 # 表示 eureka-client 间隔多久去拉取服务注册信息
  instance:
    hostname: localhost # 服务主机名称
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 实例 id
    prefer-ip-address: true # 服务列表以 ip 的形式展示
    lease-renewal-interval-in-seconds: 10 # 表示 eureka client 发送心跳给 server 端的频率
    lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待 下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该实例

四、构建eureka集群

4.1 集群结构图

 

 

集群有两种模式:去中心化集群和主从集群模式

4.2 集群的配置

进行集群的配置,再创建另外两个项目,作为server的集群,各个server的配置文件如下:

server-1(即最开始创建的那个server):

server: 
    port: 8761 #为什么是 8761,其他端口就报错 
spring: 
    application: 
        name: eureka-server #服务名称 
eureka: 
    client: 
        fetch-registry: true #是否拉取服务列表 
        register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务) 
        service-url: 
          defaultZone: http://localhost:8762/eureka/,http://localhost:8763/eureka/ 
  server:
    eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
  instance:
    lease-expiration-duration-in-seconds: 90 #server 在等待下一个客户端发送的心跳 时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量

注意这里defaultZone应该写另外两台server的地址和端口。

server-2:

server: 
  port: 8762
spring:
  application:
    name: eureka-server #服务名称
eureka:
  client:
    fetch-registry: true #是否拉取服务列表
    register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务)
    service-url:
      defaultZone: http://localhost:8761/eureka/,http://localhost:8763/eureka/
  server:
    eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
  instance:
    lease-expiration-duration-in-seconds: 90 #server 在等待下一个客户端发送的心跳 时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量

注意这里应用名称要保持一致,否则就不是集群了

server-3:

 

 

 4.3 测试发现并没有出现集群

原因是因为:http://localhost:8761/eureka/,http://localhost:8762/eureka/这样写,eureka 认为只有一个机器,就是 localhost所以这里面不能写成一样
修改 hosts 文件:
C:\Windows\System32\drivers\etc
如果你修改了 hosts 文件 发现没有生效 记得在 cmd 里面刷新一下
具体修改步骤如下:

win+R键,然后输入drivers就自动进入这个文件夹了,修改etc/hosts文件如下:

 

 然后重新修改配置文件如下(三个文件都做类似的修改):

 

 然后再次访问,可以看到出现集群:

 

 

 

 

 

 4.4 集群的终极配置方案

 将其中一台server的配置文件修改如下,主要是将defaultZone中增加三个地址。

 

server:
  port: 8761
spring:
  application:
    name: eureka-server
eureka:
  client:
    register-with-eureka: true 
    service-url:
      defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/

  instance:
    lease-expiration-duration-in-seconds: 5 #server 在等待下一个客户端发送的心跳 时间,若在指定时间不能收到客户端心跳,则剔除此实例并且禁止流量
    #hostname: peer1
    instance-id: ${spring.application.name}:${server.port}

注意:这里不能配置eureka.instance.hostname这个属性,如果配置了这个属性为peer1,则最终的三台集群都不会显示peer1这台服务器。

然后复制两份这台服务器,具体步骤如下:

 

 

 

 

 

 最终的集群信息显示如下:

 五、集群的使用

 打开一个客户端,注册到其中一台服务器上,配置文件代码如下:

注意:这里最好在三台服务器上都注册,以防止注册的那台挂掉无法注册。

server:
  port: 8002
spring:
  application:
    name: eureka-client-b
eureka:
  client:
    service-url: #eureka ????????????
      defaultZone: http://peer1:8761/eureka/
    register-with-eureka: true

 然后运行起来,然后会发现往其中一台服务器注册,另外两台也会自动有这个客户端的信息。

 

 

 

 

 

 六、集群的深入理解

eureka没有分布式数据一致性的机制,节点都是相同的 ,也就是说是去中心化的集群。
而zookeeper和nacos都是主从模式集群,都需要保证分布式数据一致性的机制,zk用的是Paxos协议,nacos用的是raft协议。
这里可以详细了解一下raft协议中主机的选举过程以及主机与从机的工作过程。

七、服务发现

7.1 服务发现简介

根据服务名称发现服务的实例过程
客户端会在本地缓存服务端的列表
拉取列表是有间隔周期的 (导致服务上线 客户端不能第一时间感知到 (可以容忍))
其实每次做服务发现 都是从本地的列表来进行的

 

 7.2  服务发现的测试(目的是通过服务名称来获得IP和端口,进而再通过HTTP请求去获取另一个服务的信息)

首先启动一台server,然后确保两个客户端a和b都上线了。

 

 然后我们在A服务里做服务发现,目的是在A服务里通过名称发现服务B。

在A服务里创建一个Controller,文件位置如下:

这里有一个值得注意的点,controller文件夹必须放在与启动类同级的目录下,否则会访问不到,我这个截图是有问题的。

 cntroller中的代码如下:

package com.example.controller;

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

import java.util.List;

@RestController
public class TestCntroller {

    /*** 注入服务发现组件,我们的 eureka 已经实现了这个接口,所以 IOC 里面有这个对象 */
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("find")
    public String find(String serviceId) {
        //调用服务发现
        List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
        instances.forEach(System.out::print);
        return instances.toString();
    }

}

然后我们在浏览器中访问 http://localhost:8003/find?serviceId=eureka-client-b。

 

获得IP和端口号的具体代码如下:

八、 Eureka-Docker部署

这部分后续补充
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2022-09-17 23:39  一直学习的程序小白  阅读(112)  评论(0编辑  收藏  举报