Spring Cloud 系列之注册中心 Eureka详解

1.1 简介

1.1.1 概述

  Netflix Eureka 是由 Netflix 开源的一款基于 REST 的服务发现组件,包括 Eureka Server 及 Eureka Client。2012 年 9 月在 GitHub 上发布 1.1.2 版本,目前 Netflix 以宣布闭源,所以市面上还是以 1.x 版本为主。Eureka 提供基于 REST 的服务,在集群中主要用于服务管理。Eureka 提供了基于 Java 语言的客户端组件,客户端组件实现了负载均衡的功能,为业务组件的集群部署创造了条件。使用该框架,可以将业务组件注册到 Eureka 容器中,这些组件可进行集群部署,Eureka 主要维护这些服务的列表并自动检查它们的状态。Spring Cloud Netflix Eureka 是 Pivotal 公司为了将 Netflix Eureka 整合于 Spring Cloud 生态系统提供的版本。
  Eureka 包含两个组件:Eureka Server 和 Eureka Client, Eureka Server 提供服务注册服务。各个微服务节点通过配置启动后,会在 EurekaServer 中进行注册,这样 EurekaServer 中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。EurekaClient 通过注册中心进行访问。它是一个 Java 客户端,用于简化 Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向 Eureka Server 发送心跳(默认周期为30秒)。如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,EurekaServer 将会从服务注册表中把这个服务节点移除(默认90秒)

1.1.2 原理图

  一个简单的 Eureka 集群,需要一个 Eureka 服务器、若干个服务提供者。我们可以将业务组件注册到 Eureka 服务器中,其他客户端组件可以向服务器获取服务并且进行远程调用。Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址;提供者:启动后向 Eureka 注册自己信息(地址,提供什么服务);消费者:向 Eureka 订阅服务,Eureka 会将对应服务的所有提供者地址列表发送给消费者,并且定期更新;心跳(续约):提供者定期通过 http 方式向 Eureka 刷新自己的状态。

1.1.3 相关依赖

<!-- 需要确定 Spring Cloud 版本 -->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

1.2 搭建 EurekaServer

1.2.1 相关依赖

  现在都是子父工程,我们将子模块中都需要用的依赖放到父工程的 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <packaging>pom</packaging>
 <modules>
 <module>eureka</module>
 </modules>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>2.2.10.RELEASE</version>
 <relativePath/> <!-- lookup parent from repository -->
 </parent>
 <groupId>com.software</groupId>
 <artifactId>spring-cloud</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>spring-cloud</name>
 <description>Demo project for Spring Boot</description>

 <properties>
 <java.version>1.8</java.version>
 <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
 </properties>

 <dependencies>
 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
 </dependency>
 <!-- 演示就不使用数据库了 -->
		<!--<dependency>-->
		<!--<groupId>org.springframework.boot</groupId>-->
		<!--<artifactId>spring-boot-starter-data-jpa</artifactId>-->
		<!--</dependency>-->
 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <!-- H 版 Spring Cloud 将 server 与 client 分开了,需要导入两个坐标 -->
 <dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
 </dependency>
 <dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
 </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>

1.2.2 声明为 Eureka Server

  在 eureka 服务的启动类上使用 @EnableEurekaServer,声明当前应用为 Eureka 服务。

/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description Eureka 启动类
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
 public static void main(String[] args) {
 SpringApplication.run(EurekaApplication.class, args);
 }
}

1.2.3 配置文件

server:
 port: 8081

spring:
 application:
 name: eurekaServer # 应用名称,在 Eureka 中作为 id 标识

eureka:
 client:
 register-with-eureka: false # 不注册自己
 fetch-registry: false # 不拉取自己
 service-url:
 defaultZone: http://127.0.0.1:8081/eureka/ # EurekaServer 的地址,如果是集群,需要加上其它 Server 的地址

