Eureka注册中心

1、什么是注册中心

打个比方,注册中心就好比手机中的通讯录,所有的联系人的联系方式就在这个通讯录中储存。当需要打电话的时候,只需要查询通讯录就可以获取某个联系人的联系方式。

注册中心类似于通信录,只不过注册中心储存的不是联系人的联系方式,而是每个服务的信息,从注册中心获取服务就好比通讯录的查询联系人,向注册中心注册服务,就好比通讯录的保存联系人,先有注册,才能查找。

注:注册中心只不过是用来注册和获取服务,并不会用来调取服务,具体的调取服务有获取服务方实现。就好比通讯录只负责储存和查询联系人,查到联系人后使用拨号软件拨打查询到的联系人电话。

2、CAP原则和BASE理论

2.1、CAP原则

名称 描述
Consistency 一致性。也叫做原子性。系统在执行某些操作后数据仍然处于一致的状态。在分布式系统中,更新操作执行成功后所有的用户都应该读到最新的值,这样的系统被认为是具有强一致性的。等同于所有节点访问同一份最新的数据副本。
Availability 可用性。每一个操作总是能够在一定的时间内返回结果,这里需要注意的是"一定时间内"和"返回结果”。一定时间内指的是在可以容忍的范围内返回结果,结果可以是成功或者是失败,且不保证获取的数据为最新数据。
Partition tolerance 分区容错性。分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障。

CAP原则又称CAP定理。值得是在系统中,ConsistencyAvailabilityPartition tolerance三者不可兼得。最多只能同时满足其中两者。

CAP 由 Eric Brewer 在 2000 年 PODC 会议上提出。该猜想在提出两年后被证明成立,成为我们熟知的 CAP定理。CAP三者不可兼得。

  • CA:一致性和可用性。如果同时要满足一致性和可用性,那么只有单体应用可以实现。因为如果是分布式应用的话,如果要保证多个系统的一致性,可定要消耗时间。那么可用性肯定就达不到要求。只有单体应用,可以满足CA
  • CP:一致性和分区容错性。这种典型的案例就是涉及到金钱的系统。涉及到金钱的系统肯定要保证数据一致,在分布式中多台服务器要保证数据一致,肯定不能再一定的时间内返回数据。好比在进行金钱转账的时候,宁愿牺牲可用性,也要保证数据一致性。
  • AP:可用性和分区容容错性。这种的经典案例就是抢购性的系统。例如春运的火车票,有时候明明看到还有票,但是在下单的时候却被告知没票了,这就是因为需要满足可用性,在一定的时间内返回数据,从而放弃了数据的一致性。但是这种情况在最后会有一个最终一致性。好比购票,显示的是还有车票,但是下单时却显示失败,就是因为最终一致性。在最后的时候会进行一致性判断。

如今,对于大多数互联网应用场景,主机众多,部署分散,并且规模也越来越大,节点只会越来越多,所以节点故障、网络故障时常态,分区容错性也就成为了一个分布式系统必然要面对的问题。那么就只能在C和A之前进行取舍。但是对于设计金钱的系统却不同,涉及到金钱的是非常重要的,宁愿牺牲A,也要保证C。如果出现机器故障的话,宁愿停止服务。

没有最好的策略,只有最符合当前系统的策略。

2.2、BASE理论

CAP 理论已经提出好多年了,难道真的没有办法解决这个问题吗?也许可以做些改变。比如 C 不必使用那么强的一致性,可以先将数据存起来,稍后再更新,实现所谓的 “最终一致性”。这个思路又是一个庞大的问题,同时也引出了第二个理论 BASE 理论。

BASE全称为 Basically Available(基本可用)、Soft state(软状态)和Eventually consistent(最终一致性)三个短语句的缩写,来自 ebay 的架构师提出。

BASE 理论是对 CAP 中一致性和可用性权衡的结果,其来源于对大型互联网分布式实践的总结,是基于 CAP 定理逐步演化而来的。其核心思想是:既然无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

2.2.1、Basically Available(基本可用)

