SpringCloud的入门学习之深入理解Eureka注册中心

本文主要是介绍SpringCloud的入门学习之深入理解Eureka注册中心,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、Eureka 注册中心三种角色。

  答:a、Eureka Server,注册中心,通过 Register、Get、Renew 等接口提供服务的注册和发现。
    b、Application Service (Service Provider),服务提供方,把自身的服务实例注册到 Eureka Server中。
    c、Application Client (Service Consumer),服务调用方,通过 Eureka Server获取服务列表,消费服务。

2、Erueka的架构图,如下所示。来源:https://github.com/Netflix/eureka/wiki/Eureka-at-a-glance

解释如下所示:

Eureka Server是Eureka的注册中心。Application Service是Service Provider。Application Client是Service Consumer。Application ServiceApplication Client都是Eureka Client(即Eureka客户端)。

a、Register(服务注册):把自己的 IP 和端口注册给 Eureka。
b、Renew(服务续约):发送心跳包,每 30 秒发送一次。告诉 Eureka 自己还活着。
c、Cancel(服务下线):当 provider 关闭时会向 Eureka 发送消息,把自己从服务列表中删除。防止 consumer 调用到不存在的服务。
d、Get Registry(获取服务注册列表):获取其他服务列表。
e、Replicate(集群中数据同步):eureka 集群中的数据复制与同步。
f、Make Remote Call(远程调用):完成服务的远程调用。

3、什么是CAP原则?

  答:CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。CAP 由 Eric Brewer 在 2000 年 PODC 会议上提出。该猜想在提出两年后被证明成立,成为我们熟知的 CAP 定理。

CAP定律:任何分布式系统只可同时满足二点,没法三者兼顾。 

4、Zookeeper与Eureka的区别。

5、Eureka的优雅停服。在什么条件下,Eureka会启动自我保护?什么是自我保护模式?

  1)、自我保护的条件,一般情况下,微服务在 Eureka上注册后,会每30秒发送心跳包,Eureka通过心跳来判断服务时候健康。同时会定期删除超过 90秒没有发送心跳服务

  2)、但是有两种情况会导致 Eureka Server 收不到微服务的心跳。第一种情况是微服务自身的原因。第二种情况是是微服务与 Eureka 之间的网络故障。如果未设置优雅停服的情况下,此两种情况是不会将服务进行删除的。

    通常(微服务的自身的故障关闭,也被称为单节点故障)只会导致个别服务出现故障,一般不会出现大面积故障。而(网络故障)通常会导致 Eureka Server 在短时间内无法收到大批心跳。考虑到这个区别,Eureka 设置了一个阀值,当判断挂掉的服务的数量超过阀值时, Eureka Server 认为很大程度上出现了网络故障,将不再删除心跳过期的服务。

  3)、那么这个阀值是多少呢?

    如果15 分钟之内是否低于 85%,Eureka Server 在运行期间,会统计心跳失败的比例在 15 分钟内是否低于 85% 这种算法叫做 Eureka Server 的自我保护模式。

  4)、案例如下:启动之前搭建的Eureka Server集群版,启动Provider客户端,启动Consumer客户端,可以在页面查看到都已经注册到Eureka Server注册中心了。

现在将Provider客户端、Consumer客户端关闭(在eclipse停止启动的Provider服务、Consumer服务即可)。

大概翻译如下所示:

如果是大于阈值(85%),Eureka注册中心判定为网络故障,如果小于阈值(85%),Eureka注册中心判定为单节点故障。因为我这里是启动4个服务,就是向Eureka注册中心注册了4个服务,挂了2个,就是50%,远远低于85%。所以Eureka注册中心判定此种情况为单节点故障。Eureka注册中心认为节点在以后可以修复的,所以对出现故障的节点进行了保留,这就是Eureka注册中心的自我保护

6 、Eureka为什么要启动自我保护。

  答:因为同时保留"好数据"与"坏数据"总比丢掉任何数据要更好,当网络故障恢复后,这个 Eureka 节点会退出"自我保护模式"。当你的节点修复好以后,Eureka注册中心会退出自我保护模式。

    为什么Eureka要进行自我保护,因为Eureka 还有客户端缓存功能(也就是微服务的缓存功能),Eureka注册中心缓存了之前注册的信息。即便 Eureka 集群中所有节点都宕机失效,微服务的 Provider 和 Consumer都能正常通信。微服务的负载均衡策略会自动剔除死亡的微服务节点。

