博客园:程序开发者社区:使用并认识Eureka注册中心
博客园:程序开发者社区:搭建高可用Eureka注册中心
Eureka 注册中心看这一篇就够了
在微服务架构中,服务注册与发现是核心组件之一,手动指定每个服务是很低效的, Spring cloud提供了多种服务注册与发现的实现方式,例如: Eureka、Consu、 Zookeeper
SringCloud支持得最好的是 Eureka,其次是 Consul,再次是 Zookeeper。
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)
由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡,在此 Zookeeper保证的是CP而 Eureka则是AP。
在 ZooKeeper中,当 master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行 leader选举,但是问题在于,选举 leader需要一定时间,且选举期间整个 ZooKeeper集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得 ZooKeeper集群失去 master节点是大概率事件,虽然服务最终能够恢复,但是在选举时间内导致服务注册长期不可用是难以容忍的。
Eureka优先保证可用性, Eureka各个节点是平等的,某几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka的客户端在向某个 Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台 Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)
所以 Eureka在网络故障导致部分节点失去联系的情况下,只要有一个节点可用,那么注册和查询服务就可以正常使用,而不会像 zookeeper那样使整个注册服务瘫痪, Eureka优先保证了可用性。
SpringCloud要使用 Eureka注册中心非常简单和方便, SpringCloud中的Eureka服务注册中心实际上也是一个SpringBoot工程,我们只需通过引入相关依赖和注解配置就能让 SpringBoot构建的微服务应用轻松地与Eureka进行整合,他不像Zookeeper那样需要安装独立的Zookeeper服务。
<!--使用spring cloud要添加依赖管理-->
>
>
>
>org.springframework.cloud >
>spring-cloud-dependencies >
>Finchley.SR4 >
>pom >
>import >
>
>
>
<!--eureka服务端依赖-->
>
>org.springframework.cloud >
>spring-cloud-starter-netflix-eureka-server >
>
spring:
application:
name: springcloud-eureka-server
server:
port: 8700
#设置该服务中心的hostname,指定ip,该实例名称不能重复
eureka:
instance:
hostname: localhost
client:
#由于我们目前创建的应用是一个服务注册中心,而不是一个普通的应用,默认情况下,这个应用会向注册中心(也是它自己)注册它自己,设置为false表示禁止这种自己向自己注册的默认行为
register-with-eureka: false
#表示是否从Eureka Server获取注册信息,默认为true。如果这是一个单点的 Eureka Server,不需要同步其他节点的数据,可以设为false。
fetch-registry: false
#指定服务注册中心的位置
#如果是集群,Eureka集群相互指向注册中心
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
server:
#自我保护模式默认是自动开启的,可以选择关闭,禁用自我保护模式,保证不可用的服务及时剔除
enable-self-preservation: true
#剔除失效服务间隔单位ms,默认1分钟
eviction-interval-timer-in-ms: 20000
#留存的服务示例低于多少比例进入保护模式,默认85%
renewal-percent-threshold: 0.5
在服务提供者加入Eureka客户端依赖
<!--spring cloud集成eureka客户端的起步依赖-->
>
>org.springframework.cloud >
>spring-cloud-starter-netflix-eureka-client >
>
在主类上添加@EnableEurekaClient注解
修改服务提供者的application.yml配置添加Eureka注册中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:8700/eureka
服务的发现由 eureka客户端实现,而服务的消费由 Ribbon实现也就是说服务的调用需要 eureka客户端和 Ribbon两者配合起来才能实现。
在调用服务提供者时使用 Ribbon来调用
@LoadBalanced //加入ribbon的支持,那么在调用时,即可改为使用服务名称来访问
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
加入ribbon的支持,那么在调用时,即可改为使用服务名称来访问,将ip:port改为服务名称调用就行了。
restTemplate.getForEntity("http://SPRINGCLOUD-SERVICE-PROVIDER/service/hello",String.class).getBody();
在微服务架构的这种分布式系统中,我们要充分考虑各个微服务组件的高可用性问题,不能有单点故障,由于注册中心Eureka本身也是一个服务,如果它只有一个节点,那么它有可能发生故障,这样我们就不能注册与查询服务了,所以我们需要—个高可用的服务注册中心,这就需要通过注册中心集群来解决。Eureka服务注册中心它本身也是一个服务,它也可以看做是一个提供者,又可以看做是一个消费者,我们之前通过配置eureka.client.register-with-eureka= false让注册中心不注册自己,但是我们可以向其他注册中心注册自己。
Eureka server的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就会形成一组互相注册的服务注册中心,进而实现服务清单的互相同步,往注册中心A上注册的服务,可以被复制同步到注册中心B上,所以从任何一台注册中心上都能查询到已经注册的服务,从而达到高可用的效果。
Eureka注册中心高可用集群就是各个注册中心相互注册。
复制Eureka服务端(springcloud-eureka-server)的application.yml为application-eureka8701.yml,application-eureka8702.yml,我们让8701和8702的Eureka服务相互注册。
修改application-eureka8701.yml相应的配置如下:
spring:
application:
name: springcloud-eureka-server
server:
port: 8701
#设置该服务中心的hostname,指定ip,该实例名称不能重复
eureka:
instance:
hostname: eureka8701
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka8702:8702/eureka
修改application-eureka8701.yml相应的配置如下:
spring:
application:
name: springcloud-eureka-server
server:
port: 8702
#设置该服务中心的hostname,指定ip,该实例名称不能重复
eureka:
instance:
hostname: eureka8702
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka8701:8701/eureka
<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.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>eureka-demoartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.4.RELEASEversion>
parent>
<properties>
<spring-cloud.version>Hoxton.SR1spring-cloud.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
project>
在刚才的父工程下创建 eureka-server 注册中心的项目。
添加依赖:
<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.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>eureka-serverartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>com.examplegroupId>
<artifactId>eureka-demoartifactId>
<version>1.0-SNAPSHOTversion>
parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
dependencies>
project>
```yml
配置文件:
application.yml
server:
port: 8761 # 端口
spring:
application:
name: eureka-server # 应用名称
eureka:
instance:
hostname: localhost # 主机名,不配置的时候将根据操作系统的主机名来获取
client:
register-with-eureka: false # 是否将自己注册到注册中心,默认为 true
fetch-registry: false # 是否从注册中心获取服务注册信息,默认为 true
service-url: # 注册中心对外暴露的注册地址
defaultZone: http:// e u r e k a . i n s t a n c e . h o s t n a m e : {eureka.instance.hostname}: eureka.instance.hostname:{server.port}/eureka/
此时如果直接启动项目是会报错的,错误信息:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect,这是因为 Eureka 默认开启了将自己注册至注册中心和从注册中心获取服务注册信息的配置,如果该应用的角色是注册中心并是单节点的话,要关闭这两个配置项。
启动类:
EurekaServerApplication.java
```java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
// 开启 EurekaServer 注解
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}