基本可用是指分布式系统在出现故障时,允许损失部分可用性(例如响应时间、功能上的可用性)。需要注意的是,基本可用绝不等价于系统不可用。

  • 响应时间上的丢失:例如原先查询数据只需要0.5秒,但是现在由于机器故障可以运行返回响应时间变为1~2秒。
  • 功能上的可用性:例如双十一购物的时候,为了满足非常庞大的流量冲击,为了保证系统的大方向的稳定,允许对一些服务降级处理(缩减服务器集群,给别的访问量大的使用)或者停止一些非必要的服务。

2.2.2、Soft state(软状态)

相对于原子性而言,要求多个节点的数据副本都是一致的,这是一种 “硬状态”。

软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据会有多个副本,允许不同副本数据同步的延时就是软状态的体现。

2.2.3、Eventually consistent(最终一致性)

系统不可能一直是软状态,必须有个时间期限。在期限过后,应当保证所有副本保持数据一致性。从而达到数据的最终一致性。这个时间期限取决于网络延时,系统负载,数据复制方案设计等等因素。

实际上,不只是分布式系统使用最终一致性,关系型数据库在某个功能上,也是使用最终一致性的,比如备份,数据库的复制都是需要时间的,这个复制过程中,业务读取到的值就是旧值。当然,最终还是达成了数据一致性。这也算是一个最终一致性的经典案例。

3、为什么需要注册中心

在分布式系统中,不仅仅是需要在注册中心找到服务和服务地址的映射关系那么简单,还需要考虑很多的复杂问题:

  • 服务注册后,如何被及时的发现
  • 服务宕机后,如何及时处理下线
  • 服务如何有效的水平扩展
  • 服务发现时,如何进行路由
  • 服务异常时,如何进行降级
  • 注册溪红心如果实现自身的高可用

这些问题的解决都依赖于注册中心。简单看,注册中心的功能有点类似于 DNS 服务器或者负载均衡器,而实际上,注册中心作为微服务的基础组件,可能要更加复杂,也需要更多的灵活性和时效性。当然上面的问题,单单使用注册中心是无法完成的,还需要使用SpringCloud的其他组件共同完成。

注册中心解决了一下问题:

  • 服务管理
  • 服务之间的自动发现
  • 服务的依赖关系管理

4、Eureka

4.1、Eureka介绍

Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

4.2、Eureka注册中心的各个角色

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

4.3、Eureka入门案例

4.3.1、创建Mave聚合项目

  • server01:注册中心
  • server02:注册中心(后期搭建集群版准备)
  • provider:服务提供者
  • consumer:服务消费者

4.3.2、添加依赖,配置文件

4.3.2.1、父项目

pom.xml

<!-- 继承 spring-boot-starter-parent 依赖 -->
<!-- 使用继承方式,实现复用,符合继承的都可以被使用 -->
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.0.RELEASE</version>
</parent><!--集中定义依赖组件版本号,但不引入,在子工程中用到声明的依赖时,可以不加依赖的版本号,这样可以统一管理工程中用到的依赖版本-->
<properties><!-- Spring Cloud Hoxton.SR1 依赖 --><spring-cloud.version>Hoxton.SR5</spring-cloud.version>
</properties><!-- 项目依赖管理 父项目只是声明依赖,子项目需要写明需要的依赖(可以省略版本信息) -->
<dependencyManagement><dependencies><!-- spring cloud 依赖 --><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>

4.3.2.2、server02

pom.xml

<!-- 项目依赖 -->
<dependencies><!-- netflix eureka server 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!-- spring boot web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- spring boot test 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies>

application.yml

server:port: 8761 # 端口spring:application:name: eureka-server # 应用名称# 配置 Eureka Server 注册中心
eureka:instance:hostname: localhost           # 主机名,不配置的时候将根据操作系统的主机名来获取client:register-with-eureka: false   # 是否将自己注册到注册中心,默认为 truefetch-registry: false         # 是否从注册中心获取服务注册信息,默认为 trueservice-url:                  # 注册中心对外暴露的注册地址defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

如果是单节点需要把register-with-eurekafetch-registry设置为false,否则会报错

4.3.3、单节点启动

