001-eureka学习记录
eureka学习记录
一、单eureka示例
1.1 eureka 服务(注册中心)
1.1.1 新建spring boot程序
省略
1.1.2 引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
注意cloud 版本与 boot版本的对应 我这里使用了
<?xml version="1.0" encoding="UTF-8"?>
<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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zhoust</groupId>
<artifactId>eureka-single</artifactId>
<version>1.0</version>
<name>eureka-single</name>
<url>www.baidu.com</url>
<description>eureka-single 单机eureka</description>
<packaging>pom</packaging>
<modules>
<!--父工程下的模块-->
<module>eureka-single-server</module>
</modules>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>2.5.1</spring-boot.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-boot-admin.version>2.4.1</spring-boot-admin.version>
<lombok.version>1.18.20</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot 依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot 监控客户端 -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
1.1.3 yml中添加配置
server:
port: 7000
spring:
application:
name: eureka
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false #
fetch-registry: false
serviceUrl:
defaultZone : "http://localhost:7001/eureka/"
1.1.4 启动类
启动类加上@EnableEurekaServer
注解,注意是 @EnableEurekaServer
不是@EnableEurekaClient
@SpringBootApplication
@EnableEurekaServer
public class EurekaSingleServerApp {
public static void main(String[] args) {
SpringApplication.run(EurekaSingleServerApp.class, args);
}
}
1.1.5 启动
启动后访问 http://localhost:7000/ 就可以访问eureka注册中心了。
1.2 服务提供者
1.2.1 新建spring boot程序
基本就是一个springboot程序,对外提供controller
1.2.2 依赖
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>eureka-single</artifactId>
<groupId>com.zhoust</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-single-producer</artifactId>
<dependencies>
<!--对外提供controller,使用web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
1.2.3 配置
server:
port: 8001
spring:
application:
name: eureka-sigle-producer
eureka:
client:
register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
serviceUrl:
defaultZone: http://localhost:7000/eureka # 注册到eureka服务上。
1.2.4 对外提供接口
编写一个controller测试类
@RestController
@Slf4j
public class DealController {
@GetMapping("/dealMsgToProducer")
public String dealMsgToProducer(){
log.info("我对外提供服务");
return "我是 服务dealMsgToProducer,对外提供能力";
}
}
1.2.5 启动
启动类加上@EnableEurekaClient
注解,注意是 @EnableEurekaServer
不是@EnableEurekaServer
@SpringBootApplication
@EnableEurekaClient
public class EurekaSingleProducerApp {
public static void main(String[] args) {
SpringApplication.run(EurekaSingleProducerApp.class, args);
}
}
1.3 服务消费者
1.3.1 新建项目
普通的spring boot项目
1.3.2 依赖
跟服务提供者一样
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
1.3.3 配置
跟服务提供者基本一样
server:
port: 8000
spring:
application:
name: eureka-single-consumer
eureka:
client:
register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
serviceUrl:
defaultZone: http://localhost:7000/eureka
1.3.4 启动类
启动类加上@EnableEurekaServer
注解,注意是 @EnableEurekaServer
不是@EnableEurekaClient
1.3.5 远程调用
使用 LoadBalancerClient 拉去注册信息,RestTemplate 发送信息,后面使用到feign 后不再使用这个方式。
package com.zhoust.eureka.single.consumer.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@Slf4j
public class SendController {
// 拉去注册中心信息
private final LoadBalancerClient client;
// 如果依赖注入的话先在config中创建
private final RestTemplate restTemplate;
public SendController(LoadBalancerClient client, RestTemplate restTemplate) {
this.client = client;
this.restTemplate = restTemplate;
}
// 服务提供者注册到注册中心的名
private String INSTANCE = "eureka-single-producer";
@GetMapping("/sendMsgToProducer")
public String sendMsgToProducer(){
// 拿到eureka注册的实例
ServiceInstance choose = client.choose(INSTANCE);
if(null == choose){
return "instance is null";
}
// 获取地址
String host = choose.getHost();
// 获取端口
int port = choose.getPort();
String url = "http://"+host+":"+port+"/dealMsgToProducer";
log.info("开始向{}发送msg信息",url);
String forObject = restTemplate.getForObject(url, String.class);
return forObject;
}
}
RestTemplateConfig类
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
1.4 eureka添加鉴权认证
eureka 注册中心默认是不需要权限认证的,什么服务都可以注册上去,当我们有需要限制这些服务时,可以增加权限校验。
1.4.1 借助 security 来实现
通过security鉴权让拥有账号密码的服务注册,同时打开注册中心也需要账号密码。
1.4.1.1 依赖
在 eureka-single-server项目中引入 security 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
1.4.1.2 配置
主要增加了security.user.name/password
server:
port: 7000
spring:
application:
name: eureka-single-server
security: # 进入eureka注册中心需要账号密码
base:
enabled: true
user:
name: zhoust
password: zhoust
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false # 是否将自己注册到eureka上
fetch-registry: false # 是否从eureka服务上拉取拉取 服务信息
1.4.1.3 启动
启动后访问localhost:7000会自动跳转到登陆页面如下,登录后进入
注意:
如果是新版的 eureka 需要配置过滤请求 "/eureka/**"
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/eureka/**");
super.configure(http);
}
}
1.4.2 服务注册
服务提供者跟消费者都一样,这一以服务提供者为例
直接注册就会报错。Request execution failure with status code 401; retrying on another server if available
1.4.2.1 依赖
无需多余的依赖
1.4.2.2 配置
配置中增加账号密码 defaultZone: http://user:password@localhost:7000/eureka # 注册到eureka服务上。
server:
port: 8001
spring:
application:
name: eureka-single-producer
eureka:
client:
register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
serviceUrl:
defaultZone: http://zhoust:zhoust@localhost:7000/eureka # 注册到eureka服务上。
1.4.2.3 启动
注册成功
注意:
如果报错DiscoveryClient_EUREKA-SINGLE-PRODUCER/localhost:eureka-single-producer:8001 - registration failed Cannot execute request on any known server
多半是把/eureka/**
地址也拦截了,请在注册中心中配置 过滤请求 "/eureka/**"
, 或者账号密码错误
1.5 eureka 在多网卡环境下
1.5.1 忽略指定网卡
cloud:
inetutils:
preferred-networks:
- 127.0
- 0.1
eureka:
instance:
prefer-ip-address: true
1.5.2 只使用本地站点地址
cloud:
inetutils:
use-only-site-local-interfaces: true
1.5.3 手动指定ip
eureka:
instance:
prefer-ip-address: true
ip-address: 127.0.0.1
1.6 健康检查
eureka server 页面有一个 status 该项表明eureka 是否可用,当标记为 up 时为可用,除此外还有 down,out_of_service,unknown 等,这个状态只是表明了eureka server 与 client 之间的心跳是否正常。
但当client 服务因网络抖动,连不上数据库时,client 其实是不正常的,所以我们要想法把这个状态同步到eureka 中,我们可以结合SpringBootActuator提供的/health 端点去同步状态。
在client(生产者消费者)端配置
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置eureka.client.healthcheck.enabled=true
eureka:
client:
register-with-eureka: true # 是否将自己注册到eureka上 不配置默认是true
fetch-registry: true # 是否从eureka服务上拉取拉取 服务信息 不配置默认是true
serviceUrl:
defaultZone: http://zhoust:zhoust@localhost:7000/eureka # 注册到eureka服务上。
healthcheck:
enabled: true
测试:
在producer中编写链接数据库的dome, 启动正常注册。当我把数据库关闭后
日志检测
2021-10-14 23:59:56.373 WARN 12820 --- [nfoReplicator-0] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@107b5f0 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2021-10-15 00:00:01.384 WARN 12820 --- [nfoReplicator-0] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@1792c4f (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2021-10-15 00:00:06.392 WARN 12820 --- [nfoReplicator-0] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@f59344 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2021-10-15 00:00:11.405 WARN 12820 --- [nfoReplicator-0] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@b213cc (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2021-10-15 00:00:16.409 WARN 12820 --- [nfoReplicator-0] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@b3b002 (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2021-10-15 00:00:21.424 WARN 12820 --- [nfoReplicator-0] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl@c09fba (No operations allowed after connection closed.). Possibly consider using a shorter maxLifetime value.
2021-10-15 00:00:21.430 WARN 12820 --- [nfoReplicator-0] o.s.b.a.jdbc.DataSourceHealthIndicator : DataSource health check failed
org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30059ms.
然后服务被标记为down
但实际上我们服务还在存活,服务可用,数据库不可用。文末有代码地址
二、eureka 集群
生产场景下为了保证系统的高可用,通常会使用eureka集群来搭建高可用的注册中心。
2.1 创建eureka-server工程
新建三个eureka-server工程,命名eureka-colony-server-one
,eureka-colony-server-two
,eureka-colony-server-three
三个工程的配置同单机eureka,配置上多了一句defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/
配置互为主备
2.2 配置
2.2.1 eureka-colony-server-one
server:
port: 7001
spring:
application:
name: eureka-colony-server-one
eureka:
instance:
hostname: localhost-one
client:
register-with-eureka: false # 是否将自己注册到eureka上
fetch-registry: false # 是否从eureka服务上拉取拉取 服务信息
serviceUrl:
defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/
2.2.2 eureka-colony-server-two
defaultZone: http://localhost:7001/eureka/,http://localhost:7003/eureka/
2.2.3 eureka-colony-server-three
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/
2.3 启动
由于我们使用的都是 localhost 域名,所以分片数据只有localhoust,为了区分对此进行修改。
2.3.1 修改系统host文件
127.0.0.1 eureka-colony-server-one eureka-colony-server-two eureka-colony-server-three
2.3.2 修改yml配置
三个配置文件都修改为对应的域名
defaultZone: http://eureka-colony-server-one:7001/eureka/,http://eureka-colony-server-three:7003/eureka/
2.3.3 查看
以 eureka-colony-server-one 这个程序为例,看到另外两个分片
2.4 服务注册
2.4.1 注册配置
配置基本跟单体一样defaultZone
节点将所有eureka都配置上
defaultZone: http://eureka-colony-server-one:7001/eureka/,http://eureka-colony-server-two:7002/eureka/,http://eureka-colony-server-three:7003/eureka/
三、eureka常见概念
3.1 服务同步(集群环境)
在集群环境中,每个注册中心节点都会把自己的服务同步到两外的节点中,保证每个节点数据的完整性
3.2 服务续约
每个注册到注册中心的服务(服务提供者,消费者)都会定时给注册中心发送心跳,告诉注册中心自己还活着。
3.3 服务剔除
当注册中心定时接收不到服务的心跳时,就会考虑将该服务剔除服务列表,不在提供服务。
3.4 自我保护
eureka 在启动一段时间后会报这个警告
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.
这个警告实际上就是触发了Eureka Server的自我保护机制。Eureka Server在运行期间会去统计心跳失败比例在15分钟之内是否低于85%,如果低于85%,Eureka Server会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。我们在单机测试的时候很容易满足心跳失败比例在15分钟之内低于85%,这个时候就会触发Eureka的保护机制,一旦开启了保护机制,则服务注册中心维护的服务实例就不是那么准确了,此时我们可以使用eureka.server.enable-self-preservation=false来关闭保护机制,这样可以确保注册中心中不可用的实例被及时的剔除
————————————————
版权声明:本文为CSDN博主「_江南一点雨」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012702547/article/details/77877914