三. 初步认识Eureka注册中心
Eureka
Eureka是Netflix公司出品,英文直译:发现了,找到了!
认识Eureka
(一)首先我们来解决第一问题,服务的管理。
Ⅰ.早期开发模式中出现的问题
再早期开发时业务时,首先模块中service对外提供服务,需要对外暴露自己的地址。而consumer(调用者)需要记录服务提供者的地址IP。如果将来地址IP出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦,这与DevOps的思想是背道而驰的。
Ⅱ.例子
这就好比是 网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦,而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。
此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息(联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。
此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到你面前,为你服务,完美!
Ⅲ.Eureka做用?
Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。
同时,服务提供方与Eureka之间通过“心跳”
机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。
这就实现了服务的自动注册、发现、状态监控。
Ⅳ.原理图
- renewal:续约
Eureka-Server:就是服务注册中心(可以是一个集群),对外暴露自己的地址。
提供者:启动后向Eureka注册自己信息(地址,服务名称等),并且定期进行服务续约
消费者:服务调用方,会定期去Eureka拉取服务列表,然后使用负载均衡算法选出一个服务进行调用。
心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态
(二)入门案例
Ⅰ.基本步骤如下:
①创建一个新的微服务,命名为eurekaServer
②引入eureka-server的依赖
③编写启动类,添加注解@EnableEurekaServer,代表开启eurekaServer功能
④编写application.yml文件,配置端口等信息
- ⑤启动服务,并访问:http://127.0.0.1:10010
Ⅱ.实现
①.创建一个新的微服务,命名为eurekaServer
②.引入eureka-server的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloud</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion> <artifactId>eurekaService</artifactId> <!--eureka-服务端-->
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies> <!--打包插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
③.编写启动类,添加注解@EnableEurekaServer,代表开启eurekaServer功能
@SpringBootApplication
@EnableEurekaServer
public class EurekaServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceApplication.class);
System.out.println("===Eureka服务启动===");
}
}
④.编写application.yml文件,配置端口等信息
server:
port: 10010
spring:
application:
name: eurekaServer # 应用名称,会在Eureka中作为服务的id标识(serviceId)
eureka:
client:
service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要写其它Server的地址。
defaultZone: http://127.0.0.1:10010/eureka
#register-with-eureka: false # 不注册自己,默认是true
#fetch-registry: false #不拉取服务,默认是true
⑤.启动服务,并访问:http://127.0.0.1:10010
如果配置时,将register-with-eureka: false
去掉,则能看到eureka-server
自己也注册为一个微服务了:
(三)简单服务注册
注册服务:就是让服务提供者userService把自己的信息注册到EurekaServer上,方便服务消费者去拉取。
Ⅰ.步骤如下:
- ①再创建一个UserApplication模块
②引入eurekaClient依赖
③在application.yml中配置EurekaServer端的服务名称和地址
④启动服务,并访问:http://127.0.0.1:10010
①.再创建一个UserService模块
②.引入eurekaClient依赖
<!-- Eureka客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
③.在application.yml中配置EurekaServer端的服务名称和地址
# ...略
spring:
application:
name: userService #用户服务
eureka:
client:
service-url: # 需要注册到的EurekaServer地址
defaultZone: http://127.0.0.1:10010/eureka/
④.启动User服务,并访问:http://127.0.0.1:10010
(四)Eureka进阶详解
接下来我们详细讲解Eureka的原理及配置。
Ⅰ.基础架构:
Ⅱ.Eureka架构中的三个核心角色:
服务注册中心
Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eurekaServer
服务提供者
提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。就是我们实现的userService
服务消费者
消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。
Ⅲ.高可用的Eureka Server:
Eureka Server即服务的注册中心,在刚才我们只有一个EurekaServer,事实上EurekaServer也可以是一个集群,形成高可用的Eureka中心。
①.服务同步
多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现高可用集群。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。
而作为客户端,需要把信息注册到每个Eureka中:
②.手动尝试搭建高可用的EurekaServer
目标:我们尝试搭建为两台EurekaServer的集群,端口分别为:10010和10011,两者互相注册即可。
1.我们修改原来的EurekaServer配置:
server:
port: 10086 # 端口 spring:
application:
name: eureka-server # 应用名称,会在Eureka中显示 eureka:
client:
service-url: # 配置其他Eureka服务的地址列表,多个以“,”隔开
defaultZone: http://127.0.0.1:10011/eureka/,http://127.0.0.1:10011/eureka/
2.再启动一台eureka服务
但是需要保证两个服务端口不同,因此要配置JVM参数,覆盖配置文件中的端口: -Dserver.port=10011
完成后启动如图:
Ⅳ.Eureka客户端
服务提供者要向EurekaServer注册服务,并且完成服务续约等工作。
①.服务注册
服务提供者在启动时,会检测配置属性中的:eureka.client.register-with-erueka=true
参数是否正确,事实上默认就是true。如果值确实为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息,Eureka Server会把这些信息保存到一个双层Map结构中。
第一层Map的Key就是服务id,一般是配置中的
spring.application.name
属性第二层Map的key是服务的实例id。一般host+ serviceId + port,例如:
locahost:userService:8081
值则是服务的实例对象,也就是说一个服务,可以同时启动多个不同实例,形成集群。
②.服务心跳续约
在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renewal)
lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒
lease-expiration-duration-in-seconds:服务失效时间,默认值90秒
默认情况下每隔30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳,EurekaServer就会认为该服务宕机,可能会从服务列表中移除,这两个值在生产环境不要修改,默认即可。
③.服务下线
当服务进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线了”。服务中心接受到请求之后,将该服务置为下线状态。
④.失效剔除
有时我们的服务可能由于内存溢出或网络故障等原因使得服务不能正常的工作,而服务注册中心并未收到“服务下线”的请求。相对于服务提供者的“服务续约”操作,服务注册中心在启动时会创建一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除,这个操作被称为失效剔除。
可以通过eureka.server.eviction-interval-timer-in-ms
参数对其进行修改,单位是毫秒。
⑤.自我保护机制
我们关停一个服务,就会在Eureka面板看到一条警告:
这是触发了Eureka的自我保护机制。当服务未按时进行心跳续约时,Eureka会统计服务实例最近15分钟心跳续约的比例是否低于了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka在这段时间内不会剔除任何服务实例,直到网络恢复正常。生产环境下这很有效,保证了大多数服务依然可用,不过也有可能获取到失败的服务实例,因此服务调用者必须做好服务的失败容错。
最新文章
- mono for android学习过程系列教程(4)
- css 多个不定数量提交按钮居中显示,纯css解决
- Icon Font的转换
- DOM系列---DOM操作样式
- Activity与WindowManagerService服务的连接过程分析
- 1105ecos笔记
- 2014第7周四excel多列文本复制技巧
- ASP.NET MVC4(Razor)从客户端中检测到有潜在危险的 Request.Form 值
- Children’s Queue
- 使用JDK中的安全包对数据进行加解密
- HostingEnvironment RegisterObject和QueueBackgroundWorkItem
- 模仿qq界面实现(WTL)
- 2017.3.3自测j纠错题.
- File FileStream StreamWriter StreamReader文件读写操作方法
- 百度编辑器上传视频音频的bug
- redis主从,哨兵回忆手册
- 玩转PHP(二)--PHP强大的时间函数:date()
- 创建一个多进程(multiprocessing.Process)
- 转载:https://blog.csdn.net/qq_22706515/article/details/52595027
- 创建标签的两种方法insertAdjacentHTML 和 createElement 创建标签 setAttribute 赋予标签类型 appendChild 插入标签
热门文章
- nodejs+express+mongodb实现登录注册
- Kubernetes-1.概述
- windows本地连接虚拟机上的ubuntu的redis,以及无法连接解决方法(redisDesktopManager Jedis详细步骤)
- Arrays.Sort()中的那些排序算法
- Vmware虚拟机CentOS7、Ubuntu20系统设置静态IP,且主机和虚拟机系统能相互ping通。
- Spring中各种扩展原理及容器创建原理
- 使用代码生成工具快速开发ABP框架项目
- 001-HashMap源码分析
- vue 弹窗禁止底层滚动
- android消息线程和消息队列