Eureka 注册中心看这一篇就够了
哈喽沃德先生 人气:2
服务注册中心是服务实现服务化管理的核心组件,类似于目录服务的作用,主要用来存储服务信息,譬如提供者 url 串、路由信息等。服务注册中心是微服务架构中最基础的设施之一。
在微服务架构流行之前,注册中心就已经开始出现在分布式架构的系统中。Dubbo 是一个在国内比较流行的分布式框架,被大量的中小型互联网公司所采用,它提供了比较完善的服务治理功能,而服务治理的实现主要依靠的就是注册中心。
## 什么是注册中心
注册中心可以说是微服务架构中的“通讯录”,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/timg.jfif)
举个现实生活中的例子,比如说,我们手机中的通讯录的两个使用场景:
> 当我想给张三打电话时,那我需要在通讯录中按照名字找到张三,然后就可以找到他的手机号拨打电话。—— 服务发现
>
> 李四办了手机号并把手机号告诉了我,我把李四的号码存进通讯录,后续,我就可以从通讯录找到他。—— 服务注册
>
> 通讯录 —— ?什么角色(提示:服务注册中心)
总结:服务注册中心的作用就是**服务的注册**和**服务的发现**。
## 常见的注册中心
- Netflix Eureka
- Alibaba Nacos
- HashiCorp Consul
- Apache ZooKeeper
- CoreOS Etcd
- CNCF CoreDNS
| 特性 | Eureka | Nacos | Consul | Zookeeper |
| :-------------- | :---------- | :------------------------- | :---------------- | :--------- |
| CAP | AP | CP + AP | CP | CP |
| 健康检查 | Client Beat | TCP/HTTP/MYSQL/Client Beat | TCP/HTTP/gRPC/Cmd | Keep Alive |
| 雪崩保护 | 有 | 有 | 无 | 无 |
| 自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
| 访问协议 | HTTP | HTTP/DNS | HTTP/DNS | TCP |
| 监听支持 | 支持 | 支持 | 支持 | 支持 |
| 多数据中心 | 支持 | 支持 | 支持 | 不支持 |
| 跨注册中心同步 | 不支持 | 支持 | 支持 | 不支持 |
| SpringCloud集成 | 支持 | 支持 | 支持 | 支持 |
## 为什么需要注册中心
了解了什么是注册中心,那么我们继续谈谈,为什么需要注册中心。在分布式系统中,我们不仅仅是需要在注册中心找到服务和服务地址的映射关系这么简单,我们还需要考虑更多更复杂的问题:
- 服务注册后,如何被及时发现
- 服务宕机后,如何及时下线
- 服务如何有效的水平扩展
- 服务发现时,如何进行路由
- 服务异常时,如何进行降级
- 注册中心如何实现自身的高可用
这些问题的解决都依赖于注册中心。简单看,注册中心的功能有点类似于 DNS 服务器或者负载均衡器,而实际上,注册中心作为微服务的基础组件,可能要更加复杂,也需要更多的灵活性和时效性。所以我们还需要学习更多 Spring Cloud 微服务组件协同完成应用开发。
## 注册中心解决了什么问题
- 服务管理
- 服务的依赖关系管理
## 什么是 Eureka 注册中心
Eureka 是 Netflix 开发的服务发现组件,本身是一个基于 REST 的服务。Spring Cloud 将它集成在其子项目 Spring Cloud Netflix 中,实现 Spring Cloud 的服务注册与发现,同时还提供了负载均衡、故障转移等能力。
## Eureka 注册中心三种角色
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/timg-1578234270981.jfif)
### Eureka Server
通过 Register、Get、Renew 等接口提供服务的注册和发现。
### Application Service(Service Provider)
服务提供方,把自身的服务实例注册到 Eureka Server 中。
### Application Client(Service Consumer)
服务调用方,通过 Eureka Server 获取服务列表,消费服务。
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578648274465.png)
## Eureka 入门案例
### 创建项目
我们创建聚合项目来讲解 Eureka,首先创建一个 pom 父工程。
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113319718.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578822985788.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578823080703.png)
### 添加依赖
pom.xml
```xml
```
### 注册中心 eureka-server
在刚才的父工程下创建 `eureka-server` 注册中心的项目。
#### 创建项目
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578836332989.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113447822.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578239500169.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113547468.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578823384080.png)
#### 添加依赖
pom.xml
```xml
```
#### 配置文件
application.yml
```yml
server:
port: 8761 # 端口
spring:
application:
name: eureka-server # 应用名称
# 配置 Eureka Server 注册中心
eureka:
instance:
hostname: localhost # 主机名,不配置的时候将根据操作系统的主机名来获取
client:
register-with-eureka: false # 是否将自己注册到注册中心,默认为 true
fetch-registry: false # 是否从注册中心获取服务注册信息,默认为 true
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://${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);
}
}
```
#### 访问
访问:http://localhost:8761/
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578243640844.png)
## 高可用 Eureka 注册中心
### 注册中心 eureka-server
#### 创建项目
在刚才的父工程下再创建一个 `eureka-server02` 注册中心的项目,如果是多机器部署不用修改端口,通过 IP 区分服务,如果在一台机器上演示需要修改端口区分服务。
#### 添加依赖
pom.xml
```xml
```
#### 配置文件
集群配置下,注册中心需要相互注册实现信息的同步。
eureka-server 的 application.yml
```yml
server:
port: 8761 # 端口
spring:
application:
name: eureka-server # 应用名称(集群下相同)
# 配置 Eureka Server 注册中心
eureka:
instance:
hostname: eureka01 # 主机名,不配置的时候将根据操作系统的主机名来获取
client:
# 设置服务注册中心地址,指向另一个注册中心
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://localhost:8762/eureka/
```
eureka-server02 的 application.yml
```yml
server:
port: 8762 # 端口
spring:
application:
name: eureka-server # 应用名称(集群下相同)
# 配置 Eureka Server 注册中心
eureka:
instance:
hostname: eureka02 # 主机名,不配置的时候将根据操作系统的主机名来获取
client:
# 设置服务注册中心地址,指向另一个注册中心
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://localhost:8761/eureka/
```
#### 启动类
启动类不变,启动两个 server。
#### 访问
访问:http://localhost:8761/ 或者 http://localhost:8762/ 都出现如下图说明互相注册成功。
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578311267949.png)
`Status` 显示方式为默认值,如果想要清晰可见每个服务的 IP + 端口需要通过以下配置来实现。
#### 显示 IP + 端口
一个普通的 Netflix Eureka 实例注册的 ID 等于其主机名(即,每个主机仅提供一项服务)。 Spring Cloud Eureka 提供了合理的默认值,定义如下:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}},也就是:主机名:应用名:应用端口。
我们也可以可以自定义进行修改:
```yml
eureka:
instance:
prefer-ip-address: true # 是否使用 ip 地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
```
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578311606022.png)
### 服务提供者 service-provider
#### 创建项目
在刚才的父工程下创建一个 `service-provider` 服务提供者的项目。
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578836246536.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113447822.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578288878277.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/image-20200213113547468.png)
![](https://mrhelloworld.com/resources/articles/spring/spring-cloud/eureka/1578824040960.png)
#### 添加依赖
pom.xml
```xml
```
#### 配置文件
application.yml
```yml
server:
port: 7070 # 端口
spring:
application:
name: service-provider # 应用名称(集群下相同)
# 配置 Eureka Server 注册中心
eureka:
instance:
prefer-ip-address: true # 是否使用 ip 地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
client:
service-url: # 设置服务注册中心地址
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
```
#### 实体类
Product.java
```java
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {
private Integer id;
private String productName;
private Integer productNum;
private Double productPrice;
}
```
#### 编写服务
ProductService.java
```java
package com.example.service;
import com.example.pojo.Product;
import java.util.List;
/**
* 商品服务
*/
public interface ProductService {
/**
* 查询商品列表
*
* @return
*/
List
加载全部内容