7、如何关闭Eureka的自我保护。可以修改Eureka Server配置文件,在Eureka Server的注册中心中进行操作,如下所示:

在你的application.properties配置文件中新增如下配置即可以,关闭自我保护,并在注册中心清理你的无效服务。如果是高可用的,在两个或者多个配置文件application-eureka1.properties、application-eureka2.properties都新增如下配置即可。重启,打包,部署,运行可以查看效果。

1 # 关闭自我保护,值设置为true为开启自我保护。值设置为false为关闭自我保护。
2 eureka.server.enable-self-preservation=false
3 
4 # 清理间隔,单位毫秒,默认是60*1000
5 eureka.server.eviction-interval-timer-in-ms=60000

8、如何进行Eureka的优雅停服,不需要在Eureka Server中配置关闭自我保护,需要再服务中添加actuator.jar包。在服务端进行配置,进行Eureka的优雅停服,上面的在Eureka Server注册中心的关闭自我保护配置就可以注释掉,或者删除掉了。

我这里修改的是服务端provider的pom.xml配置文件,如下所示。将spring-cloud-starter-netflix-eureka-client修改成了spring-cloud-starter-netflix-eureka-client

因为springcloud eureka 服务端包含了actuator.jar包。

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
 5     https://maven.apache.org/xsd/maven-4.0.0.xsd">
 6     <modelVersion>4.0.0</modelVersion>
 7     <parent>
 8         <groupId>org.springframework.boot</groupId>
 9         <artifactId>spring-boot-starter-parent</artifactId>
10         <version>2.2.0.RELEASE</version>
11         <relativePath />
12         <!-- lookup parent from repository -->
13     </parent>
14     <groupId>com.bie</groupId>
15     <artifactId>springcloud-eureka-provider</artifactId>
16     <version>0.0.1-SNAPSHOT</version>
17     <name>springcloud-eureka-provider</name>
18     <description>Demo project for Spring Boot</description>
19 
20     <properties>
21         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
22         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
23         <java.version>1.8</java.version>
24         <spring-cloud.version>Hoxton.RC1</spring-cloud.version>
25         <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
26     </properties>
27 
28     <dependencies>
29         <dependency>
30             <groupId>org.springframework.boot</groupId>
31             <artifactId>spring-boot-starter-web</artifactId>
32         </dependency>
33         <!-- springcloud eureka 服务端也包含了actuator.jar包 -->
34         <!-- pom中引用actuator -->
35         <dependency>
36             <groupId>org.springframework.boot</groupId>
37             <artifactId>spring-boot-starter-actuator</artifactId>
38         </dependency>
39         <dependency>
40             <groupId>org.springframework.cloud</groupId>
41             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
42         </dependency>
43         <dependency>
44             <groupId>org.springframework.boot</groupId>
45             <artifactId>spring-boot-starter-test</artifactId>
46             <scope>test</scope>
47             <exclusions>
48                 <exclusion>
49                     <groupId>org.junit.vintage</groupId>
50                     <artifactId>junit-vintage-engine</artifactId>
51                 </exclusion>
52             </exclusions>
53         </dependency>
54     </dependencies>
55 
56     <dependencyManagement>
57         <dependencies>
58             <dependency>
59                 <groupId>org.springframework.cloud</groupId>
60                 <artifactId>spring-cloud-dependencies</artifactId>
61                 <version>${spring-cloud.version}</version>
62                 <type>pom</type>
63                 <scope>import</scope>
64             </dependency>
65         </dependencies>
66     </dependencyManagement>
67 
68     <build>
69         <plugins>
70             <plugin>
71                 <groupId>org.springframework.boot</groupId>
72                 <artifactId>spring-boot-maven-plugin</artifactId>
73             </plugin>
74         </plugins>
75     </build>
76 
77     <repositories>
78         <repository>
79             <id>spring-milestones</id>
80             <name>Spring Milestones</name>
81             <url>https://repo.spring.io/milestone</url>
82         </repository>
83     </repositories>
84 
85 </project>