package cn.yanghuisen;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/*** @author admin* @version 1.0* @date 2020/6/15 15:16* @Description TODO*/
@SpringBootApplication
@EnableEurekaServer     // 开启EurekaServer注解
public class EurekaServer01Application {public static void main(String[] args) {SpringApplication.run(EurekaServer01Application.class);}
}

访问:http://localhost:8761/

4.3.4、高可用(集群)

server02

pom.xml

<!-- 项目依赖 -->
<dependencies><!-- netflix eureka server 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!-- spring boot web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- spring boot test 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>cn.yanghuisen</groupId><artifactId>eureka-server01</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope></dependency>
</dependencies>

server02:application.yml

server:port: 8762 # 端口spring:application:name: eureka-server # 应用名称(集群下相同)# 配置 Eureka Server 注册中心
eureka:instance:hostname: eureka02            # 主机名,不配置的时候将根据操作系统的主机名来获取client:# 设置服务注册中心地址,指向另一个注册中心service-url:                  # 注册中心对外暴露的注册地址defaultZone: http://localhost:8761/eureka/

server01:application.yml

server:port: 8761 # 端口spring:application:name: eureka-server # 应用名称(集群下相同)# 配置 Eureka Server 注册中心
eureka:instance:hostname: eureka01            # 主机名,不配置的时候将根据操作系统的主机名来获取client:# 设置服务注册中心地址,指向另一个注册中心service-url:                  # 注册中心对外暴露的注册地址defaultZone: http://localhost:8762/eureka/

server02:启动类

package cn.yanghuisen;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/*** @author admin* @version 1.0* @date 2020/6/15 15:16* @Description TODO*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer02Application {public static void main(String[] args) {SpringApplication.run(EurekaServer01Application.class);}
}

访问:http://localhost:8761/ 或者 http://localhost:8762/

4.3.5、显示IP+端口

(server01和server02):application.yml

eureka:instance:prefer-ip-address: true       # 是否使用 ip 地址注册instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port

4.3.6、provider

pom.xml

<!-- 项目依赖 -->
<dependencies><!-- netflix eureka client 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- spring boot web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- lombok 依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><!-- spring boot test 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies>

application.yml

server:port: 7070 # 端口spring:application:name: service-provider # 应用名称(集群下相同)# 配置 Eureka Server 注册中心
eureka:instance:prefer-ip-address: true       # 是否使用 ip 地址注册instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:portclient:service-url:                  # 设置服务注册中心地址defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

实体类

package cn.yanghuisen.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {private Integer id;private String productName;private Integer productNum;private Double productPrice;}

控制层

package cn.yanghuisen.controller;import cn.yanghuisen.pojo.Product;
import cn.yanghuisen.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/product")
public class ProductController {@Autowiredprivate ProductService productService;/*** 查询商品列表** @return*/@GetMapping("/list")public List<Product> selectProductList() {return productService.selectProductList();}}

服务类:接口

package cn.yanghuisen.service;import cn.yanghuisen.pojo.Product;import java.util.List;/*** 商品服务*/
public interface ProductService {/*** 查询商品列表** @return*/List<Product> selectProductList();}

服务类:实现类

package com.example.service.impl;import com.example.pojo.Product;
import com.example.service.ProductService;
import org.springframework.stereotype.Service;import java.util.Arrays;
import java.util.List;/*** 商品服务*/
@Service
public class ProductServiceImpl implements ProductService {/*** 查询商品列表** @return*/@Overridepublic List<Product> selectProductList() {return Arrays.asList(new Product(1, "华为手机", 2, 5888D),new Product(2, "联想笔记本", 1, 6888D),new Product(3, "小米平板", 5, 2666D));}}

启动类

package cn.yanghuisen;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
// 开启 EurekaClient 注解,目前版本如果配置了 Eureka 注册中心,默认会开启该注解
//@EnableEurekaClient
public class ServiceProviderApplication {public static void main(String[] args) {SpringApplication.run(ServiceProviderApplication.class, args);}}

访问:http://localhost:8761/ 或者 http://localhost:8762/。查看服务提供者是否已经注册到注册中心