1.2.4 启动服务

  启动服务访问对应的端口就可以看到以下界面,现在是一个服务都没有注册上来。可以把 register-with-eurekafetch-registry 两个配置取消就可以看到 eureka 自己了。

1.3 提供者

1.3.1 声明为 Eureka Client

  在服务提供者启动类中使用 @EnableDiscoveryClient,让 Eureka 能够发现,扫描到该服务。@EnableEurekaClient 注解也能实现但是该注解只支持 Eureka 作为注册中心,@EnableDiscoveryClient 可以是其他注册中心,建议使用 @EnableDiscoveryClient

/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description 服务提供者启动类
 */
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
 public static void main(String[] args) {
 SpringApplication.run(ProviderApplication.class, args);
 }
}

1.3.2 配置文件

server:
 port: 8082

spring:
 application:
 name: ProviderServer # 应用名称,在 Eureka 中作为 id 标识

eureka:
 client:
 service-url:
 defaultZone: http://127.0.0.1:8081/eurake/

1.3.3 提供服务

/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description
 */

@RestController
@RequestMapping("/provider")
public class ProviderController {

 @GetMapping("/get")
 public Object get() {
 return "你已经消费了";
 }
}

1.3.4 启动服务

  启动服务之后,会自动将自己注册到 Eureka 中

1.4 消费者

1.4.1 声明为 Eureka Client

/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description 消费者启动类
 */
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
 public static void main(String[] args) {
 SpringApplication.run(ConsumerApplication.class, args);
 }

	// 将 RestTemplate 交由容器管理
 @Bean
 public RestTemplate getRestTemplate() {
 return new RestTemplate();
 }
}

1.4.2 配置文件

server:
 port: 8083

spring:
 application:
 name: ConsumerServer # 应用名称,在 Eureka 中作为 id 标识

eureka:
 client:
 service-url:
 defaultZone: http://127.0.0.1:8081/eureka

1.4.3 消费服务

  我们之前使用 RestTemplate 需要自己写 URI,这样很不利于维护,而且容易出错,现在只需要确定应用名称,利用应用名称从 Eureka 中就可以获取到详细信息。

/**
 * Created with IntelliJ IDEA.
 *
 * @author gaohu9712@163.com
 * @date 2020/10/29
 * @description
 */
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

 @Autowired
 private DiscoveryClient discoveryClient;

 @GetMapping("/go")
 public void go() {
 List<ServiceInstance> providerServer = discoveryClient.getInstances("ProviderServer");

 if (0 == providerServer.size()) {
  return;
 }

 ServiceInstance serviceInstance = providerServer.get(0);
 String host = serviceInstance.getHost();
 int port = serviceInstance.getPort();
 URI uri = serviceInstance.getUri();
 System.out.println("主机:" + host);
 System.out.println("端口:" + port);
 System.out.println("uri:" + uri);

 RestTemplate restTemplate = new RestTemplate();
 String str = restTemplate.getForObject(uri + "/provider/get", String.class);
 System.out.println(str);
 }
}

1.4.4 启动服务

1.4.5 请求服务

1.4.6 执行流程

 ♞ 先启动 eureka 注册中心
 ♞ 启动服务提供者 provider
 ♞ 服务提供者启动后会把自身信息(比如服务地址以别名方式注册进 eureka)
 ♞ 消费者 consumer 服务在需要调用接口时,使用服务别名去注册中心获取实际的 RPC 远程调用地址
 ♞ 消费者获得调用地址后,底层实际是利用 HttpClient 技术实现远程调用
 ♞ 消费者获得服务地址后会缓存在本地 jvm 内存中,默认每间隔 30 秒更新一次服务调用地址

1.5 补充配置

1.5.1 actuator 信息完善

  我们现在的服务注册到 Eureka 上面是没有 ip 地址的,以后等服务搭建集群是很不方便的,所以我们需要让他显示自己的 ip 地址;第二个就是服务名称为主机 + 服务名 + 端口,这样就暴露了主机名,我们可以指定显示的名称。

