服务治理中心是微服务(分布式)架构中最基础,也是最核心的功能组件,它主要对各个服务实例进行管理,包括服务注册、服务发现,续约等。
服务治理组件有:Eurake,Dobbo,Consul,ZooKeeper等。

看到 Netflix的组件,需要留意下,可能已进入维护阶段,不再开发新功能或者最新的已不在开源使用。
下面会完整的搭建项目(后面其他的组件基于它,就不重复了),版本如下:

  • IDEA 2020.2
  • Maven 3.6.3
  • SpringCloud Hoxton.SR9
  • SpringBoot 2.3.6
  • JDK8

一、Netflix Eureka简介

1. Eureka是什么

Eureka是入门 SpringCloud微服务架构的必学组件,是学习所有其他组件的基础和基石。

Eureka(/juˈriːkə/ 音译‘尤瑞卡’)是服务治理中心,它提供微服务的治理,服务提供方与 Eureka服务治理中心之间通过 “心跳” 机制进行监控,当某个服务提供方出现问题时,Eureka自然会把它从服务列表中剔除,从而实现了服务的自动注册、发现、状态监控,续约等功能。

主要功能是:

  • 进行服务治理
  • 定期检查服务状态
  • 返回服务实例清单列表。

2. 三个核心角色

Eureka中的三个核心角色:

  • 服务注册中心
    指 Eureka服务端应用,提供服务注册,发现和续约等功能
  • 服务提供者
    提供服务的应用,可以是 SpringBoot应用,也可以是其它技术实现的应用。主要对外提供以 REST风格的服务节点被服务消费者调用。
  • 服务消费者
  • 消费应用从注册中心获取服务实例清单列表,保存到本地,然后通过特定的负载均衡的策略确定使用具体的实例,最后通过请求该实例获取数据。

注意: 服务提供者和服务消费者并不是对立的,一个微服务可以同时是服务提供者和服务消费者。

3. Eureka包含两个组件:

  • Eureka Server即服务端
    提供服务注册中心功能 管理所有服务 支持所有服务注册
  • Eureka Client即客户端
    所有向Eureka注册中心注册的都是Eureka服务端,例如 用户服务 、商品服务、消息服务等等

4. 服务的高可用

高可用就是,在发生一定的不可控情况时,服务依然能用。

1、服务提供者和消费者的高可用

微服务是指完成某一业务功能的独立系统。
一个微服务可以有多个实例,实例是指一个具体的服务节点。
同一个微服务下的实例应该具备相同的业务功能。通过把微服务注册为多个实例,从而实现服务之间的高可用。

·2、Eureka的高可用

Eureka服务注册中心也是一个特殊的服务。
多个 Eureka服务注册中心之间也会相互注册为服务,当服务提供者注册到 Eureka Server集群中的某个节点时,该节点会把服务的信息同步到集群中的每一个节点中。从而实现数据同步。因此,无论客户端访问到哪个 Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。

二、搭建单节点Eureka服务注册中心

创建一个名为 springcloud-demo的maven项目,新建几个模块如下:

  • eureka-server: 作为Eureka服务器。
  • parent模块:添加 SpringBoot父坐标和统一管理其他组件的依赖版本。
  • user用户微服务
  • order订单微服务
    在这里插入图片描述

1. parent模块

添加 SpringBoot父坐标和统一管理其他组件的依赖版本。

<?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.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>parent</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>pom</packaging>
	<name>parent</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
		<mysql.version>8.0.22</mysql.version>
		<fastjson.version>1.2.72</fastjson.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>${fastjson.version}</version>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<!-- springCloud -->
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<!-- mysql驱动 -->
			<dependency>
				<groupId>mysql</groupId>
				<artifactId>mysql-connector-java</artifactId>
				<version>${mysql.version}</version>
			</dependency>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-starter-config</artifactId>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
		</repository>
	</repositories>

</project>

注意:通过 scope标签的 import值,表示:可以继承 SpringBoot的依赖,也可继承 spring-cloud-dependencies工程中的依赖。

2. eureka-server

eureka-server 作为单节点Eureka服务端,需要配置自身不注册自己,否则启动日志为不断出现异常。
(1)pom.xml
引入 Eureka server依赖。

<?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>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>

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

</project>

(2)yml配置文件

server:
  # 项目端口
  port: 8762
  # 项目上下文路径
  servlet:
    context-path: /

spring:
  application:
    # 服务实例名
    name: EUREKA-SERVER

