SpringCloud2.x(二)微服务注册与发现——Eureka

如果直接在服务消费者项目指定服务提供者地址的话,会带来很多问题。比如

  • 服务提供者的网络地址(IP和端口)发生了变化,服务消费者无法自动感知,需要手动修改并重新部署。
  • 无法动态增减每个微服务的集群节点。
  • 服务之间调用混乱,难于管理。

服务发现组件提供了解决以上问题的能力。

一、服务发现简介

  • 服务提供者、服务消费者、服务发现组件这三者的关系大致如下:
  • 各个微服务在启动时,将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些信息。
  • 服务消费者可从服务发现组件查询服务提供者的网络地址,并使用该地址调用服务提供者的接口。
  • 各个微服务与服务发现组件使用一定机制(例如心跳)通信。服务发现组件如长时间无法与某微服务实例通信,就会注销该实例。
  • 微服务网络地址发生变更(例如实例增减或者IP端口发生变化等)时,会重新注册到服务发现组件。使用这种方式,服务消费者就无需人工修改提供者的网络地址了。

综上,服务发现组件应该具备以下功能:

  • 服务注册表:是服务发现组件的核心,它用来记录各个微服务的信息,例如微服务的名称、IP、端口等。服务注册表提供查询API和管理API,查询API用于查询可用的微服务实例,管理API用于服务的注册和注销。
  • 服务注册与服务发现:服务注册是指微服务在启动时,将自己的信息注册到服务发现组件上的过程。服务发现是指查询可用微服务列表及其网络地址的机制。
  • 服务检查:服务发现组件使用一定机制定时检测已注册的服务,如发现某实例长时间无法访问,就会从服务注册表中移除该实例。 

服务发现组件的其它叫法:服务注册、服务发现或注册中心。Spring Cloud提供了多种服务发现组件的支持,例如Eureka、Consul和Zookeeper等。 

二、Eureka简介

Eureka是Netflix开源的服务发现组件,本身是一个基于REST的服务。它包含Server和Client两部分。

PS:Eureka 2.x已宣布闭源,不过可能是临时的。

三、Eureka原理

SpringCloud2.x(二)微服务注册与发现——Eureka_第1张图片 Eureka架构图
  • Application Service:相当于服务提供者
  • Application Client:相当于服务消费者
  • Make Remote Call:可理解成调用RESTful API的行为 

Eureka包含两个组件:Eureka Server和Eureka Client,它们的作用如下:

  • Eureka Server提供服务发现的能力,各个微服务启动时,会向Eureka Server注册自己的信息(例如IP、端口、微服务名称等)。Eureka Server会存储这些信息。
  • Eureka Client是一个Java客户端,用于简化与Eureka Server的交互。
  • 微服务启动后,会周期性(默认30秒)地向Eureka Server发送心跳以续约自己的“租期”。
  • 如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例。
  • 默认情况下,Eureka Server同时也是Eureka Client。多个Eureka Server实例,互相之间通过复制的方式,来实现服务注册表中数据的同步。
  • Eureka Client会缓存服务注册表中的信息。这种方式有一定的优势——首先,微服务无需每次请求都查询Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server所有节点都宕掉,服务消费者依然可以使用缓存的信息找到服务提供者并完成调用。

Eureka通过心跳检查、客户端缓存等机制,提供了系统的灵活性、可伸缩性和可用性。

四、Eureka的使用

1、编写Eureka Server

1)新建maven项目microservice-eureka,pom.xml文件引入spring boot、spring cloud和eureka-server的相关依赖。



    4.0.0

    cn.zhh
    microservice-eureka
    1.0
    
    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.1.RELEASE
    

    
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                Finchley.M7
                pom
                import
            
        
    
    
    
    	
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-server
        
    

    
    
        
            spring-milestones
            Spring Milestones
            https://repo.spring.io/libs-milestone
            
                false
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

2)在application.yml加上以下配置。

## 服务端口
server:
  port: 8080
 
eureka:
  instance:
    hostname: localhost
  client:
    ## 因为该应用为注册中心,所以设置为false,代表不向注册中心注册自己
    registerWithEureka: false
    ## 因为该应用为注册中心,职责就是维护服务实例信息,并不需要去检索服务,所以设置为false。 
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

3)启动类加上EnableEurekaServer注解。

@SpringBootApplication
@EnableEurekaServer
public class MicroserviceEurekaApplication {

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

}

4)启动项目,浏览器访问http://localhost:8080/,看到以下页面说明Eureka服务端运行成功。

SpringCloud2.x(二)微服务注册与发现——Eureka_第2张图片

2、将微服务注册到Eureka Server

1)新建maven项目microservice-provider,pom.xml文件引入spring boot、spring cloud和eureka-server的相关依赖。



    4.0.0

    cn.zhh
    microservice-provider
    1.0
    
    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.0.1.RELEASE
    

    
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                Finchley.M7
                pom
                import
            
        
    
    
    
    	
        
            org.springframework.boot
            spring-boot-starter-web
        
		
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
		
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
    

    
    
        
            spring-milestones
            Spring Milestones
            https://repo.spring.io/libs-milestone
            
                false
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