在配置文件中添加如下配置,通过健康检查(http://ip:port/actuator/health)查看是否修改成功。

eureka:
 instance:
 # 实例名称
 instance-id: consumer-01
 # 地址中显示 ip
 prefer-ip-address: true

1.5.2 自我保护机制 ☞ 概述

  我们可以看到 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.它代表了 Eureka 保护模式的开启。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
  默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与 Eureka Server 之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。为了防止 Eureka Client 可以正常运行,但是与 Eureka Server 网络不通情况下,Eureka Server 不会立刻将 Eureka Client 服务剔除。

☞ 关闭自我保护机制

  我们之前的 Eureka 截图中可以看到 DESKTOP-GL7GS52:ConsumerServer:8083consumer-01 两个同时存在,这明明是一个服务,修改完配置之后前面的没有剔除,这就是因为自我保护机制打开了。

# Eureka Server 配置
eureka:
 server:
 # 关闭自我保护模式, 默认为打开
 enable-self-preservation: false
 # 续期时间,即扫描失效服务的间隔时间
 eviction-interval-timer-in-ms: 5000 

# Eureka Client 配置
eureka:
 instance:
 # Eureka Client 给 Eureka Server 发送心跳的时间间隔,默认 30 单位是 s
 lease-renewal-interval-in-seconds: 1
 # Eureka Server 最后一次收到心跳的等待上限,超时剔除服务,默认 90 单位是 s
 lease-expiration-duration-in-seconds: 2

1.6 Eureka 高可用

1.6.1 Eureka 集群搭建

  在之前的单体中我们的端口是随意的,但是搭建集群我们需要对端口进行规划,例如将 808X 端口作为 Eureka 集群的端口。先来看下配置有什么区别,起初我们是将自己注册到自己上,现在我们需要将自己注册到其他 Eureka 上,有多个则用 , 隔开。

server:
 port: 8081

spring:
 application:
 name: eurekaServer

eureka:
 client:
 register-with-eureka: false
 fetch-registry: false
 service-url:
 defaultZone: http://127.0.0.1:8082/eureka
 server:
 enable-self-preservation: false
 eviction-interval-timer-in-ms: 5000
server:
 port: 8082

spring:
 application:
 name: eurekaServer_back

eureka:
 client:
 register-with-eureka: false
 fetch-registry: false
 service-url:
 defaultZone: http://127.0.0.1:8081/eureka
 server:
 enable-self-preservation: false
 eviction-interval-timer-in-ms: 5000


1.6.2 Privoder 集群

  服务提供者的集群配置了多个 Eureka 地址,会将自己同时注册到多个 Eureka 上,除了配置文件以外其他的服务代码完全一致,也可以加以区分是哪个提供的服务。需要注意的是 Eureka 集群的应用名称可以不一致甚至不写,但是服务提供者的应用名称必须保持一致,否则会被认为不是一个服务。

server:
 port: 8091

spring:
 application:
 name: ProviderServer # 应用名称,在 Eureka 中作为 id 标识

eureka:
 client:
 service-url:
 defaultZone: http://127.0.0.1:8081/eureka, http://127.0.0.1:8082/eureka
 instance:
 instance-id: provider-prim
 prefer-ip-address: true
 lease-renewal-interval-in-seconds: 1
 lease-expiration-duration-in-seconds: 2
server:
 port: 8092

spring:
 application:
 name: ProviderServer

eureka:
 client:
 service-url:
 defaultZone: http://127.0.0.1:8081/eureka, http://127.0.0.1:8082/eureka
 instance:
 instance-id: provider-back
 prefer-ip-address: true
 lease-renewal-interval-in-seconds: 1
 lease-expiration-duration-in-seconds: 2

1.6.3 远程调用

/**
 * Created with IntelliJ IDEA.
 *
 * @author Demo_Null
 * @date 2020/10/29
 * @description
 */
@RestController
@RequestMapping("/consumer")
public class ConsumerController {

 @Autowired
 private DiscoveryClient discoveryClient;

 @GetMapping("/go")
 public void go() {
 List<ServiceInstance> providerServer = discoveryClient.getInstances("ProviderServer");

 if (0 == providerServer.size()) {
  return;
 }

 RestTemplate restTemplate = new RestTemplate();

 for (ServiceInstance instance : providerServer) {
  System.out.print(instance.getUri() + "---");
  String url = instance.getUri() + "/provider/get";
  System.out.println(restTemplate.getForObject(url, String.class));
 }
 }
}

  咱们可以使用服务发现 DiscoveryClient 来获取服务信息,但是无法自动选择使用那个服务,这里就涉及到 Ribbon 负载均衡了。我们可以将 RestTemplate 交由 Ioc 管理,在注入时使用 @LoadBalanced 注解进行负载均衡。

☞ 源码

到此这篇关于Spring Cloud 系列之注册中心 Eureka的文章就介绍到这了,更多相关Spring Cloud 注册中心Eureka内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring-Cloud Eureka注册中心实现高可用搭建

    前言: spring-cloud为基础的微服务架构,所有的微服务都需要注册到注册中心,如果这个注册中心阻塞或者崩了,那么整个系统都无法继续正常提供服务,所以,这里就需要对注册中心进行集群,换言之,高可用(HA) 前提: 阅读并完成第一个注册中心的项目,环境无需改变.本文是 模拟的高可用 , 可以复制两个注册中心的项目单独修改各自的配置文件达到同样的效果 修改hosts,在文件末添加两行如下: 127.0.0.1 peer1 127.0.0.1 peer2 推荐使用notepad++,如果是win

  • Spring cloud Eureka注册中心搭建的方法

    前提  系统安装jdk1.8及以上,配置好maven的ide(这里用idea进行演示,maven版本3.5,配置阿里云源) 项目搭建 新建一个maven项目,创建最简单的那种就好,项目名这里为EurekaServerDemo,包名什么的随意,项目打包方式为jar, 也可以使用spring官方的生成器,官方的生成器会创建基础的springboot项目结构.这里为了演示,都可以 修改pom文件,参考如下,版本推荐和本文相同,springboot和cloud版本的坑很多 <?xml version=&qu

  • springcloud实现注册中心Eureka

    Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组件之一. 背景介绍 服务中心 服务中心又称注册中心,管理各种服务功能包括服务的注册.发现.熔断.负载.降级等,比如dubbo admin后台的各种功能. 有了服务中心调用关系会有什么变化,画几个简图来帮忙理解 项目A调用项目B 正常调用项目A请求项目B 有了服务中心之后,任何一个服务都不能直接去掉用

  • 详解spring-cloud与netflixEureka整合(注册中心)

    基础依赖 compile('org.springframework.boot:spring-boot-starter-actuator') compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.cloud:spring-cloud-starter') eureka(单机) 服务端: 依赖 compile('org.springframework.cloud:spring-c

  • spring cloud实现Eureka注册中心的HA的方法

    前言: 在前面的例子中,我们的Eureka Server都是单节点的,一旦该节点在生产中挂掉,就无法再提供服务的注册,为了保证注册中心的高可用,在生产中一般采用多节点的服务注册中心. 一.在hosts文件中加入如下配置 127.0.0.1 peer1 127.0.0.1 peer2 二.修改application.yml配置文件 --- spring: profiles: peer1 # 指定profile=peer1 application: name: Eureka-Server1 serv

  • Spring Cloud 系列之注册中心 Eureka详解

    1.1 简介 1.1.1 概述   Netflix Eureka 是由 Netflix 开源的一款基于 REST 的服务发现组件,包括 Eureka Server 及 Eureka Client.2012 年 9 月在 GitHub 上发布 1.1.2 版本,目前 Netflix 以宣布闭源,所以市面上还是以 1.x 版本为主.Eureka 提供基于 REST 的服务,在集群中主要用于服务管理.Eureka 提供了基于 Java 语言的客户端组件,客户端组件实现了负载均衡的功能,为业务组件的集群

  • spring cloud alibaba Nacos 注册中心搭建过程详解

    这篇文章主要介绍了spring cloud alibaba Nacos 注册中心搭建过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 nacos下载地址 什么是 Nacos? nacos主要起到俩个作用一个是注册中心,另外一个是配置中心. 下面图 是nacos的功能结构图 运行环境 JDK 1.8+: Maven 3.2.x+: 下载 你可以通过源码和发行包两种方式来获取 Nacos. nacos发行包下载地址 选择版本解压 unzip

  • SpringBoot实现服务接入nacos注册中心流程详解

    目录 概述 接入nacos注册中心 springboot服务pom文件 application.properties配置 源码分析 小结 源码流程图 概述 某些场景下只需要把springboot微服务化而不想引入springcloud如何实现的呢? 下面我们介绍nacos注册中心方案. 接入nacos注册中心 springboot服务pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h

  • Spring Cloud Gateway动态路由Apollo实现详解

    目录 背景 路由的加载 实现动态路由 背景 在之前我们了解的Spring Cloud Gateway配置路由方式有两种方式 通过配置文件 spring: cloud: gateway: routes: - id: test predicates: - Path=/ms/test/* filters: - StripPrefix=2 uri: http://localhost:9000 通过JavaBean @Bean public RouteLocator routeLocator(RouteL

  • Spring Cloud GateWay 路由转发规则介绍详解

    Spring在因Netflix开源流产事件后,在不断的更换Netflix相关的组件,比如:Eureka.Zuul.Feign.Ribbon等,Zuul的替代产品就是SpringCloud Gateway,这是Spring团队研发的网关组件,可以实现限流.安全认证.支持长连接等新特性. Spring Cloud Gateway Spring Cloud Gateway是SpringCloud的全新子项目,该项目基于Spring5.x.SpringBoot2.x技术版本进行编写,意在提供简单方便.可

  • Spring Cloud 的 Hystrix.功能及实践详解

    一.概述 在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身间题出现调用故障或延迟,而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会因等待出现故障的依赖方响应形成任务积压,最终导致自身服务的瘫痪. 所以我们引入了断路器,类似于物理上的电路,当电流过载时,就断开电路,就是我们俗称的"跳闸".同理,服务间的调

  • Spring cloud Feign 深度学习与应用详解

    简介 Spring Cloud Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单.Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数.格式.地址等信息.Feign会完全代理HTTP请求,开发时只需要像调用方法一样调用它就可以完成服务请求及相关处理.开源地址:https://github.com/OpenFeign/feign.Feign整合了Ribbon负载和Hystrix熔断,可以不再需要显式地

  • Java Spring Cloud Bus 实现配置实时更新详解

    目录 背景 实现原理 ConfigServer改造 1. pom.xml增加以下依赖 2. 配置文件中配置暴露接口 Service改造 1. pom.xml增加以下依赖 2. 通过@RefreshScope声明配置刷新时需要重新注入 测试 总结 背景 使用Spring Cloud Config Server,启动Service时会从配置中心取配置文件,并注入到应用中,如果在Service运行过程中想更新配置,需要使用Spring Cloud Bus配合实现实时更新. 实现原理 需要借助Rabbi

  • Spring Cloud Gateway全局异常处理的方法详解

    前言 Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式.Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等

  • Spring Boot系列教程之死信队列详解

    前言 在说死信队列之前,我们先介绍下为什么需要用死信队列. 如果想直接了解死信对接,直接跳入下文的"死信队列"部分即可. ack机制和requeue-rejected属性 我们还是基于上篇<Spring Boot系列--7步集成RabbitMQ>的demo代码来说. 在项目springboot-demo我们看到application.yaml文件部分配置内容如下 ... listener: type: simple simple: acknowledge-mode: aut

随机推荐