目录

  • 基于上一集
  • 认识Eureka
  • 原理图
  • 入门案例
    • 搭建eureka-server工程
    • 服务注册
    • 服务发现
  • Eureka详解
    • 基础架构
    • 高可用的Eureka Server
    • Eureka客户端
    • 失效剔除和自我保护

基于上一集

认识Eureka

首先我们来解决第一问题,服务的管理。

  • 问题分析

在微服务场景模拟的案例中,user-service对外提供服务,需要对外暴露自己的地址。而consumer-demo(调用者)需要记录服务提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂的互联网环境,一个项目可能会拆分出十几,甚至几十个微服务。此时如果还人为管理地址,不仅开发困难,将来测试、发布上线都会非常麻烦,这与DevOps的思想是背道而驰的。
DevOps的思想是系统可以通过一组过程、方法或系统;提高应用发布和运维的效率,降低管理成本。

  • 网约车

这就好比是 网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦,而且满大街的车,谁知道哪个才是愿意载人的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。
此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息(联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到你面前,为你服务,完美!

  • Eureka做什么?

Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。同时,服务提供方与Eureka之间通过 “心跳” 机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。这就实现了服务的自动注册、发现、状态监控。

原理图

  • Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
  • 提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
  • 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
  • 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

入门案例

搭建eureka-server工程


pom文件:

<?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>heima-springcloud</artifactId><groupId>com.itheima</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>eureka-server</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties></project>

使用JBLSpringBootAppGen快速生成启动器类(需安装插件)

1)编写启动器类
eureka-server\src\main\java\com\itheima\EurekaServerApplication.java

package com.heima.EurekaServer;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@EnableEurekaServer//声明当前应用是Eureka服务
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

2)编写配置文件
eureka-server\src\main\resources\application.yml

server:port: 10086
spring:application:name: eureka-server # 应用名称,会在Eureka中作为服务的id标识(serviceId)
eureka:client:service-url: # EurekaServer的地址,现在是自己的地址,如果是集群,需要写其它Server的地址。defaultZone: http://127.0.0.1:10086/eurekaregister-with-eureka: false # 不注册自己fetch-registry: false #不拉取

3)启动服务
启动 eureka-server 访问:http://127.0.0.1:10086

服务注册

注册服务,就是在服务上添加Eureka的客户端依赖,客户端代码会自动把服务注册到EurekaServer中。

1)添加依赖
我们在user-service的pom文件中添加Eureka客户端依赖:

<!-- Eureka客户端 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2)修改启动类
在启动类上开启Eureka客户端功能
通过添加 @EnableDiscoveryClient 来开启Eureka客户端功能

package com.itheima.user;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import tk.mybatis.spring.annotation.MapperScan;@SpringBootApplication
@MapperScan(basePackages = "com.itheima.user.mapper")//扫描通用mapper所在包
@EnableDiscoveryClient//开启eureka客户端发现功能
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

3)修改配置文件
编写user-service\src\main\resources\application.yml配置文件为如下:

server:port: 9091address: 127.0.0.1spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springcloud?serverTimezone=UTCusername: rootpassword: 123456@rootapplication:#应用名称,会在eureka中作为服务的id(serviceId)name: user-service
mybatis:type-aliases-package: com.itheima.user.pojo
eureka:client:service-url:#eureka服务地址,若是集群则是其它服务的地址,后面要加/eureka,可以配置多个服务地址defaultZone:  http://127.0.0.1:10086/eureka

注意:
这里我们添加了spring.application.name属性来指定应用名称,将来会作为服务的id使用。

4)测试
重启 user-service 项目,访问Eureka监控页面

可以看到user-service服务已经注册成功了

服务发现

接下来我们修改 consumer-demo ,尝试从EurekaServer获取服务。
方法与服务提供者类似,只需要在项目中添加EurekaClient依赖,就可以通过服务名称来获取信息了!

1)添加依赖
找到 consumer-demo\pom.xml 添加如下依赖

<?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>heima-springcloud</artifactId><groupId>com.itheima</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>consumer</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies></project>

2)修改启动类
修改 consumer-demo\src\main\java\com\itheima\consumer\ConsumerApplication.java
开启Eureka客户端

