分布式系统开发技术 | Eureka服务注册与发现

本文章是在网易云课堂的课程学习中编写,部分图片从网易云课堂ppt引用

一、什么是Eureka注册中心

各个服务注册到Eureka,Eureka对服务进行管理:
1、可感知注册的服务的健康情况,是否下线
2、可感知注册的服务的IP和Port地址变更

注:若使用nginx,nginx无法感知注册的服务是否下线,且若变更服务地址,需改动nginx配置

Eureka使用图示:

image.png

说明:
服务提供者启动时:定时向EurekaServer注册自己的服务信息(服务名、IP、端口..等等)
服务消费者启动时:后台定时拉取Eureka-Server中存储的服务信息

二、如何集成Eureka

1. Eureka注册中心

1.1 maven引入

<properties>
     <java.version>1.8</java.version>
     <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
 </properties>

 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
     </dependency>
     <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-server</artifactId>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>
 </dependencies>

 <dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-dependencies</artifactId>
             <version>${spring-cloud.version}</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
     </dependencies>
 </dependencyManagement>

 <build>
     <plugins>
         <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
     </plugins>
 </build>

1.2 代码

在Application使用 @EnableEurekaServer 注解

1.3 yml配置

spring:
 application:
   name: eureka-peer
 profiles: dev

server:
 port: 10000

eureka:
 #实例
 instance:
   hostname: dev
   instance-id: dev
 #作为客户端的配置
 client:
   #是否从eureka拉取信息
   fetch-registry: false
   #是否将自己注册到eureka
   register-with-eureka: false
   #定义区域,进行分区。使得调用更加方便快捷,适用于非常大的服务器
   #availability-zones:
     #beijing: zone-1
   service-url:
     #默认的注册中心的通信地址
     defaultZone: http://localhost:10000/eureka/,http://localhost:10001/eureka/,http://localhost:10002/eureka/
     #beijing对应区域的通信地址,若该区域没有找到服务,再尝试去访问别的区域
     #zone-1: http://localhost:10000/eureka/
 #作为服务端的配置
 server:
     #服务间请求的等待时长
     wait-time-in-ms-when-sync-empty: 0
     #自我保护机制
     enable-self-preservation: true
     #同步时长
     peer-eureka-nodes-update-interval-ms: 10000

启动工程,网页打开 localhost:10000 可以看到Eureka页面:

image.png

1.4 调用链路

在配置文件中,可加入日志级别的配置,查看调用链路信息,用来排查问题

logging.level.org.springframework.cloud = debug
logging.level.com.netflix = debug

2. 生产者(服务提供者)

2.1 maven引入

<properties>
     <java.version>1.8</java.version>
     <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
 </properties>

 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
     </dependency>
     <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>
         <version>2.1.1.RELEASE</version>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>

 </dependencies>

 <dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-dependencies</artifactId>
             <version>${spring-cloud.version}</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
     </dependencies>
 </dependencyManagement>

 <repositories>
     <repository>
         <id>spring-milestones</id>
         <name>Spring Milestones</name>
         <url>https://repo.spring.io/milestone</url>
     </repository>
 </repositories>

 <build>
     <plugins>
         <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
     </plugins>
 </build>

2.2 代码示例

在Application使用 @EnableEurekaClient 注解。这里配置2个服务提供者
服务提供者1:

@SpringBootApplication
@EnableEurekaClient
@RestController
public class HelloDemoPeer1Application {

 public static void main(String[] args) {
     SpringApplication.run(HelloDemoPeer1Application.class, args);
 }

 @GetMapping("")
 public Object index(){
      String str =  "这是服务端1返回的应答";
     return new String(str);
 }
 
}

服务提供者2:

@SpringBootApplication
@EnableDiscoveryClient
@EnableEurekaClient
@RestController
@RefreshScope
public class HelloDemoPeer1Application {

 public static void main(String[] args) {
     SpringApplication.run(HelloDemoPeer1Application.class, args);
 }

 @GetMapping("")
 public Object index(){
     String str =  "这是服务端2返回的应答";
     return new String(str);
 }

}

2.3 yml配置

服务提供者1:

server:
 port: 8001
spring:
 application:
     name: helloserver

eureka:
 client:
     service-url:
         defaultZone: http://127.0.0.1:10000/eureka/,http://127.0.0.1:10001/eureka/,http://127.0.0.1:10002/eureka/

服务提供者2:

server:
 port: 8002
spring:
 application:
     name: helloserver

eureka:
 client:
     service-url:
         defaultZone: http://127.0.0.1:10000/eureka/

3. 消费者

3.1 maven引入

<properties>
     <java.version>1.8</java.version>
     <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
 </properties>

 <dependencies>
     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-actuator</artifactId>
     </dependency>
     <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>

     <!-- 重试机制。如果调用后,出现异常,可以通过重试机制,发起重试。 -->
     <dependency>
         <groupId>org.springframework.retry</groupId>
         <artifactId>spring-retry</artifactId>
     </dependency>

     <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
     </dependency>
 </dependencies>

 <dependencyManagement>
     <dependencies>
         <dependency>
             <groupId>org.springframework.cloud</groupId>
             <artifactId>spring-cloud-dependencies</artifactId>
             <version>${spring-cloud.version}</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
     </dependencies>
 </dependencyManagement>

 <build>
     <plugins>
         <plugin>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
     </plugins>
 </build>

3.2 代码示例

