注册中心可以说是微服务架构中的”通讯录“,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其他服务时,
就到这里找到服务的地址进行调用
特性 | Eureka | Nacos | Consul | Zookeeper |
---|---|---|---|---|
CAP | AP | CP+AP | CP | CP |
健康检查 | Client Beat | TCP/HTTP/MYSQL/Client Beat | TCP/HTTP/GRPC/CMD | Keep Alive |
雪崩保护 | 有 | 有 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
访问协议 | HTTP | HTTP/DNS | HTTP/DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 |
跨注册中心同步 | 不支持 | 支持 | 支持 | 不支持 |
SpringCloud继承 | 支持 | 支持 | 支持 | 支持 |
Spring-Cloud Eureka是Spring Cloud集合中的一个组件,它是对Eureka的集成,用于服务注册和发现。Eureka是Netflix中的一个开源框架
。它和Zookeeper、Consul一样,都是用户服务注册管理的,同样Spring-Cloud还集成了Zookeeper和Consul。在项目中使用Spring Cloud
的原因是它可以利用Spring Cloud Netflix中的其他组件,如zuul等。
Eureka由多个instance(服务实例)组成,这些服务实例可以分为两种:Eureka Server和Eureka Client。而Eureka Client为
了便于理解,进一步分为Service Provider和Service Consumer,满足CAP定理的AP,高可用与可申诉的Service发现服务,突出可用性,
相对于Zookeeper而言,可能返回数据没有一致性,但是能保证能够返回数据,服务时可用的
分布式系统正变得越来越重要,大型网站介乎都是分布式的。分布式系统的最大难点,就是各个节点的状态如何同步,CAP定理是这方面的基本定理,也是理解分布式
系统的起点
一致性与可用性不能同时成立的原因就是区间通信可能会失败,即会出现分区容错
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.5.3version>
<relativePath/>
parent>
<groupId>com.lmgroupId>
<artifactId>eurake-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>eureka-servername>
<description>eureka-serverdescription>
<properties>
<java.version>1.8java.version>
<spring-cloud.version>2020.0.3spring-cloud.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
@EnableEurekaServer
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
spring:
application:
name: eureka-server # 应用名称
server:
port: 8761
eureka:
instance:
hostname: localhost #实例主机名称,不配置的时候将根据操作系统的主机名来获取
client:
service-url:
defaultZone: http://localhost:8761/eureka/ # 注册中心对外暴露的注册地址
register-with-eureka: false # 禁止将自身注册到注册中心
fetch-registry: false # 是否从注册中心获取服务注册信息
server:
enable-self-preservation: false # 关闭自我保护机制,线上需要开启
一般情况下,服务在Eureka上注册后,会每30s发送心跳包,Eureka通过心跳来判断服务是否健康,
同时会定期删除超过90秒没有发送心跳的服务。
**一般有两种情况会导致Eureka Server收不到服务的心跳: **
自我保护模式
Eureka Server在运行期间回去统计心跳失败比列在分钟之内是否低于85%,如果低于85%,Eureka Serve
r会讲这些实例保护起来,让这些实例不会过期,同时提示一个警告。这种算法叫做Eureka Server的自我保护模式
eureka:
server:
enable-self-preservation: false # 关闭自我保护机制,线上需要开启
eviction-interval-timer-in-ms: 60000 # 清理间隔
配置了优雅停服以后,将不需要Eureka Server中配置关闭自我保护。
服务提供者添加actuator依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
服务提供者配置度量指标监控与健康检查
management:
endpoints:
web:
exposure:
include: shutdown #开启shutdown断点访问
endpoint:
shutdown:
enabled: true #开启shutdown实现优雅停服
注册中心添加security依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
注册中心配置安全认证
spring:
security:
user:
name: root
password: 123456
eureka-server(注册中心) 配置文件
client:
service-url:
defaultZone: http://root:123456@localhost:8762/eureka/
eureka-server-replica(注册中心副本) 配置文件
client:
service-url:
defaultZone: http://root:123456@localhost:8761/eureka/
product-service(服务提供者)配置文件
client:
service-url:
defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/
user-service(服务消费)配置文件
client:
service-url:
defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/
Eureka会自动化配置CSRF防御机制,Spring Security认为POST、PUT、DELETE等HTTP METHODS都是有风险的,如果这个method发送
过程中没有带上CSRF token的话,会被直接拦截并返回403 forbidden。
主要两种解决方案首先注册中心配置一个@EnableWebSecurity配置类,
继承org.springframework.security.config.annotation.web.configuration.WebSecurityConfigureAdapter,
重写configure方法
使CSRF忽略/eureka/**的所有请求
package com.lm.eurakeserver.configuration;
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 {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);//加这句是为了访问eureka控制台和/actuator时能做安全控制
http.csrf().ignoringAntMatchers("/eureka/**");//忽略/eureka/**的所有请求
}
}
保证密码验证的同时禁用CSRF防御机制
package com.lm.eurekaserverreplica.configuration;
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 {
@Override
protected void configure(HttpSecurity http) throws Exception {
//注意:若直接disable的话会把安全验证也禁用掉
http.csrf().disable().authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,无需独立部署,存在每个微服务中。提供了多种负载均衡算法(轮询、随机等)
目前业界主流两种负载均衡方案
策略对应列名:RoundRobinRule
实现原理:轮询策略表示每次都顺序获取下一个provider,比如5个provider,第一次获取第一个,二次获取第二个,依次类推
根据每个provider的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性就越低
策略对应类名:WeightedResponseTimeRule
实现原理:初始为轮询策略,并开启一个定时器,每30秒手机一次每个provider的平均响应时间,当信息足够是,给每个provider附上一个权重,并按权重随机选择provider,权重越高
,被选中的概率就越高
策略对应类名:RandomRule
实现原理:从provider列表中随机选中一个
策略对应类名:BestAvailableRule
实现原理:选择正在请求中的并发数最小的provider,除非这个provider在熔断中
策略对应类名:RetryRule
实现原理:轮询策略的增强版,轮询策略服务不可用时不做处理,重试策略服务不可用时会重新尝试集群中的其他节点
策略对应类名:AvailabilityFilteringRule
实现原理:过滤性能差的provider,一种是过滤掉在Eureka中一直连接失败的provider,一种是过滤掉高并发(繁忙)的provider
策略对应类名:ZoneAvoidanceRule
实现原理:以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下的区域中选择可用的provider,若这个ip区域内有一个或多个实例不可达或响应变慢,
都会降低该区域的其他provider被选中的权重
在启动类或配置类中注入负载均衡策略对象。所有服务请求均使用该策略
import org.springframework.context.annotation.Configuration;
@Configuration
public class RibbonConfiguration {
@Bean
public RandomRule randomRule() {
return new RandomRule();
}
}
修改配置文件指定服务的负载均衡策略。格式:服务应用名.ribbon.NFLoadBalancerRuleClassName
product-service: # 需要调用的服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandoRule
点对点直连是指绕过注册中心,直接连接服务提供者获取服务,一般在测试阶段使用比较多
在pom文件中引入Ribbon,需要注意的是如果pom中有Eureka的依赖,则需要去除Eureka的依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
dependency>
配置文件中关闭Eureka,添加直连的服务地址。如果不设置负载均衡策略默认使用轮询策略
# 负载均衡策略
#product-service: 调用的服务名称
product-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
# 指定具体Provider服务列表,多个用逗号分隔
listOfServers: http://localhost:8080,http://localhost:8082
# 关闭Eureka实现Ribbon的点对点直连
ribbon:
eureka:
enabled: false