Spring Cloud框架学习-注册中心Spring Cloud Eureka

1. Eureka介绍

Eureka是Netflix公司提供的一款服务注册中心,Eureka基于REST来实现服务的注册和发现。Spring Cloud中封装了Eureka,在Eureka的基础上,优化了一些配置并提供了可视化的界面,可以方便地查看服务的注册情况以及服务注册中心集群的运行情况。

Euraka由两部分组成:服务端和客户端。服务端就是注册中心,用来接收其他服务的注册;客户端分为服务提供者和服务消费者,是一个Java客户端。如下图所示:
在这里插入图片描述

2. Eureka搭建

Eureka本身使用Java来开发的,Spring Cloud使用Spring Boot技术对Eureka进行封装,在Spring Cloud中使用Eureka非常方便,只需要引入依赖:spring-cloud-starter-netflix-eureka-server,就可以像启动一个普通Spring Boot项目那样启动了。

1.创建一个Spring Boot项目,添加Eureka依赖。
在这里插入图片描述
2.项目创建完成后,在启动类中添加注解@EnableEurekaServer标识该项目为Eureka Server。

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    
    

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

3.在application.properties中添加基本配置信息:

#当前服务的名字
spring.application.name=eureka
#端口号(Eureka后台管理端端口)
server.port=1111
#默认情况下,Eureka Server也是一个普通的微服务,所以当它还是注册中心时,就有两层身份:
#1.注册中心;2.普通服务。默认当前eureka server自动把自己注册到注册中心中,
# 通过eureka.client.register-with-eureka=false设置不注册
eureka.client.register-with-eureka=false
#表示是否从Eureka Server上获取注册信息
eureka.client.fetch-registry=false

4.配置完成就可以启动项目,在浏览器中访问http://localhost:1111就可以查看Eureka后台管理页面了。
在这里插入图片描述

3. Eureka集群

在Spring Cloud架构中,如果注册中心只有一个,如果出故障了会导致整个服务环境不可用,所以我们需要搭建Eureka注册中心集群,实现负载均衡和故障容错。Eureka集群架构图示意图:
在这里插入图片描述
Eureka集群搭建原理是互相注册。在这个集群架构中,Eureka Server之间都进行数据同步,不区分主从节点,所有节点都是平等的。节点之间通过置顶serviceUrl来互相注册,形成集群,从而提高节点的可用性。

在Eureka服务器集群中,如果单个节点发生故障,Eureka客户端将自动切换到新的Eureka服务器。每个Eureka服务器节点彼此同步数据。Eureka服务器的连接方式可以是单线,连接方式为a->b->c,节点a的数据也将与c同步。但不建议这样写。当我们配置serviceUrl时,您可以指定多个注册地址,即a可以同时在b或c上注册。

4. Eureka架构

Eureka包含两个组件:Eureka Server和Eureka Client。
在这里插入图片描述

4.1 Eureka Server

Eureka Server主要有三个功能:

  1. 服务注册,所有的服务都注册到Eureka Server上。每个微服务节点启动后,会在Eureka Server中进行注册,这样Eureka Server中的服务注册表讲会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
  2. 提供注册表,注册表就是注册到Eureka Server上的服务列表。Eureka Client在调用服务时,需要获取这个注册表,一般来说,这个注册表会缓存下来,如果缓存失败,则直接获取最新的注册表。
  3. 同步状态,Eureka Client通过注册、心跳等机制,和Eureka Server同步当前注册中心的状态。

4.2 Eureka Client

Eureka Client主要用来简化每一个服务和Eureka Server之间的交互。Eureka Client会自动拉取更新以及缓存Eureka Server中的信息,这样即使Eureka Server所有节点都宕机,Eureka Client依然能够获得想要调用的服务。(但是地址可能不准确)。

Eureka Client提供了以下功能:

  • 服务注册

服务提供者将自己注册到服务注册中心Eureka Server,所谓的服务提供者,只是一个业务上的划分,其本质上就是一个Eureka Client。Eureka Client向Eureka Server注册后会提供自身的元数据信息,例如IP地址、端口、名称、运行状态等等信息。

  • 服务续约

Eureka Client注册到Eureka Server之后,==默认情况下,Eureka每隔30s就要向Eureka Server发送一条心跳消息,来告诉Eureka Server它还在运行。==如果Eureka Server连续90秒都没有收到Eureka Client的续约消息,Eureka Server会认为这个Eureka Client已经掉线,并将其从服务注册列表中剔除。

