SpringCloud——consul
- 一、consul安装与运行
- 二、consul 实现服务注册与发现
- 1.引入
- 2.服务注册
- 3.服务发现
- 三、consul 分布式配置
- 1.基础配置
- 2.动态刷新
- 3.配置持久化
- 四、参考
Eureka
已经停止更新了,consul
是独立且和微服务功能解耦的注册中心,而不是单独作为一个独立微服务嵌入到系统中。
一、consul安装与运行
- 下载路径,下载完成后只有一个
consul.exe
文件,在对应路径下输入cmd
进入终端,输入命令consul --version
,如果能够正常的显示出版本信息,说明consul
下载的版本正确并且安装完成。 - 输入命令
consul agent -dev
,使用开发模式启动consul
。
- 通过地址
http://localhost:8500
访问到onsul
的首页。
二、consul 实现服务注册与发现
1.引入
- 通过下面的方式将一个微服务的IP地址和端口号
硬编码
另一个微服务中(例如订单微服务调用支付微服务),会存在这许多的问题:/** * 这里采用的是硬编码的地址,可扩展性低下 */ public static final String PAYMENT_SERVICE_URL = "http://localhost:8001";
- ① 如果订单微服务和支付微服务的IP地址或者端口号发生了变化,则支付微服务将变得不可用,需要同步修改订单微服务中调用支付微服务的IP地址或端口。
- ② 如果系统中提供了多个订单微服务和支付微服务,则无法实现微服务的
负载均衡
。 - ③ 如果系统需要支持高并发,需要部署更多的订单微服务和支付微服务,硬编码订单服务则后续的维护会变得异常复杂。
- 所以,在微服务开发的过程中,需要引入服务治理功能,实现微服务之间的动态注册与发现。
2.服务注册
-
第一步,修改
pom.xml
文件添加相关的依赖:<!--引入consul-discovery--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency>
- 控制台出现如下信息:
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
。这个信息对代码没有任何的影响,但是如果你有强迫症可以使用下面的方式解决掉:<!--引入consul-discovery--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
- 控制台出现如下信息:
-
第二步,在
application.yml
文件中添加相关的配置项:spring: application: # 设置服务名称 name: cloud-payment-service cloud: # 配置consul consul: # consul所在的IP地址 host: localhost # consul所在的端口号 port: 8500 discovery: # 服务以什么名字注册到 consul 中 service-name: ${spring.application.name} # 开启心跳模式,如果不开启服务注册后一直是红× heartbeat: enabled: true
-
第三步,启动微服务,并且访问
http://localhost:8500
查看服务是否注册成功:
3.服务发现
- 这个时候所有的微服务都注册到了
consul
注册中心中了,我们可以将上面的硬编码的代码修改为下面的代码了://注意这里的 cloud-payment-service 必须和上面你注册到 consul 中微服务名字保存一直。 public static final String PAYMENT_SERVICE_URL = "http://cloud-payment-service";
- 注意,
consul
默认就是支持负载均衡
的,所以如果你不做负载均衡的话会报错 - 在你的
RestTemplateConfig
配置类中添加,@LoadBalanced
注解:@Configuration public class RestTemplateConfig { /** * 使用 @LoadBalanced 注解赋予 RestTemplate 负载均衡的能力 * 默认使用的轮询负载均衡策略 */ @Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); } }
- 通过上面的两步,也就可以实现微服务之间的通信了。
三、consul 分布式配置
1.基础配置
- 微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。比如某些配置文件中的内容大部分都是相同的,只有个别的配置项不同。就拿数据库配置来说吧,如果每个微服务使用的技术栈都相同,则每个微服务中关于数据库的配置几乎都是相同的,有时候主机迁移了,我希望一次修改,处处生效。
consul
提供了通用全局配置信息的功能,直接注册进consul
服务器,从consul
获取。- 第一步,修改
pom.xml
文件添加相关的依赖:<!--引入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>
- 第二步,新增配置文件
bootstrap.yml
,将application.yml
文件中的通用的配置信息放到文件中:applicaiton.yml
是用户级的资源配置项bootstrap.yml
是系统级的,优先级更加高Spring Cloud
会创建一个"Bootstrap Context"
,作为Spring
应用的Application Context
的父上下文。初始化的时候,Bootstrap Context
负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的Environment
。Bootstrap
属性有高优先级,默认情况下,它们不会被本地配置覆盖。Bootstrap context
和Application Context
有着不同的约定,所以新增了一个bootstrap.yml
文件,保证Bootstrap Context
和Application Context
配置的分离。- 将
application.yml
文件改为bootstrap.yml
这是很关键的或者两者共存 - 因为
bootstrap.yml
是比application.yml
先加载的。bootstrap.yml
优先级高于application.yml
- bootstrap.yml
spring: application: # 设置服务名称 name: cloud-payment-service cloud: # 配置consul consul: # consul 所在的IP地址 host: localhost # consul 所在的端口号 port: 8500 discovery: # 服务以什么名字注册到 consul 中 service-name: ${spring.application.name} # 开启心跳模式,如果不开启服务注册后一直是红× heartbeat: enabled: true # 分布式配置 config: # default value is ",",we update '-' profile-separator: '-' # setting config document style; format: yaml
- 第三步,
consul
服务器key/value
配置填写:- 在
consul
上创建全局配置文件,需要按照固定的规则创建
- 这里的
cloud-payment-service
是你注册的服务名字,后面的-dev、-prod
是在表示在不同的环境中使用不同的配置,需要在application.yml
文件中配置spring.profiles.active: 环境名dev、prod
。
- 这里的
- 在
- 第四步,编写测试代码测试:
@GetMapping(value = "/pay/get/info") private String getInfoByConsul(@Value("${gdb.info}") String info) { return "consul info: " + info + ",port: " + port; }
2.动态刷新
- 在上面我们完成了
consul
的全局配置,但是如果我们现在修改配置信息,后续访问配置信息没有生效。
- 第一步:在配置类上添加注解
@RefreshScope
,启用consul
的动态刷新:@SpringBootApplication @MapperScan("com.gdb.cloud.mapper") @RefreshScope //启动 consul 全局配置的动态刷新功能 public class Main8001 { public static void main(String[] args) { SpringApplication.run(Main8001.class, args); } }
3.配置持久化
- 上面我们配置了
key/value
值,但是我们启动的方式是开发模式dev
,每次我们重新启动consul
的时候,数据就会消失,我们可以通过服务模式server
启动,这样我们就可以保存配置了。consul agent -server -ui -bootstrap-expect 1 -data-dir 自己本地保存的数据地址 -node=n1 -bind=127.0.0.1
四、参考
[1]. 使用 consul 实现服务注册与发现
[2]. Consul注册中心注册的服务总是红叉 (All service checks failing)
[3]. Consul心跳机制
[4]. consul入门案例及配置热更新的实现及Feign的使用