4.3.7、consumer

pom.xml

<!-- 项目依赖 -->
<dependencies><!-- netflix eureka client 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><exclusions><exclusion><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId></exclusion></exclusions></dependency><!-- spring boot web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- lombok 依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><!-- spring boot test 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies>

application.yml

server:port: 9090 # 端口spring:application:name: service-consumer # 应用名称# 配置 Eureka Server 注册中心
eureka:client:register-with-eureka: false         # 是否将自己注册到注册中心,默认为 trueregistry-fetch-interval-seconds: 10 # 表示 Eureka Client 间隔多久去服务器拉取注册信息,默认为 30 秒service-url:                        # 设置服务注册中心地址defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

实体类

package cn.yanghuisen.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {private Integer id;private String productName;private Integer productNum;private Double productPrice;}
package cn.yanghuisen.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.util.List;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order implements Serializable {private Integer id;private String orderNo;private String orderAddress;private Double totalPrice;private List<Product> productList;}

消费服务:接口

package cn.yanghuisen.service;import cn.yanghuisen.pojo.Order;public interface OrderService {/*** 根据主键查询订单** @param id* @return*/Order selectOrderById(Integer id);}

控制层

package cn.yanghuisen.controller;import cn.yanghuisen.pojo.Order;
import cn.yanghuisen.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
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;@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate OrderService orderService;/*** 根据主键查询订单** @param id* @return*/@GetMapping("/{id}")public Order selectOrderById(@PathVariable("id") Integer id) {return orderService.selectOrderById(id);}}

消费服务:方式一

package cn.yanghuisen.service.impl;import cn.yanghuisen.pojo.Order;
import cn.yanghuisen.pojo.Product;
import cn.yanghuisen.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;import java.util.List;@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;/*** 根据主键查询订单** @param id* @return*/@Overridepublic Order selectOrderById(Integer id) {return new Order(id, "order-001", "中国", 31994D,selectProductListByDiscoveryClient());}private List<Product> selectProductListByDiscoveryClient() {StringBuffer sb = null;// 获取服务列表List<String> serviceIds = discoveryClient.getServices();if (CollectionUtils.isEmpty(serviceIds))return null;// 根据服务名称获取服务List<ServiceInstance> serviceInstances = discoveryClient.getInstances("service-provider");if (CollectionUtils.isEmpty(serviceInstances))return null;ServiceInstance si = serviceInstances.get(0);sb = new StringBuffer();sb.append("http://" + si.getHost() + ":" + si.getPort() + "/product/list");// ResponseEntity: 封装了返回数据ResponseEntity<List<Product>> response = restTemplate.exchange(sb.toString(),HttpMethod.GET,null,new ParameterizedTypeReference<List<Product>>() {});return response.getBody();}
}

消费服务:方式二

package cn.yanghuisen.service.impl;import cn.yanghuisen.pojo.Order;
import cn.yanghuisen.pojo.Product;
import cn.yanghuisen.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.List;@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate LoadBalancerClient loadBalancerClient; // Ribbon 负载均衡器/*** 根据主键查询订单** @param id* @return*/@Overridepublic Order selectOrderById(Integer id) {return new Order(id, "order-001", "中国", 31994D,selectProductListByLoadBalancerClient());}private List<Product> selectProductListByLoadBalancerClient() {StringBuffer sb = null;// 根据服务名称获取服务ServiceInstance si = loadBalancerClient.choose("service-provider");if (null == si)return null;sb = new StringBuffer();sb.append("http://" + si.getHost() + ":" + si.getPort() + "/product/list");// ResponseEntity: 封装了返回数据ResponseEntity<List<Product>> response = restTemplate.exchange(sb.toString(),HttpMethod.GET,null,new ParameterizedTypeReference<List<Product>>() {});return response.getBody();}
}

消费服务:方式三

启动类

