Eureka
Netflix Eureka
- Eureka服务端:也称服务注册中心,同其他服务注册中心一样,支持高可用配置。如果Eureka以集群模式部署,当集群中有分片出现故障时,那么Eureka就转入自我保护模式。它允许在分片故障期间继续提供服务的发现和注册,当故障分片恢复运行时,集群中其他分片会把它们的状态再次同步回来
- Eureka客户端:主要处理服务的注册与发现。客户端服务通过注解和参数配置的方式,嵌入在客户端应用程序的代码中,在应用程序运行时,Eureka客户端想注册中心注册自身提供的服务并周期性地发送心跳来更新它的服务租约。同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性地刷新服务状态
- Eureka Server的高可用实际上就是将自己作为服务向其他注册中心注册自己,这样就可以形成一组互相注册的服务注册中心,以实现服务清单的互相同步,达到高可用效果
搭建Eureka服务注册与发现
新建一个Spring Cloud项目
工程结构:
创建父工程与common,provider,comsumer模块在上篇maven构建项目中有详细步骤:传送门
在此基础上创建microservice-eureka服务模块,创建方法:父工程右键new - module -maven -xxx
在pom文件添加:pring-cloud-starter-netflix-eureka-server 依赖包
<parent>
<artifactId>microservice</artifactId>
<groupId>com.demo</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../microservice/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservice-eureka</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- spring boot web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka-server服务端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
在applicatin.properties文件中添加:
server.port = 8761
eureka.instance.hostname = localhost
eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
eureka.client.serviceUrl.defaultZone = http://${eureka.instance.hostname}:${server.port}/eureka/
创建启动类测试:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer01 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer01.class, args);
}
}
抛异常:was unable to refresh its cache! status = Cannot execute request on any known server
问题原因:Eureka服务注册中心也会将自己作为客户端来尝试注册它自己,出现冲突,所以我们需要禁用它的客户端注册行为。
解决方法:确认这两个参数是否为false以及检查url是否符合驼峰命名法
- eureka.client.registerWithEureka = false
- eureka.client.fetchRegistry = false
- eureka.client.serviceUrl.defaultZone = http://${eureka.instance.hostname}:${server.port}/eureka/
我的就比较诡异配置都符合规范就是抛异常,后来改成properties格式的配置文件就好了。之前用的是yml格式
启动成功
Eureka Client 端
Eureka Client 端即服务的提供方,将自身服务注册到 Eureka Server,从而使服务消费方能够找到。将 microservice-order-provider01(端口8001)改造成 Eureka client 端
添加依赖包
<!--eureka-client客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在properties配置文件中添加
# 服务端口号
server.port = 8001
# 对外暴露的服务名称
spring.application.name = microservice-order
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
spring.datasource.username = root
spring.datasource.password = root
# 最大连接池数
spring.datasource.hikari.maximum-pool-size = 10
spring.datasource.hikari.max-lifetime = 1770000
# 客户端注册进eureka服务列表里 这里也可以替换成eureka01 需要激情eureka01添加到hosts文件中
eureka.client.serviceUrl.defaultZone = http://localhost:7001/eureka/
可以看到,我们给该服务起了个名称,该名称是服务对外暴露的名称, 指定了将该 Client 端注册到哪个 Eureka 服务列表里
在启动文件添加注释:@EnableEurekaClient
启动测试
启动服务消费端
启动microservice-comsumer 服务消费端
测试:http://localhost:8080/consumer/order/get/list
完善服务信息
完善Eureka上注册服务,增加服务的可读性,给服务更改信息
# 人性化显示出服务的信息
eureka.instance.instance-id = 订单服务-8001
# 访问路径可显示ip地址
eureka.instance.prefer-ip-address = true
eureka.instance.lease-renewal-interval-in-seconds = 2
eureka.instance.lease-expiration-duration-in-seconds = 5
页面变化
正常情况Eureka页面点击服务没有定义详情页会出404,这里定义一个服务详情页,
1.需要导入actuator依赖包
<!-- spring boot actuator 监控信息 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2. application文件添加自定义配置
#spring boot actuator 监控信息需要导入actuator依赖包
# 使用actuator来展示项目的基本信息
info.author.name = zhang ti
info.app.name = microservice
info.server.port = ${server.port}
info.application.name = ${spring.application.name}
3. 测试一下
ok!
服务发现
将注册的服务通过接口的方式暴露给外界调用
@RestController
@RequestMapping("/provider/order")
public class OrderProviderController {
private static final Logger LOGGER = LoggerFactory.getLogger(OrderProviderController.class);
@Resource
private EurekaClient client;
@Resource
private OrderService orderService;
/**
* 发现服务
* 创建发现服务入口
* */
@GetMapping("/discovery")
public Object discovery(){
//获取Eureka中所有的服务节点
List<Application> applications = client.getApplications().getRegisteredApplications();
if(applications !=null){
for(Application application:applications){
//对外暴露的服务名称
String name = application.getName();
//只看订单服务信息
if("MICROSERVICE-ORDER".equals(name)){
//服务有多少个实例,比如订单服务可能部署了多个,有多个订单服务注册到了Eureka
List<InstanceInfo> instances = application.getInstances();
if(instances != null){
for (InstanceInfo instance : instances){
LOGGER.info("服务id:{}",instance.getId());
LOGGER.info("服务主机:{}",instance.getHostName());
LOGGER.info("服务端口:{}",instance.getPort());
}
}
return instances;
}
}
}
return null;
}
}
引入 EurekaClient 端,在接口内部,通过 EurekaClient 获取到注册在 Eureka 上的所有 Application,这里的 application 其实就是我们常说的服务节点,从而获取到服务节点的信息,包括服务节点的名称、状态、IP、端口、心跳情况等信息。直接将服务的信息返回即可
调用返回json:
Eureka集群
1.分布式与集群区别
- 分布式:一个业务分拆多个子业务,部署在不同的服务器上
- 集群:同一个业务,分别部署在不同的服务器上
- 集群可以理解为:你中有我,我中有你,手拉手肩并肩,一起保证服务的健壮性
2.如何搭建集群
假设有三个服务分别是eureka7001、eureka7002 和 eureka7003
如何体现你中有我,我中有你的原则,看下之前eureka7001的配置文件:
server.port = 7002
eureka.instance.hostname = eureka02
eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
eureka.client.serviceUrl.defaultZone =http://${eureka.instance.hostname}:${server.port}/eureka/
这是一个 Eureka 服务,名称是 eureka7001, 注册中心是它自己的。可以改成相互注册:
server.port = 7001
eureka.instance.hostname = eureka01
eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
eureka.client.serviceUrl.defaultZone = http://eureka02:7002/eureka/,http://eureka03:7003/eureka/
新建 eureka02 详细步骤参考eureka01 端口号7002 配置文件:
server.port = 7002
eureka.instance.hostname = eureka02
eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
eureka.client.serviceUrl.defaultZone = http://eureka01:7001/eureka/,http://eureka03:7003/eureka/
新建 eureka03 详细步骤参考eureka01 端口号7003 配置文件:
server.port = 7003
eureka.instance.hostname = eureka03
eureka.client.registerWithEureka = false
eureka.client.fetchRegistry = false
eureka.client.serviceUrl.defaultZone = http://eureka01:7001/eureka/,http://eureka02:7002/eureka/
集群示意图:
启动测试:访问eureka01可以看到eureka02和eureka03服务
3 修改订单注册服务:
修改配置文件的注册地址,添加eureka02和eureka03:
# 客户端注册进eureka服务列表里
eureka.client.serviceUrl.defaultZone = http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/
启动测试:
访问eureka01服务:http://localhost:7001
注册成功!