基础应用
Eureka简介
- Eureka是一个基于REST的服务,主要在AWS云中使用,定位服务来进行中间层服务器的负载均衡和故障转移。
- SpringCloud封装了Netflix公司开发的Eureka模块来实现服务注册和发现。Eureka采用了C-S的设计架构。EurekaServer作为服务注册功能的服务器, 它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server,并维持心跳连接。这样系统的维护人员就可以通过Eureka Server 来监控系统中各个微服务是否正常运行。SpringCloud的一些其他模块(比如Zuul)就可以通过Eureka Server来发现系统中的其他微服务,并执行相关的逻辑。
- Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。
版本要求
搭建Eureka服务注册中心
新建一个springboot项目,命名为eureka-server,spring-cloud版本为:Hoxton.SR5
添加依赖
- parent的pom配置
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.xx</groupId>
<artifactId>study-springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>study-springcloud</name>
<packaging>pom</packaging>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Dalston.SR1</spring-cloud.version>
</properties>
<modules>
<module>eureka</module>
</modules>
<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>
- Eurake Server依赖pom 。主要依赖如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
yml配置
server:
port: 8761
eureka:
instance:
# eureka注册中心的实例名称
hostname: localhost
client:
# false表示不想注册中心注册自己
register-with-eureka: false
# false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与Eureka Server交互的地址(查询和注册服务)
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: eureka-server
启动类
只需要一个注解@EnableEurekaServer,这个注解需要在springboot工程的启动application类上添加。
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- Eureka Server既可以独立部署,也可以集群部署。在集群部署的情况下,Eureka Server间会进行注册表信息同步的操作,这时被同步注册表信息的Eureka Server将会被其他同步注册表信息的Eureka Server称为peer。
- 上述配置中的service-url指向的注册中心为实例本身,通常来讲,一个Eureka Server也是Eureka Client,它会尝试注册自己,所以需要至少一个注册中心的URL来定位对等点peer。如果不提供这样一个注册端点,注册中心也能工作,但是会在日志中打印无法向peer注册自己的信息。在独立(Standalone)Eureka Server的模式下,Eureka Server一般会关闭作为客户端注册自己的行为。
- Eureka Server和Eureka Client之间的联系主要通过心跳的方式实现,心跳(Heartbeat)即Eureka Client定时向Eureka Server汇报本服务实例当前的状态,维护本服务实例在注册表中有效性。
- Eureka Serve需要随时维持最新的服务实例信息,所以在注册表中的每个服务实例都需要定期发送心跳到Server中以使自己的注册保持最新的状态(数据一般直接保存在内存中)。为了避免Eureka Client在每次服务间调用都向注册中心请求依赖服务实例的信息,Eureka Client将定时从Eureka Server中拉取注册表中的信息,并将这些信息缓存到本地,用于服务发现。
搭建Eureka服务客户端
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
yml配置
server:
port: 8080
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
# 自定义服务名称信息
instance-id: eureka-provider:8080
#访问路径可以显示Ip地址
prefer-ip-address: true
spring:
application:
# 对应的微服务名字(eureka会自动改为全大写)
name: eureka-provider
info:
app.name: study-springcloud
company.name: www.xxx.com
build.artifactId: @project.artifactId@
build.version: @project.version@
actuator与注册微服务信息
- 当前工程添加actuator端点监控:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 父工程添加maven插件,读取配置
<build>
<finalName>study-springcloud</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
</plugins>
</build>
- 配置yml
info:
app.name: study-springcloud
company.name: www.fengfan.com
build.artifactId: @project.artifactId@
build.version: @project.version@
提供服务接口
@RestController
@RequestMapping("/api")
public class ProviderController {
@Value("${server.port}")
private String serverPort;
@PostMapping("/sayHello")
public String sayHello(String name) {
return "我是服务端" + serverPort + ",你好" + name;
}
}
启动类
@SpringBootApplication
@EnableEurekaClient // 本服务启动后会自动注册进eureka服务中
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
服务调用
@Configuration
public class RestTemplateConfig {
/**
* @return org.springframework.web.client.RestTemplate
* @description 注入一个可以进行负载均衡的Rest Temple用于服务问调用
* @author fengfan
* @date 2022/5/18 14:43
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
@RequestMapping("/api")
public class ConsumerController {
@Resource
private RestTemplate restTemplate;
@PostMapping("/askHello")
public String askHello(){
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("name", "consumer8090");
ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://EUREKA-PROVIDER/api/sayHello", body, String.class);
return responseEntity.getBody();
}
}
测试
服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息,修改ProviderController内容:
@PostMapping("/discovery")
public Object discovery(){
List<String> list = client.getServices();
System.out.println(list);
List<ServiceInstance> serviceInstances = client.getInstances("EUREKA-PROVIDER");
for (ServiceInstance serviceInstance: serviceInstances){
System.out.println(serviceInstance);
}
return client;
}
@SpringBootApplication
@EnableEurekaClient // 本服务启动后会自动注册进eureka服务中
@EnableDiscoveryClient
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
Eureka的集群配置
做一个本机的域名映射
修改defaultZone参数,添加多台eureka地址(注意不要将自己加入,分别添加其他两台)
eureka:
instance:
# eureka注册中心的实例名称
hostname: localhost
client:
# false表示不想注册中心注册自己
register-with-eureka: false
# false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与Eureka Server交互的地址(查询和注册服务)
defaultZone: http://localhost:8762/eureka/,http://localhost:8763/eureka/
更改启动参数,启动不同的端口,进行模拟
Eureka和zookeeper 的区别
Zookeeper保证了CP,Eureka保证了AP。
A:高可用
C:一致性
P:分区容错性
1.当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接down掉不可用。也就是说,服务注册功能对高可用性要求比较高,但zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新选leader。问题在于,选取leader时间过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。
2.Eureka保证了可用性,Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供注册和查询服务。而Eureka的客户端向某个Eureka注册或发现时发生连接失败,则会自动切换到其他节点,只要有一台Eureka还在,就能保证注册服务可用,只是查到的信息可能不是最新的。除此之外,Eureka还有自我保护机制,默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例。如果在15分钟内超过85%的实例没有正常的心跳,那么Eureka就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况:
- Eureka不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其他节点。 因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样 使整个微服务瘫痪。