一、Eureka
Eureka是Netflix开发的一个服务注册和发现框架,通常被用于构建微服务架构中的服务治理体系。作为Spring Cloud Netflix组件之一,Eureka被广泛用于Spring Cloud项目中来实现服务的注册与发现。
核心概念
- 服务注册中心(Eureka Server): 提供服务注册和发现的服务器。各个微服务启动时,会将自己的网络地址注册到Eureka Server中,这样Eureka Server中便拥有了所有服务实例的信息。
- 服务提供者(Service Provider): 微服务实例,它将自己的服务信息注册到Eureka Server,以供其他服务查询和调用。
- 服务消费者(Service Consumer): 需要调用其他微服务的客户端,它从Eureka Server中获取所需服务的网络位置信息后,才能进行服务调用。
工作原理
- 服务注册: 当服务提供者启动时,它会向Eureka Server发送自己的服务信息(如服务名称、主机名、端口等),并在Eureka Server中注册。
- 服务同步: 在Eureka集群模式下,各个Eureka Server之间会相互复制注册信息,确保数据的一致性。
- 服务续约: 服务提供者会每隔一定时间(默认30秒)向Eureka Server发送心跳,以续约其在注册中心的存活状态。如果Eureka Server在一定时间内(默认90秒)没有接收到某个服务实例的心跳,它将会从服务注册表中移除该实例。
- 服务下线: 当服务提供者正常关闭时,它会向Eureka Server发送服务下线请求,Eureka Server接收到请求后将该服务实例从注册表中删除。
- 服务获取: 服务消费者从Eureka Server获取注册表信息,并缓存到本地。服务调用时,消费者通过本地缓存的信息来选择合适的服务实例进行调用。
特点
- 自我保护机制: Eureka Server在检测到网络故障导致服务实例心跳失败比例过高时,会进入自我保护模式,此时不会剔除任何服务实例,以免因网络分区问题导致大量服务下线,从而保持服务的高可用。
- 负载均衡: Eureka客户端内置了负载均衡机制,可以在多个服务实例之间进行智能均衡调用。
- 易于集成和使用: 与Spring Cloud体系集成紧密,配置简单,易于扩展和维护。
Eureka通过这些机制,有效地实现了服务治理,提高了微服务架构的稳定性和弹性。
二、CAP理论
CAP理论是分布式系统中一个非常重要的概念,由加州大学伯克利分校的计算机科学家Eric Brewer在2000年提出。CAP代表一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance),这三个属性在分布式系统的设计中至关重要。理论指出,一个分布式系统最多只能同时满足这三个属性中的两个。
CAP三要素
- 一致性(Consistency): 所有节点在同一时间具有相同的数据。在进行过某项更新的操作之后,任何后续的访问都将返回最新的数据,或者是错误的信息。这种一致性是逻辑一致性,并非所有节点在同一时刻的物理数据一致性。
- 可用性(Availability): 每个请求都能在有限的时间内接收到一个响应,不论个别的节点故障如何。响应可能是最新的数据,也可能不是,但是必须是有效的数据。
- 分区容忍性(Partition tolerance): 系统能够在任何网络分区发生的情况下继续运行。网络分区意味着网络中任意信息的丢失。一个具备分区容忍性的系统可以在任何网络分区后继续提供服务。
理论的实际应用
在实际应用中,分布式系统通常要在一致性和可用性之间做权衡,因为分区容忍性在现代网络环境下是一个必须要保证的属性(否则系统的某个部分可能由于网络故障而被孤立)。
- CA(一致性和可用性): 如果系统不需要分区容忍性,那么系统可以在不考虑网络分割的情况下,同时保证一致性和可用性。但这样的系统在现实中较少见,因为大多数网络环境都不能保证完全不发生分区。
- CP(一致性和分区容忍性): 系统在遇到网络分区时,仍然能保证数据的一致性,但可能牺牲部分可用性。例如,某些节点可能因为无法确定数据的最新状态而拒绝服务。
- AP(可用性和分区容忍性): 系统在网络分区发生时依然能够对外提供服务,但不保证所有节点的数据一致性。最终一致性(eventual consistency)是AP系统常见的数据一致性模型。
结论
CAP理论提供了一个有用的框架来理解不同分布式系统设计所面临的权衡。虽然理论指出无法同时实现三者,但实际应用中,系统设计者通常会根据业务需求的优先级来动态调整一致性和可用性的级别,同时尽量保持系统对分区的容忍性。
三、在spring boot构建的spring cloud 项目中 如何创建Eureka-server
Spring Boot中创建一个Eureka Server非常直接,主要分为几个步骤:添加依赖、配置应用、启用Eureka Server,然后运行它。下面是详细的步骤:
1. 创建Spring Boot项目
首先,你需要一个基本的Spring Boot项目。可以使用Spring Initializr来快速生成项目结构。
2. 添加依赖
在项目的pom.xml
文件中,添加Eureka Server的依赖。如果你正在使用Maven,可以添加如下依赖:
XML
<dependencies>
<!-- Eureka Server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 添加Spring Boot Starter Test,用于测试 -->
<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>
这里的${spring-cloud.version}
需要替换为当前稳定的Spring Cloud版本,例如2020.0.3
。请访问Spring Cloud官方文档查看最新版本。
3. 配置Eureka Server
在你的Spring Boot项目中的application.properties
或application.yml
文件中添加Eureka的基本配置:
如果是application.properties
:
XML
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.instance.hostname=localhost
如果是application.yml
:
XML
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
instance:
hostname: localhost
这些配置设定了Eureka Server的端口为8761,并告诉Eureka Server它自己不是一个客户端(不需要将自己注册到其他Eureka Server上)。
4. 启用Eureka Server
在你的Spring Boot应用的主类上添加@EnableEurekaServer
注解来启用Eureka Server功能:
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
现在,一切都配置好了,你只需要运行这个Spring Boot应用。可以直接在IDE中运行,或者通过命令行使用Maven或Gradle构建并运行。
启动后,访问http://localhost:8761
,你应该能看到Eureka的控制台,这表示你的Eureka Server已经正常运行。
以上就是在Spring Boot项目中设置Eureka Server的基本步骤。这样设置后,你可以开始将其他微服务注册到这个Eureka Server上了。
四、服务注册与服务发现
要实现服务注册和发现的具体代码,我可以给你展示如何在一个使用Spring Cloud和Eureka的环境中进行配置和编码。这里包括了如何创建Eureka服务器、服务提供者和服务消费者的示例代码。
步骤1:设置Eureka服务器
我之前已经描述了如何设置一个Eureka服务器。这里我们只关注代码部分。在Spring Boot应用的主类中使用@EnableEurekaServer
注解来激活Eureka服务器。
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
步骤2:创建服务提供者
服务提供者会注册自己到Eureka服务器。这需要在pom.xml
中添加Eureka客户端依赖,然后在Spring Boot的主类中使用@EnableDiscoveryClient
注解。
XML
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceProviderApplication.class, args);
}
}
java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceController {
@GetMapping("/service")
public String service() {
return "Hello from Service Provider";
}
}
步骤3:创建服务消费者
服务消费者同样需要添加Eureka客户端依赖,并在主类中使用@EnableDiscoveryClient
。然后,使用RestTemplate
或Feign
客户端从Eureka获取服务并进行调用。
添加依赖(如果使用Feign):
XML
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
}
java
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "service-provider")
public interface ServiceProviderClient {
@GetMapping("/service")
String getService();
}
@RestController
public class ServiceController {
@Autowired
private ServiceProviderClient serviceProviderClient;
@GetMapping("/consume")
public String consume() {
return serviceProviderClient.getService();
}
}