@Bean
@LoadBalanced // 负载均衡注解
public RestTemplate restTemplate() {return new RestTemplate();
}
package cn.yanghuisen.service.impl;import cn.yanghuisen.pojo.Order;
import cn.yanghuisen.pojo.Product;
import cn.yanghuisen.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.List;@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate RestTemplate restTemplate;/*** 根据主键查询订单** @param id* @return*/@Overridepublic Order selectOrderById(Integer id) {return new Order(id, "order-001", "中国", 31994D,selectProductListByLoadBalancerAnnotation());}private List<Product> selectProductListByLoadBalancerAnnotation() {// ResponseEntity: 封装了返回数据ResponseEntity<List<Product>> response = restTemplate.exchange("http://service-provider/product/list",HttpMethod.GET,null,new ParameterizedTypeReference<List<Product>>() {});return response.getBody();}
}

访问:http://localhost:9090/order/1

4.3.8、自我保护

一般情况下,服务在 Eureka 上注册后,会每 30 秒发送心跳包,Eureka 通过心跳来判断服务是否健康,同时会定期删除超过 90 秒没有发送心跳的服务。

有两种情况会导致 Eureka Server 收不到微服务的心跳

  • 微服务自身的原因
  • 微服务与 Eureka 之间的网络故障

自我保护模式

Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,同时提示一个警告。这种算法叫做 Eureka Server 的自我保护模式。

为什么要启动自我保护

  • 因为同时保留"好数据"与"坏数据"总比丢掉任何数据要更好,当网络故障恢复后,这个 Eureka 节点会退出"自我保护模式”。
  • Eureka 还有客户端缓存功能(也就是微服务的缓存功能)。即使 Eureka 集群中所有节点都宕机失效,微服务的 Provider 和 Consumer 都能正常通信。
  • 微服务的负载均衡策略会自动剔除死亡的微服务节点。

关闭自我保护

server01和server02:application.yml

eureka:server:enable-self-preservation: false # true:开启自我保护模式,false:关闭自我保护模式eviction-interval-timer-in-ms: 60000 # 清理间隔(单位:毫秒,默认是 60*1000)

4.3.9、优雅停服

配置了优雅停服以后,将不需要 Eureka Server 中配置关闭自我保护。本文使用 actuator 实现。

1、添加依赖

provider:pom.xml

<!-- spring boot actuator 依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、配置文件

provider:application.yml

# 度量指标监控与健康检查
management:endpoints:web:exposure:include: shutdown         # 开启 shutdown 端点访问endpoint:shutdown:enabled: true               # 开启 shutdown 实现优雅停服

使用 POST 请求访问:http://localhost:7070/actuator/shutdown

4.3.10、Eureka安全认证

1、添加依赖

server01和server02:pom.xml

<!-- spring boot security 依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>

2、配置文件

server01和server02:application.yml

spring:# 安全认证security:user:name: rootpassword: 123456

3、修改访问集群节点的 url

server01和server02:application.yml

# 配置 Eureka Server 注册中心
eureka:instance:hostname: eureka01            # 主机名,不配置的时候将根据操作系统的主机名来获取prefer-ip-address: true       # 是否使用 ip 地址注册instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:portclient:# 设置服务注册中心地址,指向另一个注册中心service-url:                  # 注册中心对外暴露的注册地址defaultZone: http://root:123456@localhost:8762/eureka/

provider:application.yml

# 配置 Eureka Server 注册中心
eureka:instance:prefer-ip-address: true       # 是否使用 ip 地址注册instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:portclient:service-url:                  # 设置服务注册中心地址defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/

consumer:application.yml

# 配置 Eureka Server 注册中心
eureka:client:register-with-eureka: false         # 是否将自己注册到注册中心,默认为 trueregistry-fetch-interval-seconds: 10 # 表示 Eureka Client 间隔多久去服务器拉取注册信息,默认为 30 秒service-url:                        # 设置服务注册中心地址defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/

4.3.11、过滤CSRF

Eureka 会自动化配置 CSRF 防御机制,Spring Security 认为 POST, PUT, and DELETE http methods 都是有风险的,如果这些 method 发送过程中没有带上 CSRF token 的话,会被直接拦截并返回 403 forbidden。

官方给出了解决的方法,具体可以参考 spring cloud issue 2754,里面有大量的讨论,这里提供两种解决方案。

