写在前面
该系列博客仅用于本人学习尚硅谷课程SpringCloud笔记,其中的错误在所难免,如有错误恳请指正。
官方源码地址:https://github.com/zzyybs/atguigu_spirngcloud2020
什么是SpringCloud
Spring Cloud是微服务一站式服务解决方案,微服务全家桶。它是微服务开发的主流技术栈。SpringCloud 和 SpringCloud Alibaba 目前是最主流的微服务框架组合。
Spring Cloud包含了许多功能强大的组件,例如服务注册与发现、负载均衡、断路器、配置管理、消息总线等,这些组件可以帮助开发者构建弹性、可靠、可扩展的分布式系统。
微服务是一种理念。程序员可以将应用程序拆分为多个微服务,每个微服务负责实现一个特定的功能,并通过Spring Cloud提供的组件进行协调和管理。这样,程序员可以更加灵活地组织和扩展应用程序,同时提高系统的可维护性和可靠性。
前期准备
父工程
首先创建一个父工程。maven版本使用3.5,不要使用idea自带的。
Java编译版本选择JDK8。
修改pom:找到pom文件,如果严格按照以上步骤,可以直接粘贴,否则需要自行修改。
<?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.atguigu.springcloud</groupId>
<artifactId>cloud2020</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 统一管理jar包版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0.RELEASE-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
<properties></properties>
:后序需要创建子工程,在父亲工程这统一管理jar包。<dependencyManagement></dependencyManagement>
:通过该标签管理子模块的版本号。要注意的是,该标签只是声明了依赖,但是不是实现引入。如果要引入,需要将放到该标签外面,刷新等待引入后再放回该标签里面。<dependencies></dependencies>
dependencyManagement只是声明一个依赖,而不实现引入,故需要子模块中也需要对依赖进行声明,倘若不声明子模块自己的依赖,是不会从父模块中继承的;只有子模块中也声明了依赖。并且没有写对应的版本号它才会从父类中继承;并且version和scope都是取自父类;此外要是子模块中自己定义了自己的版本号,是不会继承自父类的。
里面的部分依赖并不是当前需要的,如果发现有的依赖导致了报错,可以先将相关依赖注释。
创建微服务 cloud-provider-payment8001
该微服务用于客户端服务的提供者。
pom
<?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>cloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<!-- 引入自己定义的api通用包,可以使用Payment支付Entity 当前不需要,主要注释掉 -->
<groupId>com.atguigu.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<!--这个和web要写到一块-->
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
yml
启动类
可以直接通过spring初始化一步到位。
常规操作
数据库建表
create table `payment`(
`id` bigint(20) not null auto_increment comment 'ID',
`serial` varchar(200) default '',
PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
select * from payment;
数据可以随意添加两条。本人数据如下
entities
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor //无参构造器
public class Payment implements Serializable {
private long id;//数据库是bigint
private String serial;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//返回给前端的通用json数据串
@Data //set/get方法
@AllArgsConstructor //有参构造器
@NoArgsConstructor //无参构造器
public class CommonResult<T> {
private Integer code;
private String message;
private T data; //泛型,对应类型的json数据
//自定义两个参数的构造方法
public CommonResult(Integer code, String message){
this(code, message, null);
}
}
dao
@Mapper
public interface PaymentDao {
int create(Payment payment);
Payment getPaymentById(@Param("id") Long id);
}
resource下创建mapper文件夹,新建PaymentMapper.xml。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.springcloud.dao.PaymentDao">
<resultMap id="BaseResultMap" type="com.atguigu.springcloud.entities.Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
</resultMap>
<insert id="create" parameterType="com.atguigu.springcloud.entities.Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) values (#{serial})
</insert>
<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
select * from payment where id = #{id}
</select>
</mapper>
Controller && Service
Service层
public interface PaymentService {
int create(Payment payment);
Payment getPaymentById(@Param("id") Long id);
}
@Service
public class PaymentServiceImpl implements PaymentService {
@Autowired
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
Controller层
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
// 注意这里的 @RequestBody 是必须要写的,虽然 MVC可以自动封装参数成为对象,
// 但是当消费者项目调用,它传参是 payment 整个实例对象传过来的, 即Json数据,因此需要写这个注解
public CommonResult<Integer> create(@RequestBody Payment payment) {
int result = paymentService.create(payment);
log.info("****插入结果:" + result);
if (result > 0) {
return new CommonResult<>(200, "插入数据库成功", result);
}
return new CommonResult<>(444, "插入数据库失败", null);
}
@GetMapping(value = "/payment/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
Payment result = paymentService.getPaymentById(id);
log.info("****查询结果:" + result);
if (result != null) {
return new CommonResult<>(200, "查询成功", result);
}
return new CommonResult<>(444, "没有对应id的记录", null);
}
}
目录结构如下
启动项目
找到启动类,然后点击运行启动。启动过程中出现了异常暂时不要管。打开浏览器,访问http://localhost:8001/payment/31(注意这里的31是本人的id数据)访问已经添加的数据。如果需要插入数据,可以使用postman传入Json。
创建模块 cloud-api-commons
后面的80需要和前面的8001相同的内容。为了方便管理,将相同的类放在该模块并进行打包。
pom
<?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>cloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-api-commons</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- hutool 工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>
将8001中entities包下的类复制到该模块,删除8001下的entities包。
等待成功后,找到8001,7001中的该依赖然后加载。
创建微服务 cloud-consumer-order80
该微服务用于客户端服务的消费者。
pom
<?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>cloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-consumer-order80</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- <dependency><!– 引入自己定义的api通用包,可以使用Payment支付Entity –> -->
<!-- <groupId>com.atguigu.springcloud</groupId> -->
<!-- <artifactId>cloud-api-commons</artifactId> -->
<!-- <version>${project.version}</version> -->
<!-- </dependency> -->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
yml
server:
port: 80 # 默认 80 端口,只需要输入网址即可
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
# 将自己注册进去 true
register-with-eureka: true
#是否从Eureka server抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
spring:
application:
name: cloud-order-service
controller && config
config
@Configuration
public class ApplicationContextConfig {
// RestTemplate是Spring框架提供的一个用于发送HTTP请求的类。它简化了与RESTful服务的交互,可以方便地发送GET、POST、PUT、DELETE等请求,并且支持处理响应结果。
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
controller
@RestController
@Slf4j
public class OrderController {
//远程调用的 地址
public static final String PAYMENY_URL = "http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@PostMapping("customer/payment/create")
public CommonResult<Payment> create (Payment payment){
return restTemplate.postForObject(PAYMENY_URL + "/payment/create",//请求地址
payment,//请求参数
CommonResult.class);//返回类型
}
@GetMapping("customer/payment/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id")Long id){
return restTemplate.getForObject(PAYMENY_URL + "/payment/" + id,//请求地址
CommonResult.class);//返回类型
}
}
整个过程,通过浏览器调用order中的controller层,然后order80微服务发送http请求给payment8001微服务获取相关信息后返回。
到这里,所有的准备工作就完成了,接下来,进行eureka的正式使用。
Eureka
是什么
Eureka用于服务的注册与发现,用于管理和监控各个微服务。
比如,使用微服务后,不同的微服务在不同的机器上,为了简单方便管理,可以使用Eureka进行注册。
机制简介
Eureka包括两个组件:Eureka Server
和Eureka Client
。
- Eureka Server:服务器,里面有一个注册表,保存了不同的服务所在的机器和端口号。
- Eureka Client:客户端,负责将服务注册到Eureka Server中。
Eureka Client组件告诉Eureka Server自己在哪台机器上,监听着哪个端口;Eureka Client需要调用其他微服务的时候,通过Eureka Server寻找其他服务客户端,然后将这些相关信息从Eureka Server的注册表中缓存到自己的本地。
服务在Eureka上注册,然后定期发送心跳来更新它们的续约。如果客户端不能多次续订,那么它将在大约90秒内从服务器注册表中剔除。
服务提供者向注册中心注册服务,并每隔30秒发送一次心跳,如果Eureka长时间后还未收到服务提供者发来的心跳时,那么它就会认定该服务已经死亡就会注销这个服务。这里注销并不是立即注销,而是会在60秒以后对在这个之间段内“死亡”的服务集中注销,如果立即注销,势必会对Eureka造成极大的负担。这些时间参数都可以人为配置。
Eureka还有自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,所以不会再接收心跳,也不会删除服务。
客户端消费者会向注册中心拉取服务列表,因为一个服务器的承载量是有限的,所以同一个服务会部署在多个服务器上,每个服务器上的服务都会去注册中心注册服务,他们会有相同的服务名称但有不同的实例id,所以拉取的是服务列表。我们最终通过负载均衡来获取一个服务,这样可以均衡各个服务器上的服务。
使用Eureka
刚刚我们创建了一个微服务 cloud-provider-payment8001。当前的项目比较简单,管理起来不困难。但是如果项目比较多,而且分布在不同的机器上,管理就比较麻烦了,可以使用eureka进行服务的注册。现在将该微服务进行注册。
eureka有两个组件;server和client。将cloud-provider-payment8001作为client,那么,需要一个server,为此,需要再写一个微服务cloud-eureka-server7001,表示eureka的服务中心,端口号是7001。
按照上述方式,新建模块,选择maven工程。
创建微服务cloud-eureka-server7001
pom
<?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>cloud2020</artifactId>
<groupId>com.atguigu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- <dependency> -->
<!-- <groupId>com.atguigu.springcloud</groupId> -->
<!-- <artifactId>cloud-api-commons</artifactId> -->
<!-- <version>${project.version}</version> -->
<!-- </dependency> -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
</project>
yml
server:
port: 7001
eureka:
instance:
hostname: localhost # eureka 服务端的实例名称
client:
# false 代表不向服务注册中心注册自己,因为它本身就是服务中心
register-with-eureka: false
# false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与 Eureka Server 交互的地址,查询服务 和 注册服务都依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动类
// exclude :启动时不启用 DataSource的自动配置检查
// 依赖中存在数据源,如果启动会提示找不到数据源
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer // 表示它是服务注册中心
public class EurekaServerMain7001 {
public static void main(String[] args){
SpringApplication.run(EurekaServerMain7001.class, args);
}
}
启动类中需要格外注意的一个注解@EnableEurekaServer
,用于在Spring Boot应用程序中启用Eureka服务器。通过使用@EnableEurekaServer注解,我们可以将 cloud-eureka-server7001 标记为Eureka服务器,以便其他微服务可以进行注册和发现。
服务中心有了,使用@EnableEurekaClient
注解在 cloud-provider-payment8001 的启动类上。通过@EnableEurekaClient
可以将微服务标记为Eureka客户端,以便注册到Eureka服务器。同时要配置8001的yml。
server:
port: 8001
spring:
application:
name: cloud-payment-service # 项目名,也是注册的名字
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/cloud2020?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.dkf.springcloud.entities # 所有Entity 别名类所在包
eureka:
client:
# 注册进 Eureka 的服务中心
register-with-eureka: true
# 检索 服务中心 的其它服务
fetch-registry: true
service-url:
# 设置与 Eureka Server 交互的地址
defaultZone: http://localhost:7001/eureka/
启动该微服务,访问。
启动 cloud-provider-payment8001,cloud-consumer-order80
刷新7001网页,可以看到新注册了两个微服务。
现在看这两个微服务后面的状态信息。我们想要知道该微服务来自哪个ip,来自哪个机器,可以进行配置来显示。
微服务信息完善
order80和payment8001分别修改yml,添加
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
# 新增部分
instance:
instance-id: payment8001 # 提供者的id
prefer-ip-address: true # 显示ip地址
就可以显示提供者的id和ip地址。
微服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息。
先在8001的主启动类上添加@EnableDiscoveryClient
,然后添加代码。
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/customer/discovery")
public Object discovery(){
//获得服务清单列表
List<String> services = discoveryClient.getServices();
for(String service: services){
log.info("*****service: " + service);
}
// 根据具体服务进一步获得该微服务的信息
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-ORDER-SERVICE");
for(ServiceInstance serviceInstance:instances){
log.info(serviceInstance.getServiceId() + "\t" + serviceInstance.getHost()
+ "\t" + serviceInstance.getPort() + "\t" + serviceInstance.getUri());
}
return this.discoveryClient;
}
Eureka自我保护
看到该信息,说明eureka进入了自我保护。为了防止Eureka Client可以正常运行但是与Eureka Server网络不通情况下,Eureka Server不会立刻将Eureka Client服务剔除。
保护模式主要用于一组客户和Eureka Server之间存在网络分区场景下保护。一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中固定信息,也就是不会注销任何微服务。
默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90秒)。但是当网络分区故障发生时、卡顿、拥挤)时,微服务与Eureka Server之间无法正常通信,以上行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过"自我保护模式"来解决这个问题—当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
自我保护模式是一种应对网络异常的安全保护措施。设计理念是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让Eureka集群更加的健壮、稳定。
禁止使用自我保护
修改yml。
server:
eureka:
instance:
hostname: eureka7001.com # eureka 服务端的实例名称
client:
# false 代表不向服务注册中心注册自己,因为它本身就是服务中心
register-with-eureka: false
# false 代表自己就是服务注册中心,自己的作用就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
defaultZone: http://localhost:7001/eureka/
# server:
# # 关闭自我保护机制,保证不可用该服务被及时剔除
# enable-self-preservation: false
# # eureka server清理无效节点的时间间隔
# eviction-interval-timer-in-ms: 2000
client:
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
# 将自己注册进去 true
register-with-eureka: true
#是否从Eureka server抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
instance:
instance-id: payment8001 # 提供者的id
prefer-ip-address: true # 显示ip地址
# Eureka客户端像服务端发送心跳的时间间隔,单位s,默认30s
least-renewal-interval-in-seconds: 1
# Eureka服务端在收到最后一次心跳后等待时间上线,单位为s,默认90s,超时将剔除服务
least-expiration-duration-in-seconds: 2