使用RestTemplate对服务提供者进行访问
注:template方法上的 @LoadBalanced 是用来实现负载均衡,是Ribbon的一种内部应用模式

/**
* CustomerDemoApplication
*/
@SpringBootApplication
@RestController
public class CustomerDemoApplication {

 public static void main(String[] args) {
     SpringApplication.run(CustomerDemoApplication.class, args);
 }

 @Bean
 @LoadBalanced
 public RestTemplate template(){
     return new RestTemplate();
 }

}
/**
* CustomerController
*/
@RestController
public class CustomerController {

 @Autowired
 private RestTemplate restTemplate;

 @GetMapping("index")
 public Object getIndex(){
     //使用RestTemplate对服务提供者进行访问,这里使用服务名去访问
     return restTemplate.getForObject("http://HELLOSERVER/",String.class,"");
 }

}

3.3 yml配置

server:
 port: 8083

spring:
 application:
     name: consumer-demo

eureka:
 client:
     service-url:
         defaultZone : http://127.0.0.1:10000/eureka/

将Eureka注册中心、生产者、消费者都启动起来,可以在页面上看到注册的服务实例:
(注意:Eureka中的instance名称,不区分大小写)

image.png

三、Eureka核心知识

1. 启动时服务如何注册到Eureka的?

image.png

启动时,通过后台任务,将 【服务名、ip、端口】 注册到EurekaServer

2. 服务端如何保存这些信息?

image.png

客户端启动后,会去调用http,将服务实例放在Server内部一个Map对象中存储

3. 消费者如何根据服务名称发现服务实例?

image.png

启动时,通过后台任务,定期从EurekaServer拉取服务信息,缓存到消费者本地内存中

4. 如何构建高可用的eureka集群?

image.png
  • 在高可用状态下,Eureka通过【对等协议】,将注册在自身的实例,与组内其他Eureka进行同步。
  • 在【defaultZone】参数,可配置多个注册中心的地址。
    以下配置文件中,分别修改 active 属性值,启动三个注册中心。然后启动生产者,将服务注册到其中一个注册中心。可以看到,三个注册中心都有注册的服务实例
  • 服务注册的高可用机制:如果其中一个注册中心出现问题,不会影响其他注册中心的处理。
    比如:注册中心1、2、3之间同步服务实例。假设注册中心1挂了,生产者将服务注册到注册中心 1 ,注册中心 2 和 3 也还是能收到该生产者注册的服务实例
  • 如何防止各注册中心的重复传播:源码中,通过isReplication判断
spring:
 profiles:
     active: dev

#分割符号,分割不同的环境
---
spring:
 application:
     name: eureka-peer
 profiles: dev

server:
 port: 10000

eureka:
 #实例
 instance:
     hostname: dev
     instance-id: dev
 #作为客户端的配置
 client:
     #是否从eureka拉取信息
     fetch-registry: false
     #是否将自己注册到eureka
     register-with-eureka: false
     service-url:
         #默认的注册中心的通信地址,高可用配置
         defaultZone: http://localhost:10000/eureka/,http://localhost:10001/eureka/,http://localhost:10002/eureka/
 #作为服务端的配置
 server:
     #服务间请求的等待时长
     wait-time-in-ms-when-sync-empty: 0
     #自我保护机制
     enable-self-preservation: true
     #同步时长
     peer-eureka-nodes-update-interval-ms: 10000


---
spring:
 profiles: dev1
 application:
     name: eureka-peer2
server:
 port: 10001


eureka:
 instance:
     hostname: dev1
     instance-id: dev1
 client:
     fetch-registry: false
     register-with-eureka: false
     service-url:
         defaultZone: http://localhost:10000/eureka/,http://localhost:10001/eureka/,http://localhost:10002/eureka/
 server:
     wait-time-in-ms-when-sync-empty: 0
     enable-self-preservation: true
     peer-eureka-nodes-update-interval-ms: 10000
---
spring:
  profiles: dev2
  application:
      name: eureka-peer3
server:
 port: 10002


eureka:
     instance:
         hostname: dev2
         instance-id: dev2
     client:
         fetch-registry: false
         register-with-eureka: false
         service-url:
             defaultZone: http://localhost:10000/eureka/,http://localhost:10001/eureka/,http://localhost:10002/eureka/
     server:
         wait-time-in-ms-when-sync-empty: 0
         enable-self-preservation: true
         peer-eureka-nodes-update-interval-ms: 10000

---

5. 心跳和服务剔除机制是什么?

image.png

心跳:客户端定期发送心跳请求包到EurekaServer
若心跳长时间没有发送,eureka则会采用剔除机制,将服务实例改为 Down 状态

6. eureka自我保护模式是什么?

生产上一般会开启自我保护模式。开启自我保护机制后,服务一旦下线,注册中心中不会剔除该服务,避免将可用的服务也剔除了。
问题:如何避免调用到宕机的服务
处理:提供了补偿方案,如重试机制、熔断机制

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层...
    pengyuyancode阅读 32,997评论 0 18
  • 夜莺2517阅读 127,717评论 1 9
  • 版本:ios 1.2.1 亮点: 1.app角标可以实时更新天气温度或选择空气质量,建议处女座就不要选了,不然老想...
    我就是沉沉阅读 6,887评论 1 6
  • 我是一名过去式的高三狗,很可悲,在这三年里我没有恋爱,看着同龄的小伙伴们一对儿一对儿的,我的心不好受。怎么说呢,高...
    小娘纸阅读 3,386评论 4 7
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,531评论 28 53