上篇文章注册中心选出了Consul 和 K8S,现在我需要把他们集成到SpringCloud里,体验一下他们的服务注册发现、动态配置与权限分配难易 问题,以便选出更适合我们的。
SpringCloudConsul
首先用Docker搭建出Consul集群,这一步忽略了,属于Docker的范畴,搭建完成之后,我们登录到Consul的控制台看下
我的项目结构是这种:
最外层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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.maple.consul</groupId>
<artifactId>maple-consul</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>maple-order</module>
<module>maple-member</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-cloud.version>2022.0.0</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<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>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
服务注册与发现
服务注册:
maple-order的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.maple.consul</groupId>
<artifactId>maple-consul</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.maple.order</groupId>
<artifactId>maple-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>maple-order</name>
<packaging>jar</packaging>
<description>maple-order</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
maple-member的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.maple.consul</groupId>
<artifactId>maple-consul</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.maple.member</groupId>
<artifactId>maple-member</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>maple-member</name>
<packaging>jar</packaging>
<description>maple-member</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
maple-order的 bootstrap.yml 为:
server:
port: 1001
management:
server:
port: 8001
consul:
host: localhost
port: 8500
spring:
application:
name: maple-order
cloud:
consul:
host: ${consul.host}
port: ${consul.port}
discovery:
service-name: ${spring.application.name}
heartbeat:
enabled: true
maple-member的 bootstrap.yml 为:
server:
port: 1101
management:
server:
port: 8001
consul:
host: localhost
port: 8500
spring:
application:
name: maple-member
cloud:
consul:
host: ${consul.host}
port: ${consul.port}
discovery:
service-name: ${spring.application.name}
heartbeat:
enabled: true
然后在每一个服务的Application里加上 @EnableDiscoveryClient 注解,分别启动应用之后,我们再打开Consul控制台看:
服务已经注册成功了,接下来测试服务发现
服务发现
我们让 order服务暴露接口,member通过openFeign调用,order和member服务都在pom里引入openFeign的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
并且在消费者 member 的Application里新增 @EnableFeignClients 注解
我们在order中暴露接口,并完成接口实现
在member中集成order的这个接口
member的controller暴露web接口测试
服务间调用成功,我们再启动多一个服务,保持两个consume和两个provide,然后再shutdown 某个provide观察接口的调用情况,为了方便观察我们打点日志。
我们在启动第二个order服务的时候,手动加个端口即可
member也是一样的操作,都启动完成之后我们看下Consul控制台
然后我再访问 http://localhost:1101/user/queryOrder 让用户1调订单服务,我访问了10次,发现每个order服务分别访问了5次,轮询来访问的,当然这应该是openFeign里面的负载均衡的策略,访问另外一个member服务也是一样的效果 http://localhost:1102/user/queryOrder
下面我们把order2服务给下线,再重复上面的测试,那所有的请求都会打到order1服务,也可以正常提供能力,这里提一点Consul是没有雪崩保护的。
动态配置
Consul也可用做配置中心,
我们通过create按钮来为order服务创建配置,为了模拟正常项目,我们创建开发和生产两个环境
config/maple-order::dev/data
config/maple-order::dev/data
:: 这个是profile 的隔离符合,默认是用英文逗号 , 。
最后的data是dataKey,因为配置文件内容支持多种格式,习惯原因我用的YAML格式,YAML格式就必须得加 dataKey,默认是 data,建完之后效果是这样的:
dev里:
进去data里:
prod里:
Consul控制台里配置的K-V存储完成了,我们把order的pom引入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 文件
关于config里的属性配置可以点进源码里看,为了默认值的我都没有再重复给了,这里我激活的profile为 prod,在order的程序里获取所配置的redis的ip。
测试发现获取到的配置是prod,ip为 666666
接下来我们在Consul控制台里把 666666 改为 999999,直接刷新浏览器看结果:
直接就更新了,同时在idea控制台里也能发现这段日志,是一个TaskScheduler来帮我们做动态刷新的
平时项目中我们还会直接使用@Value注解获取配置,我们改下代码重启下
同样方法修改为 666666 再刷新浏览器,发现值没变,还是 999999...不用担心,我们加个 @RefreshScope 就能解决