Fork me on GitHub

Eureka简介及简单使用

前言

Eureka是Spring Cloud Netflix微服务套件中的一部分,一般与SpringBoot构建的微服务进行整合。它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。

服务治理可以说是微服务架构中最为核心和基础的模块。服务治理通常包含服务注册和服务发现两部分。

Eureka包含客户端和服务端部分。

  • Eureka服务端,我们也称为服务注册中心。它支持高可用配置。它依托于强一致性提供良好的服务实例可用性,可以应对多种不同的故障场景。如果Eureka以集群模式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中的其他分片就会把它们的状态再次同步回来。不同可用区域的服务注册中心通过异步模式互相复制各自的状态,这意味着在任意给定的时间点每个实例关于所有服务的状态是有细微差别的。

  • Eureka客户端,主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,嵌在客户端应用程序的代码中,在应用程序运行时,Eureka客户端向注册中心注册自身提供的服务并周期性的发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并进行周期性的刷新服务状态。

正文

我们今天先简单通过例子了解一下Eureka,后面在对其进行一些深入研究。

Eureka服务端

我们创建一个Eureka服务端,如下:

  • 新建SpringBoot项目,命名为eureka-server

    upload successful

  • 选择Eureka Server依赖

    upload successful

  • Eureka Server 的配置

    • 首先我们需要启用EurekaServer,如下:

      1
      2
      3
      4
      5
      6
      7
      8
      @SpringBootApplication
      @EnableEurekaServer
      public class EurekaServerApplication {

      public static void main(String[] args) {
      SpringApplication.run(EurekaServerApplication.class, args);
      }
      }
    • 在application.properties里进行相关配置,如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      # 应用名称
      spring.application.name=eureka-server
      # 实例端口
      server.port=8001
      # server地址
      server.address=172.30.13.173
      # 实例名称
      eureka.instance.hostname=test1
      # 实例ID
      eureka.instance.instance-id=${server.address}:${server.port}
      # 是否向注册中心注册自己
      eureka.client.register-with-eureka=false
      # 是否需要检索服务
      eureka.client.fetch-registry=false
      # 使用IP地址定义主机名
      eureka.instance.prefer-ip-address=true
      # eureka服务地址
      eureka.client.service-url.defaultZone = http://172.30.13.173:8001/eureka/

我们启动EurekaServer,通过 http://172.30.13.173:8001/ 进行访问,可以看到如下图,Eureka注册中心中尚未有可以使用的实例。

upload successful

Eureka 客户端

我们再新创建一个项目sakura-service,并为其添加web模块和eureka-client模块,以使其注册到eureka中心上。

upload successful

启用服务发现,@EnableDiscoveryClient。

1
2
3
4
5
6
7
8
9
@EnableDiscoveryClient
@SpringBootApplication
public class SakuraServiceApplication {

public static void main(String[] args) {
SpringApplication.run(SakuraServiceApplication.class, args);
}

}

application.properties进行如下相关配置。

1
2
3
4
5
6
# 实例端口
server.port=9001
# 应用名称
spring.application.name=sakura-service
# eureka服务地址
eureka.client.service-url.defaultZone = http://172.30.13.173:8001/eureka/

我们在该项目中新建一个SakuraController类,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@RestController
public class SakuraController {

// 服务注册
@Qualifier("eurekaRegistration")
@Autowired
private Registration registration;

@Autowired
private DiscoveryClient client;

@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String index(){
ServiceInstance instance = serviceInstance();
System.out.println("Host:"+instance.getHost()+";ServiceID:"+instance.getServiceId());
return "Hello World";
}

public ServiceInstance serviceInstance() {
List<ServiceInstance> list = client.getInstances(registration.getServiceId());
if (list != null && list.size() > 0) {
return list.stream().findAny().get();
}
return null;
}
}

在启动此项目,可以看到此项目已被注册到了注册中心上。

upload successful

我们在创建一个服务消费者用于消费刚才我们创建的服务Service。