服务续约相关功能有两个相关的属性(一般不建议修改):

#服务续约时间,默认30s
eureka.instance.lease-renewal-interval-in-seconds=30
#未续约的服务失效时间,默认90s
eureka.instance.lease-expiration-duration-in-seconds=90
  • 服务下线

当Eureka Client下线时,它会主动发送一条消息告诉Eureka Server,它要下线了。

  • 获取注册表信息

Eureka Client从Eureka Server上获取服务的注册信息,并将其缓存在本地。本地客户端在需要调用远程服务时,会从该信息中查找远程服务所对应的IP地址、端口等信息。Eureka Client上缓存的服务注册信息会定期更新(30秒),如果Eureka Server返回的注册表信息与本地缓存的注册表信息不同的话,Eureka Client会自动处理。
涉及到的两个属性:

#是否获取注册表信息,默认为true
eureka.client.fetch-registry=true
#定期更新的时间间隔,默认为30秒
eureka.client.registry-fetch-interval-seconds=30

4.3 Eureka自我保护

默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会注销该微服务实例。但是当网络分区故障发生延时、卡顿、拥挤时,微服务与Eureka Server之间无法正常通信,但是因为微服务其实是健康的,此时不应该下线这个微服务实例。Eureka通过“自我保护模式”来解决这个问题----当Eureka Server节点在短时间内丢失过多客户端时,那么Eureka进入自我保护模式,Eureka Server不会立刻将Eureka Client服务下线。

5. 服务注册

服务注册就是将一个微服务注册到Eureka Server上,这样其他的服务想要调用该服务时,就只需要从Eureka Server上查询该服务的信息,然后完成服务调用。

要创建一个服务提供者provider,只需要在Spring Boot项目中添加以下两个依赖:

 <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>

然后在application.properties中配置项目的注册地址,就可以将该服务提供者Provider注册到Eureka Server上:

#服务名
spring.application.name=provider
#服务端口号
server.port=1113
#注册中心url地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka

然后,首先启动服务注册中心Eureka Server,待其启动完成后再启动服务提供者provider。等到两者启动成功后,在浏览器中输入http://localhost:1111就可以查看当前服务注册中心中的注册信息。
在这里插入图片描述

6. 服务消费

首先在模块provider中提供一个接口:

@RestController
public class HelloController {
    
    
  @Value("${server.port}")
  Integer port;

  @GetMapping("/hello")
  public String hello(){
    
    
    return "hello world port:"+port;
  }
}

然后创建一个consumer模块,同样添加spring-boot-starter-web和spring-cloud-starter-netflix-eureka-client依赖。

 <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>

创建完成后在application.properties中配置注册信息

#服务名称
spring.application.name=consumer
#端口号
server.port=1114
#注册中心的url地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka

然后提供一个接口,消费服务提供者提供的接口,然后借助Eureka Client提供的DiscoveryClient工具,根据服务名从Eureka Server上查询到一个服务的详细信息,并使用RestTemplate工具类来发起请求。

@SpringBootApplication
public class ConsumerApplication {
    
    

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

  @Bean
  RestTemplate restTemplate(){
    
    
    return new RestTemplate();
  }
}
@RestController
public class HelloController {
    
    
  @Autowired
  DiscoveryClient discoveryClient;
  @Autowired
  RestTemplate restTemplate;

  @GetMapping("/hello2")
  public String hello2(){
    
    
    HttpURLConnection httpConnection=null;
    //如果是集群部署会有多个
    List<ServiceInstance> providerList = discoveryClient.getInstances("provider");
    ServiceInstance provider=providerList.get(0);
    String host = provider.getHost();
    int port=provider.getPort();
    StringBuffer providerUrl = new StringBuffer("http://").append(host)
                                                          .append(":")
                                                          .append(port)
                                                          .append("/hello");
    //通过RestTemplate实现服务的调用
    String result = restTemplate.getForObject(providerUrl.toString(), String.class);
    return result;
  }
}

配置RestTemplate的负载均衡功能,需要添加注解@LoadBalanced来开启

@SpringBootApplication
public class ConsumerApplication {
    
    

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

  @Bean
  RestTemplate restTemplate(){
    
    
    return new RestTemplate();
  }
}
  @Bean
  @LoadBalanced
  RestTemplate balancedRestTemplate(){
    
    
    return new RestTemplate();
  }

猜你喜欢

转载自blog.csdn.net/huangjhai/article/details/107501646