通过Acutator和SpringCloudConfig完成"灰度部署"——动态刷新网关路由配置
先声明下,我这个可能是冒牌的灰度部署,技术有限,纯粹个人笔记分享。
前段时间接到了头头给我的一个任务,让我研究下“灰度部署”,说是保证一个服务要升级的时候,不能停掉服务。操作步骤是,比如老版本的服务端口号是9002,新版本的服务是9003。在运行9002的时候,启动9003,修改网关路由配置9002→9003,确保流量走到9003后成功运行,停掉9002服务,这就算大功告成了。
接下来分享下我通过学习实践后可行的两种方案 1. 通过SpringCloudConfig配置分布式配置中心,连接GitHub、GitLab加上Acutator来实现刷新技术。 2. 轻量级——通过Acutator来刷新,抛弃SpringCloudConfig。仅仅本地修改就OK,不用去Git上修改。
方式一:通过SpringCloudConfig搭建分布式配置中心
概要:这种方式呢,就是通过一个服务(配置中心),连接上GitHub或者GitLab(因为公司是用lab管理代码的)的仓库,然后读取里面的配置文件(各个服务的各种配置文件都在这里放着),运维人员或者其他人吧,就可以在仓库在线修改配置文件。然后通过例如github、lab的WebHook;Actoator监控工具(手动刷新)的技术等完成刷新。这样就不用重启服务了。
1.创建一个项目,作为这个配置中心服务。 引入对应依赖。
1 2 <dependency> 3 <groupId>org.springframework.cloudgroupId> 4 <artifactId>spring-cloud-config-serverartifactId> 5 dependency> 6 7 8 <dependency> 9 <groupId>org.springframework.bootgroupId> 10 <artifactId>spring-boot-starter-actuatorartifactId> 11 dependency>
2. 然后创建application.yml配置文件。配置示例如下:
这个服务的端口号是3344,其次通过配置可以看出。连接git的uri是如下(这就是你的git仓库的地址),如果是私有的或者有权限的就在下面不上username和password,和uri并列就可以了。
server:
port: 3344
spring:
application:
name: microservicecloud-config
cloud:
config:
server:
git:
uri: https://github.com/*********r-repo.git
3.目前为止分布式配置中心的搭建基本就差不多了,但是别忘了去启动类加上启用的注解。(@EnabledConfigServer)
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.config.server.EnableConfigServer; @EnableConfigServer @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } }
4.截止到这里分布式配置中心已经搭建完成。
5.将网关服务的配置文件放置在GitHub或者GitLab上的仓库上(就是上面刚刚配置的git地址)。
6.这时候分布式配置中心的服务端配置完了,改配置客户端了,这里网关服务就相当于客户端。所以我就在网关服务中添加如下依赖:
acutator是用来刷新监控的,config是客户端,注意上面服务端的依赖是-server。
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-actuatorartifactId> dependency> <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-configartifactId> dependency>
7. 在网关(配置中心客户端)添加bootstrap.yml,这个配置文件将优先于application.yml,因为它是配置中心的文件,它需要连接服务端,以及获取仓库中的文件路径等详细信息去在仓库中茫茫多的文件读取到属于自己的配置文件。
下面是网关项目的bootstrap.yml配置文件,name是指你想读取的配置文件的名称(当然还有指定路径的配置,具体就不详细了,现在就当做是一级目录下的文件),label是指master节点,uri自然就是git的地址,如果出现权限等问题记得加上username,password。
spring:
cloud:
config:
name: zuulConfig
label: master
uri: https://github.com/*********r-repo.git
8. 到此SpringCloudConfig的配置就结束了,当修改git上的配置文件后,通过手动刷新(或者绑定webhook,这里就不提了)后,服务就更新成最新的配置了。手动刷新的方式是利用Actuator,在下面的方式最后一起描述。当然这里的关于Actuator的配置文件也应该写在application.yml或者bootstrap.yml中。
方式二:利用Actuator实现动态更新配置文件
1. 导入依赖
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-actuatorartifactId> dependency>
2. 配置文件
这里展示properties格式的,最简单的就是加入include = refresh,因为默认是没有refresh的,这里就用"*"都导入了,第二行的配置是指用什么路径,原路径/acutator/refresh,经过配置后/manager/refresh,如果本地端口失效等问题还可以加上server.port设置端口,用这个端口再试试....
management.endpoints.web.exposure.include=*
management.endpoints.web.base-path=/mannager
3. 配置Java代码(这里只是关心网关的配置的刷新,至于其他的,自行百度或者 加上@RefreshScope注解等)
第一段代码主要是配置的一个接口,调用这个接口可以查看当前网关的配置文件信息,和咱们这个动态刷新没什么大的关系。
主要是第二段代码,首先@Primary等那几个注解都是必须的,别问为什么,初学的我也是看别人博客这么说的....其次就是哪里要刷新哪里用@RefreshScope
@Configuration @Lazy(value = false) @EnableZuulProxy @EnableConfigurationProperties({ZuulProperties.class}) @RestController public class ZuulConfig { @Autowired ZuulProperties p; @GetMapping("/config") public Mapconfig() { return p.getRoutes(); } }
@EnableZuulProxy @SpringBootApplication @EnableConfigurationProperties({ZuulProperties.class}) public class ZuulServiceApplication { public static void main(String[] args) { SpringApplication.run(ZuulServiceApplication.class, args); } @Bean(name = "zuul.CONFIGURATION_PROPERTIES") @RefreshScope @ConfigurationProperties("zuul") @Primary public ZuulProperties zuulProperties() { ZuulProperties p = new ZuulProperties(); return p; } }
4.到这里简单的动态刷新监听配置就完成了。
操作步骤:
调用/config接口查看网关配置信息,在发布目录(targer)下的配置文件里修改配置信息,然后调用/manager/refersh接口,会返回给你修改了的配置信息的key,然后调用/config接口你会发现你修改的配置信息已经刷新了。当然如果觉得不可信,可以修改端口号啊等等,这也算是“灰度部署”了吧,可能有点粗糙,因为流量是直接全部导向新服务的。
做个笔记吧,以后可能还会用上,可能有很多说错的地方....hah