需要添加web模块,eureka-client模块和ribbon模块,Ribbon是一个基于HTTP和TCP的客户端负载均衡器,它可以通过客户端配置的ribbonServerList服务端列表去轮询达到负载均衡的目的,和Eureka联合使用时,Ribbon会从Eureka的注册中心获取服务列表去轮询。关于Ribbon的内容,我们后面在研究。

upload successful

启用服务发现,@EnableDiscoveryClient。并添加RestTemplate,如下:

1
2
3
4
5
6
7
8
9
10
11
12
@EnableDiscoveryClient
@SpringBootApplication
public class SakuraConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SakuraConsumerApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}

application.properties进行如下相关配置。

1
2
3
4
5
6
# 实例端口
server.port=7001
# 应用名称
spring.application.name=sakura-consumer
# eureka服务地址
eureka.client.service-url.defaultZone = http://172.30.13.173:8001/eureka/

我们在项目中新建SakuraController用于对sakura-service的hello服务进行调用,如下:

1
2
3
4
5
6
7
8
9
10
@RestController
public class SakuraController {
@Autowired
RestTemplate restTemplate;

@RequestMapping(value = "/consumer",method = RequestMethod.GET)
public String hello(){
return restTemplate.getForEntity("http://SAKURA-SERVICE/hello",String.class).getBody();
}
}

启动此项目,可以发现此项目也被注册到了Eureka注册中心。

upload successful

我们尝试访问消费者,http://172.30.13.173:7001/consumer 可以看到打印了 sakura-service的 Hello World 字样,同时 sakura-service项目日志中输出相关信息。

1
Host:DELL-3020-PC;ServiceID:SAKURA-SERVICE

高可用Eureka注册中心

上面的例子,当我们关掉Eureka服务端时,可以发现两个项目之间已经无法进行相互调用了。因此,单节点的服务注册中心是不合理的。

所以作为注册中心,应具备高可用性的特征。

Eureka Server在设计的一开始就考虑了高可用的问题,在Eureka的服务治理设计中,所有节点既是服务提供方,也是服务消费方,服务注册中心也不例外。

我们在配置单节点的注册中心时,设置过如下两个参数,让服务注册中心不注册自己。

1
2
3
4
# 是否向注册中心注册自己
eureka.client.register-with-eureka=false
# 是否需要检索服务
eureka.client.fetch-registry=false

Eureka Server 的高可用实际上就是将自己作为服务向其他服务注册中心注册自己,这样就形成一组相互注册的服务注册中心,以实现服务清单的相互同步,达到高可用的效果。

下面我们来尝试搭建高可用的服务注册中心集群,我们构建一个三节点的服务注册中心集群。

在搭建之前,我们需要知道SpringBoot是支持多环境配置的,其命名格式需要满足 application-{profile}.properties的格式,其中{profile}对应环境标识,如下:

  • application-dev.properties: 开发环境
  • application-test.properties: 测试环境
  • application-prod.properties: 生产环境

至于要加载那个配置文件,需要在application.properties 文件中通过spring.profiles.active 属性来设置,spring.profiles.active=dev 就会加载 application-dev.properties配置。

另外我们在启动项目时,可以通过 java -jar xxxxx.jar –spring.profiles.active = test 来指定使用哪个配置。