package com.itheima.consumer;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@SpringBootApplication
@EnableDiscoveryClient//开启eureka客户端发现
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}

3)新增配置文件
新增 consumer-demo\src\main\resources\application.yml 配置文件

server:port: 8080address: 127.0.0.1
spring:application:name: consumer-demo # 应用名称
eureka:client:service-url:defaultZone:  http://127.0.0.1:10086/eureka

4)修改处理器
修改
consumer-demo\src\main\java\com\itheima\consumer\controller\ConsumerController
.java 代码,
用DiscoveryClient类的方法,根据服务名称,获取服务实例。

package com.itheima.consumer.controller;
import com.itheima.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
@RequestMapping("/consumer")
public class ConsumerController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@GetMapping("{id}")public User queryById(@PathVariable Long id){String url = "http://localhost:9091/user/" + id;//获取eureka中注册的user-service实例列表List<ServiceInstance> serviceInstanceList =   discoveryClient.getInstances("user-service");ServiceInstance serviceInstance = serviceInstanceList.get(0);url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort()
+ "/user/" + id;return restTemplate.getForObject(url, User.class);}
}

5)Debug跟踪运行
重启 consumer-demo 项目;然后再浏览器中再次访问 http://localhost:8080/consumer/8 ;在代码中debug跟进查看最终拼接要访问的URL:

可以看到我们最终访问的还是user-service提供的服务地址

Eureka详解

基础架构

Eureka架构中的三个核心角色:

  • 服务注册中心
    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server
  • 服务提供者
    提供服务的应用,可以是SpringBoot应用,也可以是其它任意技术实现,只要对外提供的是Rest风格服务即可。本例中就是我们实现的user-service
  • 服务消费者
    消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中就是我们实现的consumer-demo

高可用的Eureka Server

Eureka Server即服务的注册中心,在刚才的案例中,我们只有一个EurekaServer,事实上EurekaServer也可以是一个集群,形成高可用的Eureka中心。

  • 服务同步

多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。而作为客户端,需要把信息注册到每个Eureka中:


如果有三个Eureka,则每一个EurekaServer都需要注册到其它几个Eureka服务中,例如:有三个分别为10086、
10087、10088,则:
10086要注册到10087和10088上
10087要注册到10086和10088上
10088要注册到10086和10087上

  • 动手搭建高可用的EurekaServer
    我们假设要搭建两台EurekaServer的集群,端口分别为:10086和10087

1)修改原来的EurekaServer配置;
修改 eureka-server\src\main\resources\application.yml 如下:

server:port: ${port:10086}
spring:application:# 应用名称,会在eureka中作为服务的id(serviceId)name: eureka-server
eureka:client:service-url:# eureka服务地址;如果是集群则是其它服务器地址,后面要加/eurekadefaultZone: ${defaultZone:http://127.0.0.1:10086/eureka}# 是否注册自己,自身不提供服务所以不注册#register-with-eureka: false# 是否拉取服务#fetch-registry: false

所谓的高可用注册中心,其实就是把EurekaServer自己也作为一个服务,注册到其它EurekaServer上,这样多个EurekaServer之间就能互相发现对方,从而形成集群。因此我们做了以下修改:

注意把register-with-eureka和fetch-registry修改为true或者注释掉
在上述配置文件中的${}表示在jvm启动时候若能找到对应port或者defaultZone参数则使用,若无则使用后面的默认值

  • 把service-url的值改成了另外一台EurekaServer的地址,而不是自己

    2)另外一台在启动的时候可以指定端口port和defaultZone配置:

    修改原来的启动配置组件;在如下界面中的 VM options 中
    设置 -DdefaultZone=http:127.0.0.1:10087/eureka

    复制一份并修改;在如下界面中的 VM options 中
    设置 -Dport=10087 -DdefaultZone=http:127.0.0.1:10086/eureka

    3)启动测试;同时启动两台eureka server

    4)客户端注册服务到集群
    因为EurekaServer不止一个,因此 user-service 项目注册服务或者 consumer-demo 获取服务的时候,service-url参数需要修改为如下:

eureka:client:service-url: # EurekaServer地址,多个地址以','隔开defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka

在测试完上述配置后可以再次改回单个eureka server的方式,以便后续测试。

