前言
本文主要聊聊Eureka注册中心的详解及其代码部署演示。
- Netlix在设计Eureka时,遵循的就是AP原则
- Eureka是Netflix的一个子模块,也是核心模块之一。
- Eureka是一个基于REST的服务, 用于定位服务,以实现
云端中间层服务发现和故障转移,服务注册与发现对于微服务来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类似于Dubbo的注册 中心,比如Zookeeper;
服务注册与发现
⑴ 对于服务的注册与发现可能很多人之前使用的是:Zookeeper,对于Zookeeper来说,它有一个客户端client,因此使用ZK时我们需要 开启一个客户端让它去链接。现在我们使用服务注册与发现使用的是"Eureka",它是基于CS架构的(包含:服务器和客户端),Euraka的服务器就相当于我们要写一个Service业务的子项目模块来当作服务器,而若使用原来的Zookeeper服务器就需要专门去下载zookeeper服务端了。这就是Eureka与Zookeeper的区别。
⑶ Euraka与Zookeeper几乎是类似的差别很小。都是实现服务注册的。
在远程过程服务调用"消费者和提供者"中-“图-Eureka注册中心-1”。
服务提供者 —配置注册中心地址并提供服务到Eureka Service。
消费者 — 到Eureka-service获取需要的服务。
⑴ 相对于之前的"Dubbo+Zookeeper"的架构实现中我们使用的注册中心是Zookeeper,消费者和提供者之间的通信使用的是Dubbo里面的RPC来实现通信的。
⑵ 现在在Eureka中,注册中心是Eureka,消费者与提供者的远程通信是基 于Rest实现的(Java后端通过编写对应的Controller接口的Api以此去提供给外部或第三方调用)。对于如何使用Eureka来说,Eureka的服务器是一个EurekaServer来作为一个服务器的,需要我们手动去编写一个Eureka的实现类来作为服务端。而之前使用Zookeeper过程中我们是下载一个’zookeeper’并启动zk来作为服务器。
----------->这也就是Eureka与Zookeeepr这是两种的服务端配置的区别所在。在Eureka中,我们需要"客户端和服务端"都要去连接Eureka Server这个注册中心,连接上后会产生一个心跳的东西(Eureka就是说比如需要"客户端和服务端"每5秒给Eureka发一个消息,如果没发就认为你死了),就是要连接保持心跳。
⑴ 我们之前在Dubbo+Zookeeper中,是使用Dubbo-admin来监控的。这里Eureka 是使用Eureka Server这个注册中心他就可以自己去监控了。
- Eureka的三大角色。
⑴ Eureka Server 提供服务注册与发现,之前在使用"Dubbo+Zooker"的服务注册与发现的实现中,一般通过双击zkServer.cmd让其作为客户端(启动Zookeeper的客户端)。因此这个"Eureka Server"的功能 与zkServer.cmd类似。
⑵ 服务提供者:Service Provider:将自身服务注册到Eureka中,给消费者找到。
⑶ 服务消费者:Service Consumer:从Eureka获取服务。
1. 这里的“Eureka注册中心环境搭建”是在上一个章节
"SpringCloud系列:4. 完成Rest搭建服务提供者和消费者"的基础上进
行搭建的。
1.1 接下去开始演示"Eureka注册中心环境搭建",步骤如下所示↓:
⑴ 创建一个Eureka客户端(springcloud-eureka-7001)
--->第一步:在创建的子项目的pom.xm文件中,导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--热部署工具:代码修改自动更新代码,不用重启项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
⑵ 第二步:在/resources包下,对application.yml配置文件进行
相关Eureka的配置。
server:
port: 7001
eureka:
instance:
# 声明Eureka注册中心本机ip地址,可不配
hostname: localhost
client:
# 表示是否向Eureka注册中心注册自己(这里服务端是自己就不用注册自己了false)
register-with-eureka: false
# 表示如果fetch-registry为false,就表示自己是注册中心
fetch-registry: false
#下面这个地址是执行指明Eureka注册中心的IP地址,若创建多个
# Eureka注册中心,这里可配置多个Eureka注册中心的IP地址
# 尾部"..../eureka" 这个必须配置上
service-URL:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
⑶ 第三步:创建主启动类并添加一个启动Eureka服务端的注
解"@EnableEurekaServer",在启动类上加入@EnableEurekaServer注
解,这个注解表示启动一个服务注册中心提供给其他应用进行对话。
/**
* -->创建Eureka的主启动类
* -->并开启Eureka服务,添加一个注解即可@EnableEurekaServer
*/
@SpringBootApplication
@EnableEurekaServer // EnableEurekaServer 服务端的启动类,可以接受别人注册进来,
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
⑷ 第四步:启动IDEA这个子项目,测试访问-->http://localhost:7001/
--->会进入一个Eureka注册中心的一个Eureka注册中心的一个默认页面。
⑸ 第五步:接下去我们只要将之前的8001"服务提供者"注册进来就可以了。
------>这里的"服务提供者8001"是上一篇文章创建的子项
目"springcloud-provider-dept-8001",具体可以先去看看上一篇文
章的搭建过程,先将'Rest服务提供者和消费者搭建好'。
------>参考的文章名为:"SpringCloud系列:4. 完成Rest搭建服务提供者和消者"。
----------------------------------------------------------
③ 此时我们创建的这个子项目模块属于Eureka服务的注册中心,我们需要
利用到之前创建的(服务提供者):"springcloud-provider-dept-
8001"提供服务到这个"springcloud-eureka-7001"的注册中心里面
去。
① 在上一篇文章
"SpringCloud系列:4. 完成Rest搭建服务提供者和消费者"代码基础
上,利用里面创建的子项目"springcloud-provider-dept-8001"这个
服务提供者,提供服务到子模块"springcloud-eureka-7001"这个
Eureka注册中心里面。
② 在"springcloud-provider-dept-8001"中操作如下↓
⑴ 第一步"springcloud-provider-dept-8001"中导入Eureka依赖。
<!--加入EUREKA依赖,此子模块是服务提供者,因此导入此Eureka的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
⑵ 第二步:在"springcloud-provider-dept-8001"中将服务注册
到Eureka的注册中心中去,到application.yml配置Eureka的配置。
# Eureka的配置,服务注册到哪里?
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
# 修改访问localhost:7001中Eureka服务的默认描述信息
instance:
instance-id: springcloud-provider-dept8001
# 在Eureka可以实现将注册到Eureka里面的某一服务的ip地址显示或隐藏,true表示显示ip地址
prefer-ip-address: true
⑶ 第三步:在"springcloud-provider-dept-8001"中的启动类开启Eureka注解
- 就启动类加一个注解:@EnableEurekaClient
/**
* 1. @EnableEurekaClient 注解表示
* -->在"springcloud-provider-dept-8001"中开启Eureka服务
* -->并将此子项目中的服务自动注册到7001Eureka这个注册中心中去。
* 1.1 因此我们只需要在启动类加一个@EnableEurekaClient
* 它就会自动在服务启动后自动注册到Eureka中。
*
*/
@SpringBootApplication
@EnableEurekaClient
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
⑷ 第四步:测试访问http://localhost:7001/
- 此时就将"springcloud-provider-dept-8001"中的服务注册到
"springcloud-eureka-7001"这个Eureka注册中心里面去了。
⑸ 第五步:在"服务提供者"(springcloud-provider-dept-8001)中,
添加监控信息。
- pom.xml中导入依赖
<!--添加监控信息
actuator 完善监控信息
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 在"服务提供者"(springcloud-provider-dept-8001)中配置跳转页面的信息
# info监控的基本信息配置
info:
# 项目名
app.name: aaa-springcloud
# 公司名
company.name: blog.aaa.com
- 测试并访问
① 在eureka界面的一段红色字体,就是Eureka的自我保护机制的体现。
② 在"服务提供者"(springcloud-provider-dept-8001)中配置
controller接口,显示自己配置的信息(这个配置团队开发用的比较多)
--->具体的配置代码,步骤如下所示↓:
▲. 团队合作中的通过我们在controller配置的"服务发现"机制,可以获
取到具体信息。
⑴ 第一步:配置controller类接口请求
package com.lzk.springcloud.springcloud.controller;
/**
* Created by Linzk on 2020/12
*
* -->这个Controller类就是用来提供restful服务的
*/
@RestController
public class DeptController {
@Autowired
private DiscoveryClient client;
/**
* 将注册进来的微服务,以此获取Eureka相关的一些消息!
* --->这个一般在团队开发中用得到,你告诉别人自己配置的信息是什么。
* --->即:将自己的信息展现出来!!
*
*
*/
@GetMapping("/dept/discovery")
public Object discovery() {
//获取微服务列表的清单
List<String> services = client.getServices();
System.out.println("discovery==>services" + services);
//得到一个具体的微服务信息.通过具体的微服务id-->applicationName来获取信息
List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
for (ServiceInstance instance : instances) {
System.out.println(
instance.getHost() + "\t"+
instance.getPort() + "\t"+
instance.getUri() + "\t"+
instance.getServiceId() + "\t"
);
}
return this.client;
}
}
⑵ 第二步:启动类添加:服务发现的注解@EnableDiscoveryClient
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient //服务发现
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
⑶ 第三步:测试访问http://localhost:8001/dept/discovery
① 接下去代码的基础还是在"上面项目"的基础上,继续开发。
⑴ 上面的代码是利用单个Eureka作为注册中心--->
接下去:搭建搭建集群,创建多个Eureka子项目作为注册中心。
② 创建多个Eureka集群环境配置步骤如下↓;
⑴ 第一步:创建两个子项目模块"springcloud-eureka-7002"和
"springcloud-eureka-7003"以及之前已经创建好的"springcloud-eureka-7001"
共三个Eureka注册中心。
-1 分别将创建的7002和7003这两个项目,导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--热部署工具:代码修改自动更新代码,不用重启项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
-2 分别将之前创建的"springcloud-eureka-7001"里面的
application.yml配置文件复制到7002和7003的resources包下,并修
改对应的端口号。
server:
port: 700X
eureka:
instance:
# 声明Eureka服务端的实例名字(#本机ip地址,可不配)。
hostname: localhost
client:
# 表示是否向Eureka注册中心注册自己(这里服务端是自己就不用注册自己了false)
register-with-eureka: false
# 表示如果fetch-registry为false,就表示自己是注册中心
fetch-registry: false
# Eureka需要有一个自己的连接地址,重写并配置成自己的地址。
# 通过配置下面这个地址,作为Eureka的监控地址页面
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
⑵ 第二步:在7002和7003子项目模块下,分别创建对应的启动类
@SpringBootApplication
@EnableEurekaServer // EnableEurekaServer 服务端的启动类,可以接受别人注册进来,
public class EurekaServer_700X {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_700X.class,args);
}
}
⑶ 第三步:测试。
- 启动7002或7003其中一个启动类(这里演示7003)
- http://localhost:7003/
--------------------------------------------------------
⑷ 第四步:我们现在搭建的三个Eureka注册中心,是为了防止当其中一
个注册中心突然挂掉了其他注册中心还可以用,因此需要将这三个注册中
心互相绑定起来,实现这三个集群的依赖关系.
----> 要使得三个Eureka三个注册中心,形成依赖关系就需要去电脑里
面做一个域名映射.
- 地址:C:/Windows/System32/drivers/etc/hosts
- 修改hosts文件里面的信息,实现映射关系,添加三个映射,不管是访问
"eureka7001/7002/7003"其中哪一个,都可以映射访问到"127.0.0.1"
⑸ 第五步:修改"sprinfcloud-eureka-7001",
------>"sprinfcloud-eureka-7001"的application.yml
配置文件的服务器名称与上面的映射关系地址对应。
-1 7001application.yml配置文件
server:
port: 7001
eureka:
instance:
# 声明Eureka服务端的实例名字
hostname: eureka7001.com
client:
# 表示是否向Eureka注册中心注册自己(这里服务端是自己就不用注册自己了false)
register-with-eureka: false
# 表示如果fetch-registry为false,就表示自己是注册中心
fetch-registry: false
# Eureka需要有一个自己的连接地址,重写并配置成自己的地址。
# 通过配置下面这个地址,作为Eureka的监控地址页面
service-url:
# 单机单个Eureka的情况配置为:defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 集群(关联)Eureka的情况配置为:我需要在7001里面去挂载7002和7003 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
-2 7002application.yml配置文件
server:
port: 7002
eureka:
instance:
# 声明Eureka服务端的实例名字
hostname: eureka7002.com
client:
# 表示是否向Eureka注册中心注册自己(这里服务端是自己就不用注册自己了false)
register-with-eureka: false
# 表示如果fetch-registry为false,就表示自己是注册中心
fetch-registry: false
# Eureka需要有一个自己的连接地址,重写并配置成自己的地址。
# 通过配置下面这个地址,作为Eureka的监控地址页面
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
-3 7003application.yml配置文件
server:
port: 7003
eureka:
instance:
# 声明Eureka服务端的实例名字
hostname: eureka7003.com
client:
# 表示是否向Eureka注册中心注册自己(这里服务端是自己就不用注册自己了false)
register-with-eureka: false
# 表示如果fetch-registry为false,就表示自己是注册中心
fetch-registry: false
# Eureka需要有一个自己的连接地址,重写并配置成自己的地址。
# 通过配置下面这个地址,作为Eureka的监控地址页面
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
⑹ 第六步:有了三个Eureka注册中心,就需要将这三个注册中心
7001,7002,,7003,发布出去,切换到子项目模块(服务提供者)
"springcloud-provider-dept-8001"里面的application.yml配置
文件将三个注册中心宣告发布出去。
server:
port: 8001
# mybatis配置
mybatis:
# 配置Mybatis读取实体类路径配置
type-aliases-package: com.xxx.springcloud.pojo
# mybatis核心配置文件所在路径
config-location: classpath:mybatis/mybatis-config.xml
# mybatis的mapper配置所在路径
mapper-locations: classpath:mybatis/mapper/*.xml
# Spring的配置
spring:
application:
# spring服务提供在项目的名字
name: springcloud-provider-dept
# spring数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: root123
# Eureka的配置,服务注册到哪里?
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept8001 # 修改访问localhost:7001中Eureka服务的默认描述信息
# info监控的基本信息配置
info:
# 项目名
app.name: aaa-springcloud
# 公司名
company.name: blog.aaa.com
⑺ 第七步:分别启动7001,7002,7003,三个子项目模块集群
- 启动三个集群(7001,7002,7003)
- 启动一个服务提供者(springcloud-provider-dept-8001)
⑻ 第八步:测试先去访问看localhost:7002,可以看到7002关联挂载了
7001和7003这两个Eureka注册中心了,以及下面有一个注册的服务。
- 因此:如果此时7001这个节点崩溃了,其他两个节点7002和7003一样
- 可以拿来做为注册中心,不至于一个奔溃全部崩。因为一个崩了,我们
- 只需要切换一下端口接口。 这就是Eureka集群配置的好处。
1.上面的Eureka关于消费者"springcloud-eureka-consumer"获取服务
直接去注册中心获取即可!还是利用原地址访问。
---------------------------------------------------------
2. 一般在面试的时候会以"问答题"的形式问:Zookeeper与Eureka这两个注册中心的差异或区别?
Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
⑴ zookeeper与Dubbo的区别?
- Dubbo是一个RPC框架,实现分布式系统中不同节点的通信。解决通信
层面的问题。
- zookeeper:提供服务注册进来,使得节点与节点相互找到对象。
⑵ zookeeper与Eureka的区别?
- Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,
而不会像zookeeper那样使整个注册服务瘫痪。Eureka作为单纯的
服务注册中心来说要比zookeeper更加“专业”,因为注册服务更重
要的是可用性,我们可以接受短期内达不到一致性的状况。
⑶ Springcloud与Dubbo的区别?
a. 这两个框架的使用大致概括来说打个比喻:
使用Dubbo构建的微服务架构就像组装电脑,各环节我们的选择自由
度很高,但是最终结果很有可能因为一条内存质量不行就点不亮了,
总是让人不怎么放心,但是如果你是一名高手,那这些都不是问题;
而Spring Cloud就像品牌机,在Spring Source的整合下,做了大
量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用
非原装组件外的东西,就需要对其基础有足够的了解。
b. Dubbo和Spring Cloud并不是完全的竞争关系,
两者所解决的问题域不一样:Dubbo的定位始终是一款RPC框架,
而Spring Cloud的目的是微服务架构下的一站式解决方案。
c. 非要比较的话,Dubbo可以类比到Netflix OSS技术栈,
而Spring Cloud集成了Netflix OSS作为分布式服务治理解决方案,
但除此之外Spring Cloud还提供了包括config、stream、security、
sleuth等分布式服务解决方案。 当前由于RPC协议、注册中心元数据
不匹配等问题,在面临微服务基础框架选型时Dubbo与Spring Cloud只
能二选一,这也是两者总拿来做对比的原因。
Dubbo之后会积极寻求适配到Spring Cloud生态,比如作为SpringCloud
的二进制通讯方案来发挥Dubbo的性能优势,或者Dubbo通过模块化以及
对http的支持适配到Spring Cloud
⑷ http与RPC的区别?
a. 无论是微服务还是分布式服务(都是SOA,都是面向服务编程),都面临着服务间的远程调用。
b. 那么服务间的远程调用方式有哪些呢?
常见的远程调用方式有以下几种:RPC:Remote Produce Call远程过程调用 + Http:http其实是一种网络传输协议,基于TCP,规定了数据传
输的格式。
-----------------------------------------------------
- 总结:对比RPC和http的区别
1 RPC要求服务提供方和服务调用方都需要使用相同的技术,要么都hessian,要么都dubbo而http无需关注语言的实现,只需要遵循rest规
范。
2 RPC的开发要求较多,像Hessian框架还需要服务器提供完整的接口代
码(包名.类名.方法名必须完全一致),否则客户端无法运行。
3 Hessian只支持POST请求。
4 Hessian只支持JAVA语言。