根据上面所述,我们可以在原来eureka-server项目里创建3份properties文件,如下:

  • application-test1.properties

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 应用名称
    spring.application.name=eureka-server
    # 实例端口
    server.port=8001
    # server地址
    server.address=172.30.13.173
    # 实例名称
    eureka.instance.hostname=test1
    # 实例ID
    eureka.instance.instance-id=${server.address}:${server.port}
    # 是否向注册中心注册自己
    eureka.client.register-with-eureka=true
    # 是否需要检索服务
    eureka.client.fetch-registry=true
    # 使用IP地址定义主机名
    eureka.instance.prefer-ip-address=true
    # eureka服务地址
    eureka.client.service-url.defaultZone = http://172.30.13.173:8002/eureka/,http://172.30.13.173:8003/eureka/
  • application-test2.properties

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 应用名称
    spring.application.name=eureka-server
    # 实例端口
    server.port=8002
    # server地址
    server.address=172.30.13.173
    # 实例名称
    eureka.instance.hostname=test2
    # 实例ID
    eureka.instance.instance-id=${server.address}:${server.port}
    # 是否向注册中心注册自己
    eureka.client.register-with-eureka=true
    # 是否需要检索服务
    eureka.client.fetch-registry=true
    # 使用IP地址定义主机名
    eureka.instance.prefer-ip-address=true
    # eureka服务地址
    eureka.client.service-url.defaultZone=http://172.30.13.173:8001/eureka/,http://172.30.13.173:8003/eureka/
  • application-test3.properties

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 应用名称
    spring.application.name=eureka-server
    # 实例端口
    server.port=8003
    # server地址
    server.address=172.30.13.173
    # 实例名称
    eureka.instance.hostname=test3
    # 实例ID
    eureka.instance.instance-id=${server.address}:${server.port}
    # 是否向注册中心注册自己
    eureka.client.register-with-eureka=true
    # 是否需要检索服务
    eureka.client.fetch-registry=true
    # 使用IP地址定义主机名
    eureka.instance.prefer-ip-address=true
    # eureka服务地址
    eureka.client.service-url.defaultZone=http://172.30.13.173:8002/eureka/,http://172.30.13.173:8001/eureka/

可以看到我们在一台机器上使用了3个不同端口(8001,8002,8003)来搭建了一个Eureka服务注册中心集群。

PS: application.properties 里可以配置 spring.profiles.active=test1 让其默认使用 test1的配置。

我们使用Maven 打包生成 eureka-server-1.0.0-SNAPSHOT.jar 包,并使用 java -jar eureka-server-1.0.0-SNAPSHOT.jar –spring.profiles.active=test1 启动test1 ,相同的方式启动test2和test3。

完成后访问eureka注册中心界面(http://172.30.13.173:8001/ 或者 http://172.30.13.173:8002/ 或者 http://172.30.13.173:8003/),如图:

upload successful

可以看到Eureka形成了一组相互注册的服务注册中心。

那它的高可用性能被保证吗?

我们来测试下,我们根据上面所述,对sakura-service做成两个微服务,如下:

sakura-service项目的配置文件

  • application-test1.properties

    1
    2
    3
    server.port=9001
    spring.application.name=sakura-service
    eureka.client.service-url.defaultZone = http://172.30.13.173:8001/eureka/,http://172.30.13.173:8002/eureka/,http://172.30.13.173:8003/eureka/
  • application-test2.properties

    1
    2
    3
    server.port=9002
    spring.application.name=sakura-service
    eureka.client.service-url.defaultZone = http://172.30.13.173:8001/eureka/,http://172.30.13.173:8002/eureka/,http://172.30.13.173:8003/eureka/

启动它们,可以看到服务注册中心已经有了它们的实例。

upload successful

我们启动消费者项目sakura-consumer将其也注册到注册中心。

upload successful

访问 http://172.30.13.173:7001/consumer 可以看到两个注册的sakura-service交替输出信息,这也是使用ribbon可以做到负载均衡的体现。

upload successful

这时候我们停止掉 eureka-server 的test1 ,可以看到 使用consumer调用 sakura-service的服务仍然正常。

可以看到test2和test3仍然正常进行服务,我们也可以继续停掉test2,可以看到test3正常服务,保证注册中心的服务正常进行。

upload successful

总结

今天我们研究了Eureka注册中心的使用及如何创建一个高可用的注册中心,后面会结合Eureka的源码详细了解Eureka使用及特点。




-------------文章结束啦 ~\(≧▽≦)/~ 感谢您的阅读-------------

SakuraTears wechat
扫一扫关注我的公众号
您的支持就是我创作的动力!
0%