服务提供者、服务消费者、服务注册中心三者的关系
-
各个微服务在启动时,将自己的网络地址等信息注册到服务注册中心,服务注册中心会存储这些信息
-
服务消费者可从服务注册中心查询服务提供者的网络地址,并使用该地址调用服务提供者的接口
-
各个微服务与服务注册中心使用一定机制(如心跳)通信。服务注册中心若长时间无法与某微服务实例通信,就会注销该实例
-
微服务网络地址发生变更(例如实例增减或者IP端口发生变化等)时,会重新注册到服务发现组件。使用这种方式,服务消费者就无需人工修改提供者的网络地址
1. Eureka Server 注册中心搭建步骤
-
创建SpringBoot工程,添加eureka-server的起步依赖
<--SpringBoot 版本使用的是 2.4.5 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
配置文件中添加eureka server相关配置
spring.application.name=eurekaServer server.port=8761 #收否从Eureka server获取注册信息,默认为true,因为当前应用是一个单点的Eureka server eureka.client.fetch-registry=false #是否将自己注册到Eureka Server eureka.client.register-with-eureka=false #设置于Eureka server交互的地址,查询和注册服务都需要该地址 eureka.client.service-url.defaultZone=http://localhost:8761/eureka
-
启动类添加注解@EnableEurekaServer
2. Eureka Client客户端搭建步骤
Eureka Client客户端主要包括服务提供者和消费者,需要把这两个都注册到注册中心上.
1. 服务提供者
主要是使用Mybatis-plus从数据库获取用户信息,使用Mybatis-plus方便对单表进行操作
-
添加Eureka client依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
配置文件中添加Eureka Client相关配置
server.port=8000 eureka.client.service-url.defaultZone=http://localhost:8761/eureka eureka.instance.prefer-ip-address=true
2. 服务消费者
-
添加Eureka client依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
-
添加配置文件
server.port=8081 eureka.client.service-url.defaultZone=http://localhost:8761/eureka eureka.instance.prefer-ip-address=true
-
编写cotroller调用服务提供者的API接口
在MoiveserviceApplication启动类中添加注册RestTemplate的Bean
@Bean public RestTemplate restTemplate() { return new RestTemplate(); }
在controller类中调用API接口
@Autowired private RestTemplate restTemplate; @GetMapping("/user/{id}") public User findById(@PathVariable long id) { //地址使用hardCode方式不可取 return restTemplate.getForObject("http://localhost:8000/"+id,User.class); }
二. 高可用服务注册中心
1. Eureka高可用的作用
在微服务架构这样的分布式环境中,我们需要充分考虑发生故障的情况,很难保证单节点的Eureka服务能提供100%不间断的服务,如果Eureka无响应了,整个项目就会出现问题,所以在生成环境中必须对各个组件进行高可用部署,要保障Eureka随时都能提供服务的情况下,最好的方式就是采用Eureka的集群模式,也就是搭建Eureka的高可用。
2. Eureka高可用的搭建(双机)
还是使用上面的单节点Eureka server进行改造
-
对配置文件的修改:新增2个配置文件:application-peer1.properties 和 application-peer2.properties,加上application.propertites文件,总共就3个配置文件
具体配置如下
application.propertites文件如下:
spring.application.name=eurekaServer spring.profiles.active=peer1
application-peer1.properties文件如下:
server.port=8761 #收否从Eureka server获取注册信息,默认为true,因为当前应用是一个单点的Eureka server #eureka.client.fetch-registry=false #是否将自己注册到Eureka Server #eureka.client.register-with-eureka=false eureka.instance.hostname=peer1 eureka.instance.prefer-ip-address=false eureka.client.fetch-registry=true eureka.client.register-with-eureka=true #设置于Eureka server交互的地址,查询和注册服务都需要该地址 eureka.client.service-url.defaultZone=http://peer2:8762/eureka
application-peer2.properties文件如下:
server.port=8762 #收否从Eureka server获取注册信息,默认为true,因为当前应用是一个单点的Eureka server #eureka.client.fetch-registry=false #是否将自己注册到Eureka Server #eureka.client.register-with-eureka=false eureka.instance.hostname=peer2 eureka.instance.prefer-ip-address=false eureka.client.register-with-eureka=true eureka.client.fetch-registry=true #设置于Eureka server交互的地址,查询和注册服务都需要该地址 eureka.client.serviceUrl.defaultZone=http://peer1:8761/eureka
-
由于在同一台电脑上搭建双节点Eureka集群,需要使用不同的hostName,所以需要去修改hosts文件,让上面配置的hostname能在本地正确的访问到
-
通过spring.profiles.active属性分别来启动peer1 和peer2
-
-
启动peer1
-
启动peer2
也可先打包后在通过命令 java -jar eurekaserver-1.0.0.jar --spring.profiles.active=peer1 和 java -jar eurekaserver-1.0.0.jar --spring.profiles.active=peer1来分别启动2个应用。
-
-
分别访问http://peer1:8761 和 http://peer2:8762
-
peer1:8761
-
peer2:8762
-
-
3. 搭建过程中遇到的问题
问题一: 启动过程中报错,com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
由于我们搭建的是双机的Eureka集群,刚刚才启动一台,找不到另外peer2的服务,当时一看启动就报错了,还以为哪里出什么问题了呢,等两个服务都启动起来就好了。
问题二:注册中心出现在unavaliable-replicas上面
-
当只启动了一个服务,去访问http://peer1:8761时会出现上面的情况
-
如果把eureka.instance.prefer-ip-address=true的话也会出现上面的情况,请检查application配置文件,配置如下,
eureka.instance.prefer-ip-address=false
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
三. 用户认证
前面的单节点还是集群的Eureka server注册中心,都允许直接通过输入地址和端口号就可以匿名访问,但是在实际项目中必须经过用户认证后才允许访问Eureka server。
1. 搭建步骤
-
添加security的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
-
修改配置文件,在配置文件中添加用户名和密码,设置defaultZone=http://name:password@ip:prot/eureka
#application.propertites spring.security.user.name=root spring.security.user.password=123456 #application-peer1.propertites eureka.client.service-url.defaultZone=http://root:123456@peer2:8762/eureka #application-peer1.propertites eureka.client.service-url.defaultZone=http://root:123456@peer1:8761/eureka
-
关闭Spring Security的CSRF认证,新建一个WebSecurityConfig的配置类,并继承WebSecurityConfigurerAdapter类,重写里面的configure方法
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable();//关闭csrf super.configure(http); }
-
访问页面并输入用户名和密码
-
2. 搭建过程中遇见的问题
问题一:启动过程中报错,com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
如果没有上面搭建过程的第3步的话,没有关闭spring security的csrf认证的话,就会抛出上面的错误。
1.1 actuator微服务信息服务
-
主机名称: 服务名称修改
在实际工作中在eureka服务注册中心只需要暴露服务名称,不需要将主机名称暴露,在application.yml配置文件中添加instance-id如下配置
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost2:7002/eureka
instance:
instance-id: payment8001 -
访问信息有Ip信息提示
在实际工作中微服务可能部署到多台服务器中,在服务注册中心可以查看服务具体部署到那台机器上的,添加配置
prefer-ip-address
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost2:7002/eureka
instance:
instance-id: payment8002
prefer-ip-address: true
1.2 微服务提供者集群
消费者访问微服务提供者集群时需要使用负载均衡注解@LoadBalanced
, 而且不能使用固定的IP地址,需要使用注册中心的服务名称
Ribbon和Eureka整合后Consumer可以直接调用服务而不再关心地址和端口号,且该服务还有负载功能
1.3 服务发现discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
1.4 Eureka自我保护
概述
保护模式主要用于一组客户端和Eureka server之间存在网络分区场景下的保护,一旦进入保护模式,Eureka serve将会尝试保护其注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
一句话:某时刻某一个微服务不可用了,Eureka不会立即清理,依旧会对该服务的信息进行保存。
什么是自我保护模式
默认情况下,如果Eureka server在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90s)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为变得非常危险,因为微服务本身其实时健康的,此时不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题---当eurekaserver节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
如果在Eureka server的首页看到如下这段提示,则说明eureka进入了保护模式
在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例。
它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。一句话:好死不如赖活着,使用自我保护模式,可以让eureka集群更加的健壮、稳定。
如何关闭自我保护模式
在配置文件中添加配置enable-self-preservation
就可以关闭自我保护模式,默认时开启,默认值为true
eureka:
instance:
hostname: localhost1 #eureka服务端的实例明
client:
# false表示不向注册中心注册自己
register-with-eureka: false
# false表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
# 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
service-url:
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
defaultZone: http://localhost2:7002/eureka/
server:
enable-self-preservation: false
客户端的话可以设置心跳时间和等待心跳时间上限
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:7001/eureka,http://localhost2:7002/eureka
instance:
instance-id: payment8001
prefer-ip-address: true
#Eureka客户端向服务端发生心跳的时间间隔,默认是30s
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,默认是90秒,超时将剔除服务
lease-expiration-duration-in-seconds: 2