目录
SpringCloud 系列教程 | 第十七篇: 服务网关 Zuul 基于 Apollo 动态路由
Apollo 概述
Apollo 相比于 Spring Cloud Config 优势
工程实战
示例代码
SpringCloud 系列教程 | 第十七篇: 服务网关 Zuul 基于 Apollo 动态路由
- Springboot: 2.1.7.RELEASE
- SpringCloud: Greenwich.SR2
上一篇文章我们介绍了 Gateway 基于 Nacos 动态网关路由的解决方案《Spring Cloud Alibaba | Gateway 基于 Nacos 动态网关路由》 https://www.geekdigging.com/2019/09/02/661122041/ , 同为 Spring Cloud 服务网关组件的 Spring Cloud Zuul 在生产环境中使用更为广泛, 那么它有没有方便的动态路由解决方案呢? 答案当然是肯定的, Zuul 作为一个老牌的开源服务网关组件, 动态路由对它来讲是一个十分必要的功能, 毕竟我们不能随便重启服务网关, 服务网关是一个微服务系统的大门, 今天我们介绍的 Zuul 动态路由的解决方案来自于携程开源的配置中心 Apollo.
Apollo 概述
Apollo(阿波罗) 是携程框架部门研发的开源配置管理中心, 能够集中化管理应用不同环境, 不同集群的配置, 配置修改后能够实时推送到应用端, 并且具备规范的权限, 流程治理等特性.
Apollo 支持 4 个维度管理 Key-Value 格式的配置:
- application (应用)
- environment (环境)
- cluster (集群)
- namespace (命名空间)
Apollo 相比于 Spring Cloud Config 优势
前面的文章我们也介绍了 Spring Cloud Config《跟我学 SpringCloud | 第七篇: Spring Cloud Config 配置中心高可用和 refresh》 https://www.geekdigging.com/2019/08/31/1534935350/ , 但是它和我们今天要使用的相比, 又有什么劣势呢?
Spring Cloud Config 的精妙之处在于它的配置存储于 Git, 这就天然的把配置的修改, 权限, 版本等问题隔离在外. 通过这个设计使得 Spring Cloud Config 整体很简单, 不过也带来了一些不便之处.
功能点 | Apollo | Spring Cloud Config | 备注 |
---|---|---|---|
配置界面 | 一个界面管理不同环境、不同集群配置 | 无,需要通过 git 操作 | |
配置生效时间 | 实时 | 重启生效,或手动 refresh 生效 | Spring Cloud Config 需要通过 Git webhook,加上额外的消息队列才能支持实时生效 |
版本管理 | 界面上直接提供发布历史和回滚按钮 | 无,需要通过 git 操作 | |
灰度发布 | 支持 | 不支持 | |
授权、审核、审计 | 界面上直接支持,而且支持修改、发布权限分离 | 需要通过 git 仓库设置,且不支持修改、发布权限分离 | |
实例配置监控 | 可以方便的看到当前哪些客户端在使用哪些配置 | 不支持 | |
配置获取性能 | 快,通过数据库访问,还有缓存支持 | 较慢,需要从 git clone repository,然后从文件系统读取 | |
客户端支持 | 原生支持所有 Java 和. Net 应用,提供 API 支持其它语言应用,同时也支持 Spring annotation 获取配置 | 支持 Spring 应用,提供 annotation 获取配置 | Apollo 的适用范围更广一些 |
工程实战
这里需要准备一个 Apollo 配置中心, 具体如何构建 Apollo 配置中心我这里不多做介绍, 大家可以参考 Apollo 的官方文档: https://github.com/ctripcorp/apollo/wiki
工程依赖 pom.xml 如下:
代码清单: chapter16/pom.xml
- ***
- <dependency>
- <groupId>com.ctrip.framework.apollo</groupId>
- <artifactId>apollo-client</artifactId>
- <version>${apollo-client.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
- </dependency>
配置文件
App.properties 如下:
代码清单: chapter16/src/main/resources/META-INF/App.properties
- ***
- App.id=123456789
这里配置的 App.id 是在 Apollo 中创建项目时配置的.
application.YAML 如下:
代码清单: chapter16/src/main/resources/application.YAML
- ***
- apollo:
- Bootstrap:
- enabled: true
- namespaces: zuul-config-apollo
- Meta: http://localhost:8080
在 Apollo 上新建一个命名空间 zuul-config-apollo.
其余的配置都配置在 Apollo 中, 具体如图:
启动主类 Chapter16Application.java 如下:
代码清单: chapter16/src/main/java/com/springcloud/chapter16/Chapter16Application.java
- ***
- @SpringBootApplication
- @EnableEurekaClient
- @EnableZuulProxy
- @EnableApolloConfig
- public class Chapter16Application {
- public static void main(String[] args) {
- SpringApplication.run(Chapter16Application.class, args);
- }
- }
其中 @EnableZuulProxy 表示开启 Zuul 网关代理,@EnableApolloConfig 表示开启 Apollo 配置.
路由刷新
代码路径: chapter16/src/main/java/com/springcloud/chapter16/config/ZuulProxyRefresher.java
- ***
- @Component
- public class ZuulProxyRefresher implements ApplicationContextAware {
- private ApplicationContext applicationContext;
- @Autowired
- private RouteLocator routeLocator;
- @ApolloConfigChangeListener(value = "zuul-config-apollo")
- public void onChange(ConfigChangeEvent changeEvent) {
- boolean zuulProxyChanged = false;
- for (String changedKey : changeEvent.changedKeys()) {
- if (changedKey.startsWith("zuul.")) {
- zuulProxyChanged = true;
- break;
- }
- }
- if (zuulProxyChanged) {
- refreshZuulProxy(changeEvent);
- }
- }
- private void refreshZuulProxy(ConfigChangeEvent changeEvent) {
- this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
- this.applicationContext.publishEvent(new RoutesRefreshedEvent(routeLocator));
- }
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
- }
@ApolloConfigChangeListener(value = "zuul-config-apollo") 中 value 的默认参数是 application, 因为这里我们自定义了 namespace, 所以需要指定, 我们使用 @ApolloConfigChangeListener 监听 Apollo 的配置下发, 有配置更新时会调用 refreshZuulProxy() 刷新路由信息.
测试
我们启动 Client-Apollo 工程和 Zuul-Apollo 工程, 打开浏览器访问: http://localhost:9091/client/hello , 页面可以正常显示, 我们在 Apollo 中修改路由信息, 具体如图:
修改完后点击发布, 待发布成功后, 我们刷新浏览器, 之前的路由访问已经报错 404, 我们使用修改过后的路由 http://localhost:9091/client_new/hello , 页面可以正常显示 Hello, i am dev from apollo update., 测试成功, 我们通过 Apollo 实现了 Zuul 的路由信息动态刷新.
示例代码
GitHub - 示例代码
Gitee - 示例代码
来源: https://www.cnblogs.com/babycomeon/p/11489632.html