新增配置文件,启动shutdown、禁用密码验证,如下所示:

由于springboot1.x版本和springboot2.x版本的差异性,这些配置都进行改变。

可以参考官网:https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-endpoints

1 # 启用 shutdown
2 management.endpoint.shutdown.enabled=true
3 
4 # 暴露shutdown。include后面可以添加你想用到的端点
5 management.endpoints.web.exposure.include=shutdown

如果是springboot2.x版本配置,springboot1.x版本的配置会,出现如下所示报错:

1                 http-outgoing-0 << "{"timestamp":"2019-11-16T05:07:19.423+0000","status":404,"error":"Not Found","message":"No message available","path":"/shutdown"}[\r][\n]"
2 2019-11-16 13:07:19.450 [main] DEBUG org.apache.http.headers -
3                 http-outgoing-0 << HTTP/1.1 404 

如何进行优雅停服的,这个时候不能停止服务。需要发送一个http请求,但是不可以使用浏览器发送请求,因为浏览器发送的都是get请求,该请求必须使用post发送请求的,所以可以使用postman工具或者httpClient工具类,进行优雅停服。

httpclient工具类,代码如下所示:

我这里使用的是"http://localhost:8080/actuator/shutdown,如果只是"http://localhost:8080/shutdown可能会发现并不能将服务进行停止的。

  1 package com.bie.utils;
  2 
  3 import java.io.IOException;
  4 import java.net.URI;
  5 import java.util.ArrayList;
  6 import java.util.List;
  7 import java.util.Map;
  8 
  9 import org.apache.http.NameValuePair;
 10 import org.apache.http.client.entity.UrlEncodedFormEntity;
 11 import org.apache.http.client.methods.CloseableHttpResponse;
 12 import org.apache.http.client.methods.HttpGet;
 13 import org.apache.http.client.methods.HttpPost;
 14 import org.apache.http.client.utils.URIBuilder;
 15 import org.apache.http.entity.ContentType;
 16 import org.apache.http.entity.StringEntity;
 17 import org.apache.http.impl.client.CloseableHttpClient;
 18 import org.apache.http.impl.client.HttpClients;
 19 import org.apache.http.message.BasicNameValuePair;
 20 import org.apache.http.util.EntityUtils;
 21 
 22 public class HttpClientUtil {
 23 
 24     public static String doGet(String url, Map<String, String> param) {
 25 
 26         // 创建Httpclient对象
 27         CloseableHttpClient httpclient = HttpClients.createDefault();
 28 
 29         String resultString = "";
 30         CloseableHttpResponse response = null;
 31         try {
 32             // 创建uri
 33             URIBuilder builder = new URIBuilder(url);
 34             if (param != null) {
 35                 for (String key : param.keySet()) {
 36                     builder.addParameter(key, param.get(key));
 37                 }
 38             }
 39             URI uri = builder.build();
 40 
 41             // 创建http GET请求
 42             HttpGet httpGet = new HttpGet(uri);
 43 
 44             // 执行请求
 45             response = httpclient.execute(httpGet);
 46             // 判断返回状态是否为200
 47             if (response.getStatusLine().getStatusCode() == 200) {
 48                 resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
 49             }
 50         } catch (Exception e) {
 51             e.printStackTrace();
 52         } finally {
 53             try {
 54                 if (response != null) {
 55                     response.close();
 56                 }
 57                 httpclient.close();
 58             } catch (IOException e) {
 59                 e.printStackTrace();
 60             }
 61         }
 62         return resultString;
 63     }
 64 
 65     public static String doGet(String url) {
 66         return doGet(url, null);
 67     }
 68 
 69     public static String doPost(String url, Map<String, String> param) {
 70         // 创建Httpclient对象
 71         CloseableHttpClient httpClient = HttpClients.createDefault();
 72         CloseableHttpResponse response = null;
 73         String resultString = "";
 74         try {
 75             // 创建Http Post请求
 76             HttpPost httpPost = new HttpPost(url);
 77             // 创建参数列表
 78             if (param != null) {
 79                 List<NameValuePair> paramList = new ArrayList<>();
 80                 for (String key : param.keySet()) {
 81                     paramList.add(new BasicNameValuePair(key, param.get(key)));
 82                 }
 83                 // 模拟表单
 84                 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
 85                 httpPost.setEntity(entity);
 86             }
 87             // 执行http请求
 88             response = httpClient.execute(httpPost);
 89             resultString = EntityUtils.toString(response.getEntity(), "utf-8");
 90         } catch (Exception e) {
 91             e.printStackTrace();
 92         } finally {
 93             try {
 94                 response.close();
 95             } catch (IOException e) {
 96                 // TODO Auto-generated catch block
 97                 e.printStackTrace();
 98             }
 99         }
100 
101         return resultString;
102     }
103 
104     public static String doPost(String url) {
105         return doPost(url, null);
106     }
107 
108     public static String doPostJson(String url, String json) {
109         // 创建Httpclient对象
110         CloseableHttpClient httpClient = HttpClients.createDefault();
111         CloseableHttpResponse response = null;
112         String resultString = "";
113         try {
114             // 创建Http Post请求
115             HttpPost httpPost = new HttpPost(url);
116             // 创建请求内容
117             StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
118             httpPost.setEntity(entity);
119             // 执行http请求
120             response = httpClient.execute(httpPost);
121             resultString = EntityUtils.toString(response.getEntity(), "utf-8");
122         } catch (Exception e) {
123             e.printStackTrace();
124         } finally {
125             try {
126                 response.close();
127             } catch (IOException e) {
128                 // TODO Auto-generated catch block
129                 e.printStackTrace();
130             }
131         }
132 
133         return resultString;
134     }
135 
136     public static void main(String[] args) {
137         // 请求地址是你的客户端服务的地址。
138         String url = "http://localhost:8080/actuator/shutdown";
139         // 该url必须要使用dopost方式来发送
140         HttpClientUtil.doPost(url);
141     }
142 
143 }

