Consul的简单入门
- 当Producer启动时,会向Consul发送一个post请求,告诉Consul自己的ip和Port;
- Consul接收到producer的注册后,每个10S(默认),会向producer发送一个健康检查的请求,检验Producer是否健康
- 当Consumer发送GET方式请求/api/address到Producer时,会先从Consul中拿到一个存储服务IP和Port的临时表,从表中拿到Producer的Ip和Port后再发送GET方式请求/api/address
- 该临时表每隔10s会更新,只包含有通过健康检查的Producer
1 实操 (安装Consul客户端)
实操的内容: 创建一个生产者(producer)和一个消费者(consumer). 二者通过Feign远程调用接口
从网上下载下来是一个后缀为exe
的文件,但是不要直接双击启动 ,而是在CMD窗口中找到当前的目录 使用下面的指令启动
1. 开发模式
数据保存在内存 重启之后会丢失
consul agent -dev
2. 服务模式
可以保留以前数据
consul agent -server -ui -bootstrap-expect 1 -data-dir D:\StudySoftWare\consul\data -node=n1 -bind=127.0.0.1
主页地址: http://localhost:8500/
2. 代码实现
项目结构:
这里使用的Maven的父子工程结构
1. 依赖导入
父工程:
// 这里使用2.3.1 注意这里版本不能太高, 不然好像会出现不兼容现象<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.1.RELEASE</version></parent>// <dependencies><!-- 服务注册和发现的依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId></dependency><!-- 配置中心的依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-config</artifactId></dependency><!-- SpringBootweb依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- lombok依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope></dependency></dependencies>
2. yml配置文件
bootstrap.yml
,注意这里一定要使用bootstrap.yml
作为配置文件,因为这个名称的优先级必application.yml的高, 而我们在Consul中的配置希望是在系统一启动就去读取,所以一定一定,因为我踩过坑
消费者配置文件
server:port: 8888spring:application:name: consumer-server # 服务名cloud:consul:host: 127.0.0.1 # 默认port: 8500 # 默认discovery:service-name: ${spring.application.name}heartbeat:enabled: true # 开启心跳检测config: # 先看标题5,配置中心的使用enabled: true prefix: config # 此时拼接出来的配置所在Consul地址就是 config/consumer/data.yamlname: consumerdata-key: dataformat: yaml
提供者的配置文件
server:port: 9999spring:application:name: producer-servercloud:consul:host: 127.0.0.1port: 8500discovery:service-name: ${spring.application.name}heartbeat:enabled: true
3. 定义消费者
定义controller, 这里为了测试就先简单的返回一个字符串.
package com.yfs1024.producer.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author : Cookie* date : 2023/6/13 19:23* explain :*/
@RestController
@RequestMapping
public class ProducerController {@GetMappingpublic String getDesc(){return "你好这里是提供者";}
}
4.定义消费者
这里因为我们用到了feign进行远程调用,所以这里需要在pom文件中添加feign的依赖
注意: 对于feign依赖的添加, 是谁想获取其他的服务就在谁的pom文件中添加feign依赖.
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
1. 启动类加注解开启feign
@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}
}
2. 定义feign客户端
注解的value属性就是想要调用服务的名称,
注意: 如果 参数列表中如果有参数, 注解不可以省略,注解不可以省略,注解不可以省略, feign不支持,
踩过坑
错: String getDesc(String name);
对: String getDesc(@RequestParam(“name”) String name);
@FeignClient("producer-server")
public interface ProducerClient {@GetMappingString getDesc();
}
3. 定义控制器
@RestController
@RequestMapping("/index")
//@RefreshScope
public class IndexController {@AutowiredProducerClient producerClient;@GetMappingpublic void getName(String name) {System.out.println("here is consumer value ===>>" + name + producerClient.getDesc());}
}
此时启动服务,可以看到已经注册到Consul中
此时请求方法,查看控制台
OK,实现了服务的注册以及调用.下面就差最后的使用Consul的配置中心
5.配置中心
刚才我们在Consumer的配置中其实已经配置了指定读取的配置文件的路径及名称,
config: enabled: true prefix: config # 此时拼接出来的配置所在Consul地址就是 config/consumer/data.yamlname: consumerdata-key: dataformat: yaml
下面就在consul中创建这样的一个文件
注意绿色的说明, 如果创建文件夹就使用
/
,后面yaml
格式的选择,以及标签的缩进,和 冒号后面的空格都不能省略
1.读取配置
使用@Value注解
@RestController
@RequestMapping("/index")
//@RefreshScope
public class IndexController {@Value("${school.name}")String schoolName;@Value("${school.addr}")String schoolAddr;@AutowiredProducerClient producerClient;@GetMappingpublic void getName(String name) {System.out.println("here is consumer value ===>>" + name + producerClient.getDesc() + schoolName + schoolAddr);}
}
控制台结果
这样其实已经成功了,但是如果我们想对配置进行热更新
应该怎么办? 其实可以测试如果使用当前方法是没有办法实现热更新的.但是可以通过下面的两种方法事项
配置热更新方式一
在类名上添加
@RefreshScope
,注解配合@Value
注解可以实现配置内容的热更新
@RestController
@RequestMapping("/index")
@RefreshScope
public class IndexController {@Value("${school.name}")String schoolName;@Value("${school.addr}")String schoolAddr;....
}
配置热更新方式二
@ConfigurationProperties("school")
注解天然支持热更新,所以可以定义一个属性配置类,来批量的读取随后在代码中注入,调用get方法
@Configuration
@ConfigurationProperties("school")
@Data
public class ConsumerConfig {String name;String addr;
}