Euraka是Netflix开发的开源框架。Spring-Cloud Euraka是Euraka的Spring Cloud组件。当然Spring-Cloud还集成了诸如:Zookepper、Consul等组件。他们都可以实现服务发现的相关过程。
在目前Web开发中,主要使用Euraka,原因如下所示:
服务发现支持其他语言开发的服务注册和发现,微服务架构更好的提供了异构的工具集。 关于为什么使用Euraka作为服务发现工具可以参见这篇文章: dockone.io/article/78
www.itmuch.com/spring-clou… 周立老师的Spring 教程系列
本人只是对这篇文章中的示例做了细节的描述,并且把一些基础的、容易迷惑的点做了细节的补充,大家可以先看周立老师的教程,然后来这里补充一些基础的概念。
<?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>org.bruce.study</groupId> <artifactId>UserRegisterService</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <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> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 引入H2数据库 --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> </dependencies> <!-- 引入spring cloud的依赖,管理Spring Cloud生态各组件的版本 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR2</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> 复制代码
关键点描述
由于Spring Cloud具有很多个版本,在Maven中需要配置Spring Boot的parent节点,该节点指定了当前Web项目使用的Spring Boot版本:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> 复制代码
还需要使用dependencyManagement节点指定当前使用的Spring Cloud版本号:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> 复制代码
为什么Spring Boot不使用最新版本?(写此文章时,Spring Boot最新版本是2.3.1)
Spring Cloud不同版本要求使用的Spring Boot版本不一致,具体参见下表:
版本号 | 说明 | 是否推荐使用 |
---|---|---|
纯数字版本号 | 开发版 | 开发团队内部使用,不是很稳定 |
GA | 稳定版 | 相比于开发版,基本上可以使用了 |
PRE(M1、M2) | 里程碑版 | 主要是修复了一些BUG的版本,一个GA后通常有多个里程碑版 |
RC | 候选发布版 | 该阶段的软件类似于最终版的一个发行观察期,基本只修复比较严重的BUG |
SR | 正式发布版 | 可以投入生产的版本 |
++https://start.spring.io/actuator/info++ Spring Cloud与Spring Boot版本兼容性规则参见此网址相关版本说明(JSON格式)
通过Maven配置,我们构建分布式服务主要使用了:
前三个的作用大家应该都懂了,>spring-cloud-starter-netflix-eureka-client用于当前分布式服务被识别为一个Eureka客户端。Eureka客户端将可以被注册至Eureka服务器。
package org.bruce.study.controller; import org.bruce.study.Entities.User; import org.bruce.study.dao.UserDao; 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Optional; @RestController @RequestMapping("/users") public class UserController { @Autowired private UserDao userDao; @GetMapping("/{id}") public Optional<User> getUserById( @PathVariable Integer id) { return this.userDao.findById(id); } } 复制代码
Spring Boot 2.0.x相关知识请自行学习。
以上就是我们的服务提供了一个通过用户ID查询用户的服务,该服务提供Get请求方式。
application.yml文件
server: # 指定Tomcat端口 port: 8088 spring: application: name: userservice jpa: # 让hibernate打印执行的SQL show-sql: true logging: level: root: INFO # 配置日志级别,让hibernate打印出执行的SQL参数 org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE management: endpoint: health: # 是否展示健康检查详情 show-details: always eureka: client: service-url: # 指定eureka server通信地址,注意/eureka/小尾巴不能少 defaultZone: http://localhost:8761/eureka/ instance: # 是否注册IP到eureka server,如不指定或设为false,那就会注册主机名到eureka server prefer-ip-address: true 复制代码
配置项 | 说明 |
---|---|
region | 当前客户端所在默认服务分区(默认值:us-east-1) |
availability.zones | 配置region下可用的分区(zone),多个zone使用逗号分隔,这里顺序很重要,系统会按照配置的顺序优先从前面的URL开始加载 |
serviceUrl | 配置获取应用注册的服务器地址,多个服务器地址使用逗号分隔 |
registry-fetch-interval-seconds | 从服务端获取最新的注册信息的时间步长,单位:秒。如果获取超时,第二次获取时间会翻倍 |
register.with.eureka | 是否将当前服务注册至Eureka服务器。设置为false,即说明当前服务仅仅获取其他服务访问地址,当其本身并不注册至Eureka服务器。这样可以保护一些私密的接口访问(诸如:员工身份令牌认证服务,仅仅调用外部服务发现,但其本身并不注册至Eureka服务器)。 |
fetch.registry | 是否需要从服务端获取注册信息,服务端如果是集群需要配置为true。 |
instance-info-replication-interval-seconds | 扫描本地实例的时间步长,单位:秒。如果有变化向Eureka服务器重新注册当前服务。 |
配置项 | 说明 |
---|---|
lease-renewal-interval-in-seconds | 向服务器心跳的时间步长,单位:秒。当Eureka客户端第一次向服务端心跳成功,服务端将返回404,客户端后续会接着注册本地实例,注册成功,后续心跳返回200。 |
prefer-ip-address | 当Eureka客户端注册至Eureka服务器时,是以ip地址还是主机名的方式注册当前服务。(建议:IP) |
ip.address | 当前Eureka客户端指定该Eureka实例的IP地址,当不配置该项时默认取第一个网卡的非回环地址。 |
lease-expiration-duration-in-seconds | 当前Eureka服务端驱逐客户端的时间步长,单位:秒。Eureka服务端在满足一定条件时,将会移除一些已经无法访问的Eureka客户端。如果Eureka服务端超过90秒未收到某个客户端心跳,且该客户端未开启自我保护,Eureka服务端就会驱逐该客户端。如果该客户端开启自我保护,但是上一分钟注册的客户端数 > 服务端上一分钟收到客户端的心跳数 * 每分钟续约因子(0.85),也会驱逐客户端。 |
项目名称:EurekaDemoServer
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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.bruce.study</groupId> <artifactId>EurekaDemoServer</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server --> <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> <!-- 引入spring cloud的依赖,不能少,主要用来管理Spring Cloud生态各组件的版本 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Finchley.SR2</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> 复制代码
Spring Cloud版本、Spring Boot版本等相关部分参见本章前文部分
package org.bruce.study; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class EurecaDemoServer { public static void main(String[] args) { SpringApplication.run(EurecaDemoServer.class, args); } } 复制代码
使用@EnableEurekaServer进行注解,该类即被认为是EurekaServer的启动类。
server: port: 8761 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:8761/eureka/ 复制代码
为什么Eureka Server配置中出现了Client和Instance的配置?
答:任何一个Eureka Server首先是一个Eureka Client。任何一个Eureka Clent都是一个Eureka Instance。
回忆一下 IS A原则(李氏替换原则)
为什么要这么设计?
答:Eureka Instance即Eureka实例,他主要包含了诸如心跳、服务状态回报等等基础的网络通信机制。Eureka Client可以被认为是Eureka Instance的扩展,它提供了更多、更实用的配置,包括诸如获取IP地址等等一些易用性的配置。至于为什么这么设计?很简单,就是为了保障Eureka Server也可以作为一个Eureka Client在其他Eureka Server上注册。
这是什么意思呢?
就是我做了一个商城订单付款服务,深圳服务器上部署了Eureka Server1,沈阳服务器步数了Eureka Server2,Eureka Server1可以注册在Eureka Server2 上,Eureka Server2也可以注册在Eureka Server1上。Eureka Server1和Eureka Server2的服务将被增量更新到他们的服务注册表中去,这样用户访问就不会因为某一台服务器宕机导致整个服务无法访问,这就是保障了高可用性。
Long long time ago,Netfix为了让全美都可以访问他们部署在亚马逊云上的相关服务,编写了Eureka。所以Eureka配置中保留了很多亚马逊云中的相关概念,诸如伸缩服务等等相关概念。但是一定要明白亚马逊云作为始祖级别的云服务,他的很多概念在其他云服务中都存在,因为已经成为了一种习惯,大家都在沿用这些概念,所以Eureka无论实在阿里云或者腾讯云中,都可以无缝的部署和运行。所以对于Eureka配置中遗留的一些诸如ASG等等亚马逊云独有的概念,完全无需担心,这些概念在其他云服务中都可以找到对应的特性。