使用postman停止的效果如下所示:

9、如何加强Eureka注册中心的安全认证。如果不进行安全认证的话,无论谁根据url打开Eureka管理界面,这样很不安全,如下操作进行安全认证操作。在Eureka Server中添加security 包,新增jar包,配置如下所示:

1 <!-- security安全认证 -->
2 <dependency>
3     <groupId>org.springframework.boot</groupId>
4     <artifactId>spring-boot-starter-security</artifactId>
5 </dependency>

由于我使用的Eureka是高可用的,所以集群节点之间的相互访问,需要将账号密码写入到请求地址里面。新增的配置如下所示:

修改配置文件,maven install,上传到服务器,运行,启动以后,登录界面如下所示:

登录成功以后和之前的界面完全一致。

注意,因为现在开启了安全认证,如果服务端,Provider客户端或者Consumer客户端,在配置文件里面都需要加上你配置的账号和密码。如果不添加会导致启动失败的哦。这块尤为的坑,自己注意吧,感觉Springboot的升级太变态了。

1 # 客户端需要向服务端进行注册,必须配置服务端的地址。知道服务端在那里。
2 #设置服务注册中心地址,可以将集群中的所有节点列处理。 
3 eureka.client.serviceUrl.defaultZone=http://eureka:123456@eureka1:8761/eureka/,http://eureka:123456@eureka2:8761/eureka/

 

作者:别先生

博客园:https://www.cnblogs.com/biehongli/

如果您想及时得到个人撰写文章以及著作的消息推送,可以扫描上方二维码,关注个人公众号哦。

 

这篇关于SpringCloud的入门学习之深入理解Eureka注册中心的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1060539

相关文章

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

[word] word设置上标快捷键 #学习方法#其他#媒体

word设置上标快捷键 办公中,少不了使用word,这个是大家必备的软件,今天给大家分享word设置上标快捷键,希望在办公中能帮到您! 1、添加上标 在录入一些公式,或者是化学产品时,需要添加上标内容,按下快捷键Ctrl+shift++就能将需要的内容设置为上标符号。 word设置上标快捷键的方法就是以上内容了,需要的小伙伴都可以试一试呢!

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型