注册中心简介
微服务架构中最核心的部分是服务治理,服务治理最基础的组件是注册中心,随着微服务架构的发展,出现了很多微服务架构的解决方案,比较熟知的有Spring Cloud全家桶和基于Dubbo的相关组合套件
针对注册中心dubbo 支持了 Zookeeper、Redis、Multicast 和 Simple,官方推荐 Zookeeper。Spring Cloud 支持了 Zookeeper、Consul、Eureka,也可结合阿里开源的Nacos官方推荐 Eureka。
使用量较多的几种注册中心对比如下,
注册中心对比
| 对比项 | Eureka | Nacos | Consul | Zookeeper |
|---|---|---|---|---|
| CAP | AP | CP + AP | CP | CP |
| 一致性算法 | 无 | Raft | Raft | Paxos |
| 健康检查 | Client Beat | TCP/HTTP/MySQL/Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
| 负载均衡策略 | Ribbon | 权重、metadata、selector | Fabio | - |
| 雪崩保护 | 有 | 有 | 无 | 无 |
| 自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
| 访问协议 | TCP | HTTP/DNS | HTTP/DNS | TCP |
cap是指在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance),这三个要素最多只能同时实现两点,不可能三者兼顾
- 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值(等同于所有节点访问同一份最新的数据副本)
- 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求(对数据更新具备高可用性)
- 分区容忍性(P),就是高可用性,一个节点崩了,并不影响其他的节点(5个节点,挂了两个,不影响服务) Eureka的设计原则是AP(可用性和分区容错性),它保证了注册中心的可用性,但舍弃了数据一致性(各个节点的数据有可能是不一致的,会保证最终一致性)
Eureka架构
本文重点介绍Eureka,其他组件会在后续文章中进行介绍
Eureka是Netflix基于Rest服务的,服务注册、发现组件,主要包括Eureka Server 和Eureka Client 两个组件
- Eureka Server:提供服务注册服务,各节点启动后会在Eureka Server中注册,并在服务注册表中存储所有可用服务节点的信息
- Eureka Client:一个Java Client,用于简化Eureka Server的交互,同时作为轮询负载均衡器,提供服务故障的切换支持
-
Eureka Server 注册中心
- 启动后,从其他节点拉取服务注册信息
- 运行过程中,定时运行evict(剔除)任务,剔除没有按时renew(续约)的服务(包括非正常停止和网络故障的服务)
- 运行过程中,接收到的register、renew、cancel请求,都会同步至其他注册中心节点
-
Service Provider 服务提供者
- 启动后,想注册中心发起register请求,注册服务
- 在运行过程中,定时向注册中心发送renew心跳,证明“我还活着”
- 停止服务提供者,向注册中心发起cancel请求,清空当前服务注册信息
-
Service Consumer 服务消费者
- 启动后,从注册中心拉取服务注册信息
- 在运行过程中,定时更新服务注册信息
- 服务消费者发起远程调用
项目实战
代码及配置
pom.xml
<parent>
<artifactId>spring-cloud</artifactId>
<groupId>com.kk</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
parent pom.xml
<groupId>com.kk</groupId>
<artifactId>spring-cloud</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-server</module>
<module>user-service</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring.boot.version>2.1.5.RELEASE</spring.boot.version>
<spring.cloud.version>Finchley.SR1</spring.cloud.version>
<spring.eureka.version>2.1.2.RELEASE</spring.eureka.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>${spring.eureka.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
注册中心启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
配置文件 application.yml
server:
port: 8090
spring:
application:
name: eureka-server
eureka:
instance:
prefer-ip-address: true
hostname: localhost
client:
# 设置是否将自己作为客户端注册到注册中心(缺省true)
# 这里为不需要(查看@EnableEurekaServer注解的源码,会发现它间接用到了@EnableDiscoveryClient)
register-with-eureka: false
# 设置是否从注册中心获取注册信息(缺省true)
# 因为这是一个单点的EurekaServer,不需要同步其它EurekaServer节点的数据,故设为false
fetch-registry: false
# 设置eureka服务器所在的地址,查询服务和注册服务都需要依赖这个地址
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/