新建父级工程
<?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.sco</groupId>
<artifactId>eurake</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-server</module>
</modules>
<properties>
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<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>
</project>
新建子工程eureka-server
导入依赖
<?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>eurake</artifactId>
<groupId>com.sco</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>eureka-server</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
新建启动类
package com.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaWebApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaWebApplication.class);
}
}
配置文件
server:
port: 7001
eureka:
server:
enable-self-preservation: false
client:
fetch-registry: false
register-with-eureka: false
serviceUrl:
defaultZone: http://127.0.0.1:7001/eureka/
即可
配置属性详解
client参数配置
eureka.client.register-with-eureka
:是否注册到eureka。默认为true,如果eureka是单节点,此配置设置为true且没有配置defaultZone
那么程序默认会尝试注册到http://localhost:8761/eureka/,那么就会报错,所以如果eureka是单节点,那么此字段必须设置为false- eureka.client.register-with-eureka:是否检索服务
- eureka.client.registry-fetch-interval-seconds:client本地缓存清单更新间隔,默认30秒;client每隔30秒,向Eureaka server请求可用服务清单。对于API网关类应用,可以适当降低时间间隔;
- eureka.client.serviceUrl.defaultZone:默认服务注册中心地址,多个用","隔开
Instance参数配置
- eureka.instance.prefer-ip-address:注册服务时是否使用IP注册,默认false;如果为false,则注册本机的机器名,如果设置了
eureka.instance.hostname
,则注册的是hostname - eureka.instance.ip-address:提供服务的ip地址,如果设置
eureka.instance.prefer-ip-address
为false时,那么注册到Eureka中的Ip地址就是本机的Ip地址。如果设置了true,则默认注册到Eureka中的Ip地址就是本机的Ip地址,若也设置了eureka.instance.ip-address
那么就将此ip地址注册到Eureka中。那么调用的时候,发送的请求目的地就是此Ip地址 - eureka.instance.instance-id:注册到Eureka server的实例ID
- eureka.instance.lease-renewal-interval-in-seconds:服务续约任务调用间隔时间,默认30秒,client每隔30秒向Eureka server发送心跳
- eureka.instance.lease-expiration-duration-in-seconds: 服务时效时间,默认90秒;当Eureka server 90秒内没有收到client的注册信息时,会将该节点标记失效,然后等待定时任务-清除失效服务执行清除。
server参数配置
- eureka.server.eviction-interval-timer-in-ms:Eureka server执行定时清理无效节点任务的时间间隔
- eureka.server.enable-self-preservation:是否开启自我保护,默认true
- eureka.server.renewal-percent-threshold:开启自我保护的系数,默认:0.85
Eureka高可用搭建
Eureka1配置文件
spring:
application:
name: eureka-sever
server:
port: 7001
eureka:
server:
# 是否开启自我保护
enable-self-preservation: false
# 执行失效服务清除定时任务时间
eviction-interval-timer-in-ms: 10000
client:
fetch-registry: false
# 注册到Eureka
register-with-eureka: true
serviceUrl:
#Eureka2地址
defaultZone: http://127.0.0.1:7002/eureka/
logging:
level:
root: DEBUG
Eureka2配置文件
spring:
application:
name: eureka-sever
server:
port: 7002
eureka:
server:
# 是否开启自我保护
enable-self-preservation: false
# 执行失效服务清除定时任务时间
eviction-interval-timer-in-ms: 10000
client:
fetch-registry: false
# 注册到Eureka
register-with-eureka: true
serviceUrl:
#Eureka1地址
defaultZone: http://127.0.0.1:7001/eureka/
logging:
level:
root: DEBUG
User微服务配置文件
spring:
application:
name: user
server:
port: 8080
eureka:
instance:
# 注册服务时是否使用IP注册,默认false;如果为false,则注册本机的机器名,如果设置了`eureka.instance.hostname`,则注册的是hostname
prefer-ip-address: false
instance-id: ${spring.cloud.client.ip-address}:${server.port}:${spring.cloud.client.hostname}
# 服务续约任务调用间隔时间,默认30秒,client每隔30秒向Eureka server发送心跳
lease-renewal-interval-in-seconds: 60
# 服务时效时间,默认90秒;当Eureka server 90秒内没有收到client的注册信息时,会将该节点标记失效,然后等待定时任务-清除失效服务执行清除。
lease-expiration-duration-in-seconds: 120
client:
fetch-registry: true
register-with-eureka: true
serviceUrl:
# eureka集群,多个英文逗号隔开
defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/
logging:
level:
root: DEBUG
Eureka自我保护
Eureka优雅停服
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
添加配置
management:
endpoints:
web:
exposure:
include: shutdown #开启shutdown端点访问
endpoint:
shutdown:
enabled: true #开始shutdown实现优雅停服,shutdown端点比较特殊,默认开启为false
通过post发送请求即可立即服务下线
curl -X POST http://localhost:8080//actuator/shutdown
三种服务消费方式
- DiscoveryClient:通过元数据获取服务信息
- LoadBalancerClient:Ribbon的负载均衡器
- @LoadBalanced:通过注解开启Ribbon的负载均衡器
DiscoveryClient
package com.eureka.ext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Component
public class UserFeign {
private static Logger log= LoggerFactory.getLogger(UserFeign.class);
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
public String getUser(String userId){
// 获取服务列表
List<String> services = discoveryClient.getServices();
if(CollectionUtils.isEmpty(services)){
return null;
}
// 根据服务名称获取服务
List<ServiceInstance> orders = discoveryClient.getInstances("user");
if(CollectionUtils.isEmpty(orders)){
return null;
}
ServiceInstance si = orders.get(0);
String url="http://"+si.getHost()+":"+si.getPort()+"/api/user/"+userId;
ResponseEntity<String> exchange = restTemplate.exchange(url,
HttpMethod.GET,
null,
String.class);
return exchange.getBody();
}
}
LoadBalancerClient
@Autowired
LoadBalancerClient loadBalancerClient;
public String getUser2(String userId){
// 直接获取服务实例,少了获取服务列表步骤
ServiceInstance user = loadBalancerClient.choose("user");
// 根据服务名称获取服务
List<ServiceInstance> orders = discoveryClient.getInstances("user");
if(CollectionUtils.isEmpty(orders)){
return null;
}
ServiceInstance si = orders.get(0);
String url="http://"+si.getHost()+":"+si.getPort()+"/api/user/"+userId;
ResponseEntity<String> exchange = restTemplate.exchange(url,
HttpMethod.GET,
null,
String.class);
return exchange.getBody();
}
@LoadBalanced
public String getUser3(String userId){
ResponseEntity<String> exchange = restTemplate.exchange(
"http://user/api/user/"+userId,
HttpMethod.GET,
null,
String.class);
return exchange.getBody();
}