1.Eureka 停止更新
2.初学者学习 Eureka 有困难
3.希望注册中心独立且和微服务功能解耦
4.阿里巴巴 Nacos 的进化
Consul 是一个开源的分布式服务发现和配置管理系统,使用 Go 语言进行开发,它提供了微服务中的服务治理、配置中心、控制总线等功能,这些功能可以单独使用,也可以共同使用以构建全方位的服务网络。
关于禁用规则:由于中美关系制裁,该公司(HashiCorp)的开源产品在中国大陆内禁止使用 Vault 企业版。
在官方网站下载Consul,下载成功后在 Consul 文件夹内启用 cmd 命令窗口,输入
consul agent -dev
之后,访问 localhost:8500 即可。
在子工程 pom 文件内添加依赖,步骤如下:
<!--Consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
在 application.yml 的 spring: 下添加
cloud:
consul:
host: localhost
port: 8500
在启动类上新增 @EnableDiscoveryClient 注解
@SpringBootApplication
@EnableDiscoveryClient
public class Main8001 {
public static void main(String[] args) {
SpringApplication.run(Main8001.class, args);
}
}
完成后启动服务,可以在Consul的localhost:8500下看到服务。服务可以更改名称
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
在第一节笔记中,跨服务通信组件TemplateComfig写入了一个ip硬编码,可以使用consul进行修改。
// 原硬编码ip 删除
public static final String pay_url = "http://localhost:8001";
// 新名称ip 新增,此处的名字为前文演示名称,若名称不同请自行修改
public static final String pay_url = "http://cloud-payment-service";
再次访问后进行调试会报出500错误,原因是因为Consul默认支持负载均衡,需要对通信组件进行负载均衡处理。
@Configuration
public class RestTemplateConfig {
@Bean
// 添加LoadBalanced负载均衡注解
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
再次重启并发送请求,即可正常使用。
CAP 原则:
一个分布式系统,不可能同时做到这三点,最多可以同时满足两个。
当我们将一个整体业务拆分为很多个子服务时,由于每个服务颗粒度很小,因此会出现大量的子服务。那么由于每个子服务都需要一些配置信息才能运行,所以我们需要一套动态的配置管理来实现对每个子服务的通用配置。我们不希望出现每一个子服务的通用配置都需要手动配置的情况。
针对这种情况,添加依赖:
<!--consul config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
Consul Config 的官网中指明了要实现分布式配置,就要新增一个 BootStrap.yml 配置。
Spring Cloud 会创建一个 BootStrap Context 来作为这个 Spring 应用的 Application Context 的父上下文。在初始化时,BootStrap Context 负责从外部源加载并解析配置,这两个上下文共享一个从外部获取的Environment。
BootStrap 属性具有高优先级,不会被本地配置覆盖。因为两个 Context 有不同的约定,所以需要新增 bootStrap.yml 文件来保证两个 Context 的配置分离。
提取后极简yml示例:
# 8001 application.yml
server:
port: 8001
spring:
# 多环境配置加载内容
profiles:
active: dev
datasource:
# 自行配置
# 8001 bootstrap.yml
spring:
application:
name: cloud-payment-service
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
config:
import: consul:8500
# consul 配置是否开启
enabled: true
# consul 所有工程的父文件夹
default-context: config
# consul 的分隔符
profile-separator: '-'
# consul 上的文件格式
format: YAML
yml 文件拆分完毕后,在 consul 8500 界面中,点击左侧的 KEY/VALUE 选项,新建默认文件夹 config。点击屏幕右侧的 create 按钮,在输入框中输入 config/ ,创建 config 文件夹,分别名为 cloud-payment-service、cloud-payment-service-dev。
此处我们选择使用 - 作为分隔符,是因为我们在 yml 文件中采用了 profile-separator 配置,将命名习惯改为符合大部分人逻辑的分隔方式。
之后,我们在各个 service 文件夹中新建 data 文件,文件的创建方法是命名后不加 /,创建文件过程略。注意,在文件创建时,文件的格式需要与 Spring Boot 项目中 Consul 声明的配置相同,此处文件格式选择 YAML,与项目配置文件中 format: YAML 对应。
cloud-payment-service 内容略;cloud-payment-service-dev,data文件内容示例:
name:
info: start dev!
点击保存后即可在 Spring Boot 项目中读取相应配置,我们可以通过修改 application.yml 中的 profiles-active 的内容变更访问的 data 配置,例如该演示读取的环境配置为 dev,那么我们读取的实际配置就为 cloud-payment-service-dev 中的配置。
配置的读取有很多种方式,此处我们选择对象-注解读取,其余方式可以自行探索。首先我们在 Java 项目中新建一个对象,对象内容为配置项的内容,并在对象上添加 @Component、@ConfigurationProperties 注解。注解的 prefix 属性为配置项的根键:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author salt fish
*/
@Component
@ConfigurationProperties(prefix = "name")
@Data
public class ConsulProperties {
private String info;
}
此时可以通过注入的形式验证data文件正确使用。
@Value("${server.port}")
private String port;
@Resource
private ConsulProperties consulProperties;
@RequestMapping("/test")
public String test() {
return "info:" + consulProperties.getInfo() + ",port:" + port;
}
若希望读取多层配置,例如
name:
info:
info: start dev!
则将配置类做如下修改即可。
@Component
@ConfigurationProperties(prefix = "name")
@Data
public class ConsulProperties {
private Info info;
@Data
public static class Info {
private String info;
}
}
在这个类中,我们将根键 name 的子键 info 定义成一个新的内部类,在这个内部类中将配置内容读取。这个过程可以无限循环,但是过多的层级会导致类维护困难,尽量使配置文件的层级可控来确保 Java 代码的正确性和可维护性。
我们现在已经实现了一个在 Consul 上的通用配置,那么如果我们在项目不重启的情况下修改这个配置,虽然 Consul 可以成功保存,但是项目读取到的配置却不会更新,这就需要 Consul 实现动态刷新来保证项目读取到的配置是我们最新的配置。
按照官方的解释,Consul 的配置刷新为 55 秒,他会在 55 秒后自动刷新。那么我们可以通过手动修改这个时间来完成我们想要的效果。
在 Bootstrap.yml 中,我们在 Consul 的 config 配置下添加一个配置:
# consul 配置的刷新时间
watch:
wait-time: 55
55 就是 Consul 的默认配置,我们可以调整这个时间,来完成我们指定时间刷新 Consul 配置的目的。
第二个方法是在引用时添加 @RefreshScope 注解,有需要使用这种方法的可以自行探索如何使用。
当 Consul 重启时,我们会发现我们所有的配置都已经消失,如果我们需要继续使用,那么还需要重新对 Consul 进行配置,这样对于我们的使用是非常不便的。所以,我们需要一种使配置持久化的工具或方式来保存我们的配置。
暂时使用一个简单的方式进行持久化存储,我们将 Consul 使用 windows 脚本的方式直接注册到 win 服务中并使它开机自启,脚本内容仅供参考:
@echo
@echo off
@sc stop Consul
@sc delete Consul
@sc create Consul binpath= "E:\学习资料\SpringCloud\consul_1.18.0_windows_amd64\consul.exe agent -server -ui -bind=127.0.0.1 -client=0.0.0.0 -bootstrap-expect 1 -data-dir E:\学习资料\SpringCloud\consul_1.18.0_windows_amd64\consulData"
@net stop Consul
@net start Consul
@sc config Consul start= AUTO
@echo Consul start is OK ...... success
@pause
这段脚本里制定了数据存储的地址为 consulData 文件夹,所以并不会丢失数据。
一般在正常情况下并不使用 windows 进行服务配置,所以不再深入。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。