eureka:
  server:
    # 取消 Eureka自我保护机制,不推荐
    # enable-self-preservation: false
  client:
    # 是否注册服务,单节点自身就是服务治理中心,设置为fasle-取消注册
    register-with-eureka: false
    # 是否开启检索服务,单节点不需要开启,false-表示自己就是注册中心,职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      # 注册中心地址,由注册中心ip和项目端口拼接/eureka
      defaultZone: http://localhost:8762/eureka
  instance:
    # 注册中心的主机名
    hostname: localhost

(3)启动类

启动类添加@EnableEurekaServer注解,表示开启 Eureka服务端.

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

3. user服务

(1)pom.xml
引入Eureka Client依赖

<?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>
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.example</groupId>
    <artifactId>user</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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>

</project>

(2)yml配置文件

server:
  port: 18001
  servlet:
    context-path: /user

spring:
  application:
    # 服务实例名,每个服务名必须唯一
    name: USER

eureka:
  instance:
    # 指定此实例的ip
    ip-address: 192.xx.xx.xxx
    # 使用ip地址,测试时ip+port访问不行,只能用服务实例名
    prefer-ip-address: true
    # 注册时使用ip,而不使用主机名
    instance-id: ${eureka.instance.ip-address}:${server.port}
    # 实例超时失效秒数,默认为 90秒,如果续约超时,该实例会被 Eureka剔除掉
    lease-expiration-duration-in-seconds: 90
    # 间隔对应的秒数执行一次续约服务,默认30秒
    lease-renewal-interval-in-seconds: 30
  client:
    service-url:
      # 指向 eureka注册中心地址
      defaultZone: http://localhost:8762/eureka

(3)启动类

启动类添加 @EnableEurekaClient注解,表示开启Eureka客户端,注册服务到注册中心。
使用 Ribbon 完成负载均衡。
在这里插入图片描述

@SpringBootApplication
@EnableEurekaClient
public class UserApplication {

	// 负载均衡
	@LoadBalanced
	@Bean
	public RestTemplate initRestTemplate() {
		return new RestTemplate();
	}

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

}

(4)conrtoller

@RestController
public class UserController {

    @Value("${server.port}")
    private String port;
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getOrder/{id}")
    public String getOrder(@PathVariable Long id){
        String url = "http://ORDER/order/get/" + id;
        String res = restTemplate.getForObject(url, String.class);
        return res;
    }

    @GetMapping("/get/{id}")
    public String get(@PathVariable Long id) {
        return port + "--" + "user服务返回数据 >>>>>>> " + id;
    }

}

4. order服务

order服务和 user服务操作同理, 这里使用下主机名,看一下区别。
(1)yml

server:
  port: 18002
  servlet:
    context-path: /order

spring:
  application:
    name: ORDER

eureka:
  instance:
    # 服务主机名称
    hostname: localhost
  client:
    service-url:
      defaultZone: http://localhost:8762/eureka

(2)conrtoller

@RestController
public class OrderController {

    @Value("${server.port}")
    private String port;
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/getUser/{id}")
    public String getUser(@PathVariable Long id){
        String url = "http://USER/user/get/" + id;
        // ip+port,会报错:java.lang.IllegalStateException: No instances available for 192.xx.xx.xxx
//        String url = "http://192.xx.xx.xxx:18001/user/get/" + id;
        String res = restTemplate.getForObject(url, String.class);
        return res;
    }

    @GetMapping("/get/{id}")
    public String get(@PathVariable Long id) {
        return port + "--" + "order服务返回数据 >>>>>>> " + id;
    }

}

注意:

  • 不要使用 ip+port 的方式访问,取而代之的是应用名(不区分大小写)
  • 这种方式发送的请求都会被ribbon拦截,Ribbon从eureka注册中心获取服务列表,然后采用均衡策略进行访问

5. 访问测试

(1)启动 eureka-server,然后启动 user, order服务。
访问:http://127.0.0.1:8762/
在这里插入图片描述
到此,单节点 Eureka注册中心搭建完成。

(2)测试服务之间调用
在这里插入图片描述

三、服务治理中心工作原理

从下面三个方法了解(图来自网络)
在这里插入图片描述

1. 微服务实例和服务治理中心的关系

任何的微服务都可以对 Eureka服务治理中心(Eureka服务端)发送 REST风格的请求。

在 Eureka的机制中,一般是具体的微服务(Eureka客户端)来主动维持它们之间的关系。

Eureka客户端的请求类型包括注册、续约和下线。

(1)注册

设置 eureka.client.serviceUrl.defaultZone属性的值来通过 REST风格的请求将微服务实例注册到 Eureka服务端。也可以通过 eureka.client.register-with-eureka来设置是否注册服务。