Eureka客户端

服务提供者要向EurekaServer注册服务,并且完成服务续约等工作。

  • 服务注册
    服务提供者在启动时,会检测配置属性中的: eureka.client.register-with-erueka=true 参数是否正确,事实上默认就是true。如果值确实为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息,EurekaServer会把这些信息保存到一个双层Map结构中。

    • 第一层Map的Key就是服务id,一般是配置中的 spring.application.name 属性
    • 第二层Map的key是服务的实例id。一般host+ serviceId + port,例如: localhost:user-service:8081
    • 值则是服务的实例对象,也就是说一个服务,可以同时启动多个不同实例,形成集群。

默认注册时使用的是主机名或者localhost,如果想用ip进行注册,可以在 user-service 中添加配置如下:

eureka:instance:ip-address: 127.0.0.1 # ip地址prefer-ip-address: true # 更倾向于使用ip,而不是host名

修改完后先后重启 user-service 和 consumer-demo ;在调用服务的时候就已经变成ip地址;需要注意的是:不是在eureka中的控制台服务实例状态显示。(getHost()方法返回的值)

  • 服务续约
    在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉EurekaServer:“我还活着”。这个我们称为服务的续约(renew);

有两个重要参数可以修改服务续约的行为;可以在 user-service 中添加如下配置项:

eureka:instance:lease-expiration-duration-in-seconds: 90lease-renewal-interval-in-seconds: 30
 lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒lease-expiration-duration-in-seconds:服务失效时间,默认值90秒

也就是说,默认情况下每隔30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心跳,EurekaServer就会认为该服务宕机,会定时(eureka.server.eviction-interval-timer-in-ms设定的时间)从服务列表中移除,这两个值在生产环境不要修改,默认即可。

  • 获取服务列表
    当服务消费者启动时,会检测 eureka.client.fetch-registry=true 参数的值,如果为true,则会从EurekaServer服务的列表拉取只读备份,然后缓存在本地。并且 每隔30秒 会重新拉取并更新数据。可以在 consumer-demo项目中通过下面的参数来修改:
eureka:client:registry-fetch-interval-seconds: 30

失效剔除和自我保护

