服务治理
1、Spring Cloud 封装 Netflix 公司开发的 Eureka 模块来实现服务治理
2、传统 RPC 框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理
3、作用:管理服务与服务之间依赖关系,可以实现服务发现、注册、调用、负载均衡、容错等
服务注册与发现
1、Eureka 采用 CS 设计架构
(1)Eureka Server 作为服务注册功能的服务器,它是服务注册中心
(2)系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server,并维持心跳连接,系统维护人员可以通过 Eureka Server 监控系统中各个微服务是否正常运行
2、在服务注册与发现中,有一个注册中心
(1)当服务器启动时,会把当前自身服务器的信息,比如:服务地址通讯地址等,以别名方式注册到注册中心上
(2)另一方(消费者 | 服务提供者),以该别名的方式,到注册中心上获取到实际的服务通讯地址,然后再实现本地 RPC 调用
(3)RPC 框架核心设计思想在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)
(4)在任何 RPC 框架中,都会有一个注册中心,以存放服务地址相关信息(接口地址)
Eureka 两个组件
1、Eureka Server
(1)提供服务注册服务
(2)各个微服务节点通过配置启动后,会在 Eureka Server 中进行注册,这样 Eureka Server 中的服务注册表中,将会存储所有可用服务节点的信息,服务节点的信息可以在界面中查看
2、Eureka Client
(1)通过注册中心进行访问
(2)Java 客户端,简化 Eureka Server 交互,客户端同时具备一个内置、使用轮询(round-robin)负载算法的负载均衡器
(3)在应用启动后,将会向 Eureka Server 发送心跳(默认周期为 30 秒)
(4)如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认 90 秒)
单机 Euraka 构建(例)
1、Eureka Server 服务注册中心
(1)Maven 工程的核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(2)yaml 配置文件
server:
port: 7001
eureka:
instance:
# Eureka Server 实例名称
hostname: localhost
client:
# false:表示不向注册中心注册自己
register-with-eureka: false
# false:表示自身为注册中心,作用是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与 Eureka Server 交互地址,查询服务、注册服务都需要依赖该地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
(3)Spring Boot 启动类添加注解
@EnableEurekaServer
2、Eureka Client 服务提供者
(1)Maven 工程的核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)yaml 配置文件
server:
port: 8001
spring:
application:
name: 服务提供者的默认应用程序名称
eureka:
client:
# 表示是否将自身注册到 Eureka Server,默认为 true
register-with-eureka: true
# 是否从 Eureka Server 抓取已有的注册信息,默认为 true
# 单节点情况下,该设置不影响,集群必须设置为 true,才能配合 Ribbon 使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
(3)Spring Boot 启动类添加注解
@EnableEurekaClient
3、Eureka Client 服务消费者
(1)Maven 工程的核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)yaml 配置文件
server:
port: 80
spring:
application:
name: 服务消费者的默认应用程序名称
eureka:
client:
# 表示是否将自身注册到 Eureka Server,默认为 true
register-with-eureka: true
# 是否从 Eureka Server 抓取已有的注册信息,默认为 true
# 单节点情况下,该设置不影响,集群必须设置为 true,才能配合 Ribbon 使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
(3)Spring Boot 启动类添加注解
@EnableEurekaClient
defaultZone 必须包含路径 /eureka
1、在 Eureka Server 实现中,存在一个 Web 请求过滤器,其 url 模式就是:/eureka/*,所以所有相关注册请求都在此进行处理
2、注意:这不是过滤应用的上下文路径,而是过滤剩下的请求路径,所以即使将 server.context-path 设置为 /eureka,各个节点之间还是无法连通
Eureka Client 不需要在 Spring Boot 启动类上标注 @EnableEurekaClient 也可以向 Eureka Server 注册
1、EurekaClientAutoConfiguration 为 EurekaClient 自动配置类
(1)注册 Eureka Client 相关的两个配置项:一个是 eureka.client.enabled,另一个是 spring.cloud.service-registry.auto-registration.enabled,两个配置默认都是 true
@Configuration
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@Import(DiscoveryClientOptionalArgsConfiguration.class)
@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)
//只有当 application.yaml(或环境变量,或系统变量)中,eureka.client.enabled 属性值为 true 才会初始化这个类(缺省值为 true)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })
@AutoConfigureAfter(name = {"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",
"org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",
"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration"})
public class EurekaClientAutoConfiguration {
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
//通过 @Bean,装配一个 EurekaAutoServiceRegistration 对象,注册 Eureka Client
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
}
2、EurekaAutoServiceRegistration 类
//实现 Spring 的 SmartLifecycle 接口
//SmartLifecycle 接口帮助一个类在作为 Spring 的 Bean 时,由 Spring 自动进行一些和生命周期有关的工作
//当 Spring 容器加载完所有 Bean 并且初始化之后,会继续回调实现 SmartLifeCycle 接口的类中对应方法,比如:start()
//比如:在初始化或停止时进行一些操作,注册(register)就是在 SmartLifecycle 接口的 start() 方法实现中完成
public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered, SmartApplicationListener {
//EurekaAutoServiceRegistration 类在 EurekaClientAutoConfiguration 类中被配置成 Spring 的 Bean
//所以此处 start() 会被 Spring 自动调用,不需要进行任何操作
@Override
public void start() {
// only set the port if the nonSecurePort or securePort is 0 and this.port != 0
if (this.port.get() != 0) {
if (this.registration.getNonSecurePort() == 0) {
this.registration.setNonSecurePort(this.port.get());
}
if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
this.registration.setSecurePort(this.port.get());
}
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!this.running.get() && this.registration.getNonSecurePort() > 0) {
this.serviceRegistry.register(this.registration);
this.context.publishEvent(new InstanceRegisteredEvent<>(this,
this.registration.getInstanceConfig()));
this.running.set(true);
}
}
}
3、总结
(1)引入 spring-cloud-starter-netflix-eureka-client 依赖后,并且 eureka.client.enabled、spring.cloud.service-registry.auto-registration.enabled 不手动置为 false
(2)Spring 会自动执行 EurekaAutoServiceRegistration 类中的 start(),注册动作在该方法中完成
(3)所以,Eureka Client 工程,并不需要在 Spring Boot 启动类上,显式地标注 @EnableEurekaClient
构建 Eureka 集群(例)
1、Eureka Server 服务注册中心集群
(1)相互注册,即一个 Eureka Server 包含集群中所有其他 Eureka Server
(2)只需要更改 yaml 配置文件
server:
port: 7001
eureka:
instance:
# Eureka Server 实例名称
hostname: eureka7001.com
client:
# false:表示不向注册中心注册自身
register-with-eureka: false
# false:注册中心维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 需要包括集群中所有其他 Eureka Server,使用 , 分隔多个 Eureka Server
defaultZone: http://eureka7002.com:7002/eureka/
server:
port: 7002
eureka:
instance:
# Eureka Server 实例名称
hostname: eureka7002.com
client:
# false:表示不向注册中心注册自身
register-with-eureka: false
# false:注册中心维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 需要包括集群中所有其他 Eureka Server,使用 , 分隔多个 Eureka Server
defaultZone: http://eureka7001.com:7001/eureka/
2、Eureka Client 服务提供者集群
(1)服务提供者组成集群,提供相同服务,需要统一微服务名称,使用端口号区分
(2)不向外暴露
server:
port: 8001
spring:
application:
name: 服务提供者的微服务名称
eureka:
client:
# 表示是否将自身注册到 Eureka Server,默认为 true
register-with-eureka: true
# 是否从 Eureka Server 抓取已有的注册信息,默认为 true
# 单节点情况下,该设置不影响,集群必须设置为 true,才能配合 Ribbon 使用负载均衡
fetchRegistry: true
service-url:
# Eureka Client 需要包含所有 Eureka Server,使用 , 分割
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
server:
port: 8002
spring:
application:
name: 服务提供者的微服务名称
eureka:
client:
# 表示是否将自身注册到 Eureka Server,默认为 true
register-with-eureka: true
# 是否从 Eureka Server 抓取已有的注册信息,默认为 true
# 单节点情况下,该设置不影响,集群必须设置为 true,才能配合 Ribbon 使用负载均衡
fetchRegistry: true
service-url:
# Eureka Client 需要包含所有 Eureka Server,使用 , 分割
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
(3)服务提供者 Controller,返回结果添加端口号属性,用以区分具体的提供者
@Value("${server.port}")
private String serverPort;
3、Eureka Client 服务消费者
(1)更改 yaml 配置文件
server:
port: 80
spring:
application:
name: 服务消费者的默认应用程序名称
eureka:
client:
# 表示是否将自身注册到 Eureka Server,默认为 true
register-with-eureka: true
# 是否从 Eureka Server 抓取已有的注册信息,默认为 true
# 单节点情况下,该设置不影响,集群必须设置为 true,才能配合 Ribbon 使用负载均衡
fetchRegistry: true
service-url:
# Eureka Client 需要包含所有 Eureka Server,使用 , 分割
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
(2)服务消费者 Controller,RestTemplate 的 url 参数中,使用服务提供者的微服务名称,代替 ip:port
(3)服务消费者配置类,为 RestTemplate 添加 @LoadBalanced
//Spring 配置类
@Configuration
public class ApplicationContextConfig {
@Bean
//开启负载均衡,默认轮询算法
@LoadBalanced
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
完善微服务信息
1、监控依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、Eureka Server 的 Status 默认显示:hostname:微服务名称:port
(1)修改服务提供者 yaml 配置文件,更换 Status 显示
eurkea:
instance:
instance-id: 修改后的名称
3、 访问 Eureka Server 的 Status,默认显示:hostname:port/actuator/info
(1)修改服务提供者 yaml 配置文件,使访问 ip 代替 hostname
eureka:
instance:
#使访问路径可以显示IP地址
prefer-ip-address: true
服务发现
1、Eureka Server 的 Spring Boot 启动类添加 @EnableDiscoveryClient,启用服务发现
2、Controller
(1)通过 DiscoveryClient 获取到在 Eureka 注册的微服务的信息
@Resource
private DiscoveryClient discoveryClient;
(2)示例
@GetMapping(value = "/discovery")
public Object discovery() {
//获取所有微服务,包括消费者、提供者等的 spring.application.name
List<String> services = discoveryClient.getServices();
for (String element : services) {
System.out.println(element);
}
//提供微服务名称,获取该微服务的所有实例
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance element : instances) {
System.out.println(
element.getServiceId()
+ "\t" + element.getHost()
+ "\t" + element.getPort()
+ "\t" + element.getUri());
}
return this.discoveryClient;
}
自我保护模式
1、默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认 90 秒)
2、在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例
(1)目的:防止 Eureka Client 可以正常运行,但网络分区故障发生(延时、卡顿、拥挤)时,与 Eureka Server 之间无法正常通信;让 Eureka 集群更加健壮、稳定
(2)架构哲学:宁可同时保留所有微服务(健康的微服务、不健康的微服务),也不盲目注销任何健康的微服务
(3)应用场景:一组客户端和 Eureka Server 之间存在网络分区场景下的保护
(4)Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务
(5)Eureka Server 首页以下提示,则说明进入保护模式
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
(6)属于 CAP 中的 AP 分支
3、设置
(1)Eureka Server
eureka:
server:
# Eureka Server 自我保护机制,默认为 true
enable-self-preservation: false
# Eureka Server 清理无效节点的频率,默认 60000 毫秒(60 秒)
eviction-interval-timer-in-ms: 2000
(2)Eureka Client
eureka:
client:
instance:
# 服务续约间隔,Eureka Client 向 Eureka Server 发送心跳的时间间隔,单位为秒,默认 30 秒
lease-renewal-interval-in-seconds: 1
# 服务失效时间,Eureka Server 在收到最后一次心跳后所等待时间的上限,单位为秒,默认 90 秒,超时将剔除该服务
lease-expiration-duration-in-seconds: 2
今天的文章Euraka_eurohkd分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/45217.html