2)在application.yml加上以下配置。主要是应用名(用于标记服务)、要注册到的Eureke注册中心地址。

server:
  port: 8081
spring:
  application:
    name: provider-pay
 
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/

3)编写一个支付API的控制器。

@RestController
public class PayController {

	@GetMapping("/pay")
	public String pay() {
		return "支付功能调用成功!";
	}
}

4)在项目启动类加上EnableDiscoveryClient注解。

@SpringBootApplication
@EnableDiscoveryClient // 相当于服务发现组件的门面,也可以使用@EnableEurekaClient
public class MicroserviceProviderApplication {

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

}

5)启动应用,可以看到服务已经注册到Eureka Server上了。

五、Eureka Server的高可用

Eureka Client会定时连接Eureka Server,获取服务注册表中的信息并缓存在本地。微服务在消费远程API时总是使用本地缓存中的数据。因此一般来说,即使Eureka Server发生宕机,也不会影响到服务之间的调用。但如果Eureka Server宕机时,某些微服务也出现了不可用的情况,Eureka Client中的缓存若不被更新,就可能会影响到微服务的调用,甚至影响到整个应用系统的高可用性。因此,通常会部署一个高可用的Eureka Server集群。

Eureka Server可以通过运行多个实例并相互注册的方式实现高可用部署,Eureka Server实例会彼此增量地同步信息,从而确保所有节点数据一致。事实上,节点之间相互注册时Eureka Server的默认行为。

下面来构造一个双节点Eureka Server集群(3个节点、4个节点...也是类似的,只要将自己的节点都注册到别的节点上就可以了)。

1)配置系统的hosts,Windows系统的hosts文件路径是C:\Windows\System32\drivers\etc\hosts,Linux及Mac OS等系统的文件路径是/etc/hosts。

127.0.0.1 ha1 ha2

2)复制项目microservice-eureka两份,将artifactId分别修改为microservice-eureka-ha1和microservice-eureka-ha2。

3)分别将application.yml修改如下,让两个节点的Eureka Server相互注册。

 

## 服务端口
server:
  port: 9081
 
eureka:
  instance:
    hostname: ha1
  client:
    ## 因为该应用为注册中心,所以设置为false,代表不向注册中心注册自己
    registerWithEureka: false
    ## 因为该应用为注册中心,职责就是维护服务实例信息,并不需要去检索服务,所以设置为false。 
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://ha2:9082/eureka/
## 服务端口
server:
  port: 9082
 
eureka:
  instance:
    hostname: ha2
  client:
    ## 因为该应用为注册中心,所以设置为false,代表不向注册中心注册自己
    registerWithEureka: false
    ## 因为该应用为注册中心,职责就是维护服务实例信息,并不需要去检索服务,所以设置为false。 
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://ha1:9081/eureka/

4)启动两个项目,分别访问http://localhost:9081/和http://localhost:9082/,都可以看到registered-replicas拥有对方节点。

 

5)将应用注册到Eureka Server集群上。

以microservice-provider项目为例, 只需修改eureka.client.serviceUrl.defaultZone,配置多个Eureka Server地址,就可以将其注册到Eureka Server集群了。

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9081/eureka/,http://localhost:9082/eureka/

其实,微服务即使只配置Eureka Server集群中的某个节点,也能正常注册到Eureka Server集群,因为多个Eureka Server之间的数据会相互同步。不过,避免某些极端场景,还是建议在客户端配置多个Eureka Server节点。

六、Eureka的自我保护模式

默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。

Eureka通过“自我保护模式”来解决这个问题——当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka就会保护服务注册表中的信息,不会删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动推出自我保护模式。

SpringCloud2.x(二)微服务注册与发现——Eureka_第3张图片

可以将eureka.server.enable-self-preservation设置为false禁用自我保护模式(默认为true),一般在开发环境中使用。

七、多网卡环境下的IP选择

Spring Cloud提供了按需选择IP的能力。

1、忽略指定名称的网卡

spring:
  cloud:
    inetutils:
      ignored-interfaces:
      - docker0
      - vetch.*

这样就可以忽略docker0网卡以及所有以vetch开头的网卡。

2、使用正则表达式,指定使用的网络地址

spring:
  cloud:
    inetutils:
      preferred-networks:
      - 192.168
      - 10.0

3、只使用站点本地地址

spring:
  cloud:
    inetutils:
      use-only-site-local-interfaces: true

这样就可以强制使用站点本地地址。

4、手动指定IP地址

eureka:
  instance:
    prefer-ip-address: true
    ip-address: 127.0.0.1

八、Eureka的健康检查

在Eureka Server首页,可以看到以下信息

在Status一栏有个UP,表示应用程序状态正常。应用状态还有其它取值,例如DOWN、OUT_OF_SERVICE、UNKNOWN等。只有标记为“UP”的微服务会被请求。

你可能感兴趣的:(Spring,Cloud,2.x)