eureka:
  client:
  	# 是否注册服务
  	register-with-eureka: true
    # 是否开启检索服务,默认true
    fetch-registry: true
    # 检索服务实例清单的时间间隔,单位秒,默认30秒
    registry-fetch-interval-seconds: 30
    service-url:
      # 指向 eureka注册中心地址
      defaultZone: http://localhost:8762/eureka/

当启动微服务时,并不会马上发送 REST请求,它会延迟 40秒才发起请求。

(2)续约
注册之后,微服务实例会按照一个频率对 Eureka服务端维持心跳,告诉 Eureka该实例是可用的,这样的行为被称为续约(Renew)。

Eureka通过续约来确认,对应的服务实例是否还能正常工作,如果不能工作就会被它及时的剔除掉。

续约存在两个配置:

eureka:
  instance:
    # 实例超时失效秒数,默认为 90秒,如果续约超时,该实例会被 Eureka剔除掉
    lease-expiration-duration-in-seconds: 90
    # 间隔对应的秒数执行一次续约服务,默认30秒
    lease-renewal-interval-in-seconds: 30

(3)下线

在系统出现故障,或者停止/重启某个服务实例时,正常情况下,该实例会对 Eureka发送下线的 REST请求来告知服务治理中心,所以,客户端就不再请求该实例。

2. 服务治理中心

Eureka可以有效管理具体的微服务实例,但是 Eureka本身也是服务,或者说也是Eureka客户端。

多个 Eureka服务之间如何进行注册和管理。

(1)互相复制
Eureka本身也可相互注册,来保证高可用和高性能。

各个 Eureka服务器之间会相互复制。Eureka服务器之间采用的是对等模式,即每一个 Eureka都是等价的。

(2)服务剔除

Eureka在启动时会创建一个定时任务,在默认情况下,每间隔 60秒就会更新一次微服务实例的清单,只要发现有超过 90秒没有完成续约的服务实例,就会将其剔除出去。

(3)自我保护

在本机测试时,会看到红色的警告,这就是 Eureka的自我保护机制。

在 Eureka运行期间,如果在 15分钟内低于 85%的情况下心跳测试失败,它就会出现红色警告。
可以配置取消,不推荐取消自我保护机制

eureka:
  server:
    # 取消 Eureka自我保护机制,不推荐
    # enable-self-preservation: false

在这里插入图片描述

3. 微服务之间的相互调用

上面使用了 Ribbon 完成了负载均衡。这里说一下服务获取和调用。

(1)服务获取

服务获取是指微服务实例作为 Eureka的客户端,从 Eureka服务治理中心获取其他服务实例清单的功能。服务获取会将服务实例清单列表缓存到本地,并且按一定的时间间隔刷新。

eureka:
  client:
    # 是否开启检索服务,默认true
    fetch-registry: true
    # 检索服务实例清单的时间间隔,单位秒,默认30秒
    registry-fetch-interval-seconds: 30

(2)服务调用

服务调用是指一个微服务调用另一个微服务的过程。服务调用的核心往往是负载均衡算法。

在 SpringCloud中,大部分都是采用 REST风格的请求。

Ribbon会根据请求的 URL知道调用的是哪个微服务,然后再服务获取的清单列表中,通过一种负载均衡的算法选择其中一个具体实例进行调用。默认情况下,Ribbon会采用轮询的策略。

四、搭建双节点Eureka服务注册中心

双节点Eureka服务注册中心,让 Eureka服务端实现高可用,Eureka客户端在我们也启动多个服务实例。
这样,就可实现 Eureka服务端和Eureka客户端的集群搭建,更多Eureka服务注册中心节点搭建同理。

(1)eureka-server

修改YML,让 eureka-server注册服务,获取服务,默认是开始的,在上面单节点中注释掉就可以了。

eureka:
  client:
    service-url:
      # eureka注册中心地址,由注册中心ip和项目端口拼接/eureka,如果是集群的话,使用逗号分隔
      defaultZone: http://localhost:8762/eureka, http://localhost:8763/eureka
  instance:
    # 注册中心的主机名
    hostname: localhost

在本地 启动 8762和8763端口得 Eureka服务端。

(2)user和order微服务

YML文件中服务注册地址配置成集群就可以了,其他不用变。启动多个服务实例。

      # 指向 eureka注册中心地址
      defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka

在本地 启动user和order微服务。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
调用服务时会 轮询访问,注意端口得变化,说明高可用配置ok。
在这里插入图片描述

—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