首先注册中心配置一个 @EnableWebSecurity 配置类,继承 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter,然后重写 configure 方法。

方案一:忽略/eureka/的所有请求

server01和server02:配置类

package cn.yanghuisen.config;import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** 安全认证配置类*/
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {super.configure(http); // 加这句是为了访问 eureka 控制台和 /actuator 时能做安全控制http.csrf().ignoringAntMatchers("/eureka/**"); // 忽略 /eureka/** 的所有请求}}

方案二:保持密码验证的同时禁用 CSRF 防御机制

package cn.yanghuisen.config;import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** 安全认证配置类*/
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {// 注意,如果直接 disable 的话会把安全验证也禁用掉http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();}}

(一)SpringCloud之Eureka注册中心相关推荐

  1. SpringCloud之 Eureka注册中心

    文章目录 Eureka注册中心 一.服务注册与发现 1.1 依赖导入

  2. SpringCloud(三) Eureka注册中心介绍以及单机版搭建

    一.Eureka 介绍 Spring Cloud Eureka 是 Spring Cloud Netfix微服务套件中的一部分,它基于 Netfix Eureka 做了二次封装,主要负责完成微服务架构 ...

  3. SpringCloud之一eureka注册中心(Greenwich版本)

    创建服务注册中心 采用Eureka作为服务注册与发现的组件 创建一个maven主工程 首先创建一个主Maven工程,在其pom文件引入依赖,spring Boot版本为2.1.3.RELEASE,Sp ...

  4. SpringCloud将Eureka注册中心更改为CSE注册中心

    我的开发环境是SpringCloud+Eureka,现在要更改为SpringCloud+CSE 1:环境准备 下载CSE本地注册中心:https://cse-bucket.obs.cn-north-1 ...

  5. 走进Spring Cloud之二 eureka注册中心(Greenwich版本)

    走进Spring Cloud之二 eureka注册中心(Greenwich版本) eureka 构建SpringCloud 工程 eureka 注册中心 eureka-server moudle po ...

  6. springcloud(二):注册中心Eureka

    Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service Registry和Service Discovery实现.也是springcloud体系中最重要最核心的组 ...

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

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

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

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

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

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

最新文章

  1. 1030 完美数列(two pointers解法)
  2. 从原理到落地,七大维度详解矩阵分解推荐算法
  3. h3c 3600 交换机配置Telnet登录
  4. ProxyStrike运行bug解决办法
  5. deepblueai
  6. kubernetes视频教程笔记 (32)-安全-准入控制Admission Control
  7. Yarn的原理与资源调度
  8. oracle 触发器 实例
  9. 解决永中集成office和opera的中文输入问题
  10. 我的电脑中无法新建txt文本文档
  11. matlab曲面的最小值,MATLAB中标准三维曲面
  12. Redis 知识点扫盲
  13. 河南信息统计学院微信公众平台API汇总
  14. Ubuntu 阿里源更新 amp;amp; nvidia驱动安装 amp;amp; cuda 安装
  15. 树莓派用GPIO实现模拟交通红绿灯
  16. 天线巴伦制作和原理_传输线巴伦的原理设计制作及测试
  17. 邮件中的html和浏览器不一样,HTML在浏览器中呈现良好,但在电子邮件中呈现不好(HTML是使用dataframe生成的)...
  18. 离线安装ubuntu网卡驱动
  19. 十三、SpringBoot与分布式
  20. 怎么将手机图片转成Word文档?办公常备软件

热门文章

  1. 12-16面向对象之接口和抽象类的应用
  2. 量化交易 简易回测框架
  3. Jad - the latest version
  4. 在J1939中多帧数据如何发送,它是通过TP.CM_BAM和TP_DT报文发送
  5. (dum(b)ug)
  6. Motion Graphics Loops: 2 After Effects Techniques 运动图形循环2: After Effects技术 Lynda课程中文字幕
  7. 人到中年,到底应该坚持打工还是去创业?
  8. Rasbian系统 树莓派Python环境搭建
  9. Raid常见级别(Raid 0、Raid 1、Raid 5、Raid 10)
  10. php生成小学数学练习题