如下的配置都是在Eureka Server服务端进行:

  • 服务下线
    当服务进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线了”。服务中心接受到请求之后,将该服务置为下线状态。

  • 失效剔除
    有时我们的服务可能由于内存溢出或网络故障等原因使得服务不能正常的工作,而服务注册中心并未收到“服务下线”的请求。相对于服务提供者的“服务续约”操作,服务注册中心在启动时会创建一个定时任务,默认每隔一段时间(默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除,这个操作被称为失效剔除。
    可以通过 eureka.server.eviction-interval-timer-in-ms 参数对其进行修改,单位是毫秒。

  • 自我保护
    我们关停一个服务,很可能会在Eureka面板看到一条警告:

    这是触发了Eureka的自我保护机制。当服务未按时进行心跳续约时,Eureka会统计服务实例最近15分钟心跳续约的比例是否低于了85%。在生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因为服务可能没有宕机。Eureka在这段时间内不会剔除任何服务实例,直到网络恢复正常。生产环境下这很有效,保证了大多数服务依然可用,不过也有可能获取到失败的服务实例,因此服务调用者必须做好服务的失败容错。
    可以通过下面的配置来关停自我保护:

eureka:server:enable-self-preservation: false # 关闭自我保护模式(缺省为打开)

四、Eureka注册中心相关推荐

  1. SpringCloud Greenwich(四)注册中心之eureka、Zuul和 gateway网关配置

    本项目是搭建基于eureka注册中心的springcloud,使用zuul网关和gateway网关 一.框架搭建 (1)项目结构 eureka-server  eureka注册中心 micro-ser ...

  2. Fescar 发布 0.3.0 版本, 支持 Eureka 注册中心

    开发四年只会写业务代码,分布式高并发都不会还做程序员?   Fescar 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务. 本次更新内容如下: 特性 [#510] 新增 Eure ...

  3. 创建集群版的Eureka注册中心

    我们搭建了一个Eureka服务注册中心,就是Eureka Server,他提供了服务的注册和发现,那么其实对于Eureka服务注册中心来讲,我们整个微服务开发当中,它是一个非常重要的环节,我们所有的服 ...

  4. SpringCloud 如何搭建Eureka注册中心

    导语   在之前的分享中介绍了SpringCloud相关的内容,那么如何去搭建一个Spring Cloud Eureka 的注册中心.作为微服务中最为重要的一个组件,怎么去搭建一个服务注册中心称为关键 ...

  5. spring cloud、gradle、父子项目、微服务框架搭建---搭建父子级多模块项目,并注册到Eureka注册中心(二)

    总目录 https://preparedata.blog.csdn.net/article/details/120062997 一.新建一个父级gradl模块 1.在桌面或新建文件里面,右键,打开ID ...

  6. spring cloud、gradle、父子项目、微服务框架搭建---搭建Eureka注册中心(一)

    总目录 https://preparedata.blog.csdn.net/article/details/120062997 一.新建一个父级gradl模块 1.在桌面或新建文件里面,右键,打开ID ...

  7. spring-cloud开发微服务笔记(二):高可用Eureka注册中心的搭建与RestTemplate和Fengin客户端调用微服务示例

    引言:这一篇博客是将上一篇spring-cloud-eureka-server的单机模式改为集群模式,体现eureka的高可用特性.生产环境无论是Eureka注册中心还是Client客户端大多是部署在 ...

  8. SpringCloud——Eureka注册中心搭建

    Eureka原理 eureka来源于古希腊词汇,意为"发现了" eureka分为两部分,Server端和Client端 Register 服务注册 想要参与服务注册发现的实例首先需 ...

  9. 微服务笔记:第一章_微服务简介|Eureka注册中心|Nacos注册中心|Nacos配置管理|Feign|Gateway服务网关

    微服务笔记:第一章_微服务简介|Eureka注册中心|Nacos注册中心|Nacos配置管理|Feign|Gateway服务网关 1. 微服务简介 1.1 服务架构演变 1.2 SpringCloud ...

  10. Eureka 注册中心/服务发现框架

    Eureka 注册中心/服务发现框架 Eureka注册中心/服务发现框架 如何使用构建 Eureka Server ? 加入依赖(此处以Maven为例) 创建Eureka Server 主运行类 单机 ...

最新文章

  1. Python 字符串及基本语句
  2. zabbix对一台主机监控的操作
  3. MsSQL的字段类型
  4. 不容易系列之(4)——考新郎
  5. Nebula:Slack 的覆盖全球性的开源网络
  6. 我的新书,《人人都是产品经理》自序
  7. 763. 划分字母区间009(贪心算法+思路+详解+图示)
  8. 【Loj - 515】贪心只能过样例(暴力,或01背包 + bitset)
  9. c# 编程学习(二)
  10. oracle 解死锁权限,讲解Oracle数据库中结束死锁进程的一般方法
  11. AI、大数据、中台、AIoT、Fintech等十余场火热专题应有尽有,年度盛会BDTC 2019邀您共赴!...
  12. Win 10 下载与安装 Oracle 12c 详细图解 与 Oracle 12c 卸载
  13. 根据不同时区计算北京时间
  14. 实现BIM的Revit软件学习资料
  15. 基于单片机的智能小区安防系统毕业设计
  16. 轻量版verilog仿真平台:icarus verilog使用简介
  17. 家园守卫战新系统冲入海盗营地漏洞,无限赚钱
  18. 追尾事故降发生:超低功耗滴滴桔视ADAS落地实践
  19. 云”中智控 IT管理新境界
  20. 【dubbo源码解析】 --- dubbo spi 机制(@SPI、@Adaptive)详解

热门文章

  1. 学习HTML5这一篇就够了
  2. android自定义view(二)-仿华为卡包效果
  3. 软文推广如何运动软文性广告来营销?
  4. python入门之 列表 元组 集合 字典 最全教程
  5. 一次指数平滑预测matlab,一次指数平滑法matlab
  6. 【求解器】超级强大的数学规划模型求解器Cplex,导入idea+java代码简单案例详解
  7. A095_Html5入门
  8. 链游玩家:浅谈链游开发平台,千里之行始于足下
  9. 山东大学2018年操作系统试题
  10. C语言scanf()函数返回值的问题