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等等亚马逊云独有的概念,完全无需担心,这些概念在其他云服务中都可以找到对应的特性。