[关闭]
@runzhliu 2018-06-10T06:05:26.000000Z 字数 3986 阅读 1611

SpringBoot + Swagger2 + Zookeeper 快速开发配置管理中心

springboot swagger2 zookeeper


参考资料
https://segmentfault.com/a/1190000004356362a
https://holynull.gitbooks.io/zookeeper/content/pei_zhi_fu_wu_configuration_service.html
http://curator.apache.org/getting-started.htmla
http://www.uedsc.com/346763.html

1 技术栈

  1. Spring Boot 可以说是当今最流行的微服务开发框架。
  2. Swagger2 是当前最流行的 API 接口管理工具之一。
  3. Zookeeper 是一个为分布式应用提供一致性服务的软件,在当今许多开源框架中均有应用。

分布式应用的配置管理很麻烦,使用 ZK 可以解决,但是如果只能用 ZK 的客户端来做配置信息的 CRUD,那也不会轻松,因此最好能有一个界面来进行操作。利用上述这三个框架,基本上就可以快速开发配置管理中心了。

为什么需要配置管理中心?这个可能跟组内业务相关。比较典型的是搜索和推荐系统中集成的 ab 测试组件。如何调整实验比例,如何配置实验组,都会对业务和系统产生很大的影响。拥有配置管理中心之后,可以很方便的将配置写入 ZK,然后让系统对 ZK 内的配置信息进行读取。集中式配置管理的思路是,将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。实现配置的集中式管理和动态更新。可以简单的理解为配置数据与程序分离。

整个配置管理中心稍微比较难的地方在于根据业务特点来设计 ZK 数据的存取和配置信息的版本控制。

2 具体实现

主要依赖如下:

  1. <dependency>
  2. <groupId>org.apache.curator</groupId>
  3. <artifactId>curator-recipes</artifactId>
  4. <version>2.12.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-jetty</artifactId>
  9. <version>2.0.2.RELEASE</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-web</artifactId>
  14. <version>2.0.2.RELEASE</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>io.springfox</groupId>
  18. <artifactId>springfox-swagger2</artifactId>
  19. <version>2.8.0</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>io.springfox</groupId>
  23. <artifactId>springfox-swagger-ui</artifactId>
  24. <version>2.8.0</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-test</artifactId>
  29. <version>2.0.2.RELEASE</version>
  30. <scope>test</scope>
  31. </dependency>

需要说明一下,没有用原生的 zookeeper 来开发,而是 curator,它是抽象程度更高,更易用的 ZK 客户端,推荐其官方教程学习。

Spring boot 启动主要依赖于以下程序。Application 是默认的启动类,引入 Swagger2 则是引入其 UI 并且可以配置页面展示的默认信息。

  1. .
  2. ├── Application.java
  3. ├── JacksonConfig.java
  4. └── Swagger2.java

image_1cepsc6d7gudsdnftn12fa15k09.png-41.5kB

配置信息以 KV 形式写入。本文中,一组配置元信息需要通过 project -> group -> key 来获取。

配置管理中心提供4种接口,增加配置、删除配置、回滚指定版本的配置以及获取配置的历史版本。主要提供了 ConfigManager 作为高层应用接口,分别代理了 Scala 的 Curator 封装中的相应的方法。具体的配置路径可以根据组内项目情况进行设计。

image_1cepsj1ee1621d4hphgnc4omkm.png-67.2kB

2.1 配置管理

关于配置管理,大概存在几种可能:增加配置信息、删除配置信息、展示配置信息,再加上能够回滚之前任意版本的配置信息。当然还有其他操作,使用者可以自行设计和实现。

关于以上管理方式,可以设置一个静态方法来实现:

  1. object ConfigManager {
  2. private[this] val configManager = new ConfigManager(JacksonUtil)
  3. def addNewConf[V](project: String, group: String, key: String, value: V): Unit = {
  4. configManager.addNewConf(project, group, key, value)
  5. }
  6. def show[V](project: String, group: String, key: String)(implicit m: Manifest[V]): Map[String, V] = {
  7. configManager.show(project, group, key)
  8. }
  9. def rollback(project: String, group: String, key: String, version: String): Try[_] = {
  10. configManager.rollback(project, group, key, version)
  11. }
  12. def remove(project: String, group: String, key: String): Unit = {
  13. configManager.remove(project, group, key)
  14. }
  15. }

由于操作方式比较多,这里仅就增加配置做点说明:

  1. /**
  2. * 添加项目配置.
  3. *
  4. * @param project 项目名
  5. * @param group 组别名
  6. * @param key 实验名
  7. * @param value 配置值
  8. * @param maxChildrenLength
  9. * @tparam V
  10. * @throws java.lang.Exception
  11. */
  12. @throws(classOf[Exception])
  13. def addNewConf[V](project: String,
  14. group: String,
  15. key: String,
  16. value: V,
  17. maxChildrenLength: Int = 10): Unit = {
  18. require(maxChildrenLength >= 1)
  19. val path = ZKPaths.makePath(ZK_ROOT_PATH,
  20. project,
  21. Array(group, key, System.currentTimeMillis().toString): _*)
  22. val valueBytes = serializationUtil.serialize(value)
  23. ZKUtil.addNode(path, valueBytes)
  24. val children = ZKUtil.listChildren(path).map(_.toLong)
  25. if (children.length > MAX_CHILDREN_LENGTH) {
  26. val minDateChild = children.sortBy(x => x).head
  27. logger.info(s"remove min child: $minDateChild.")
  28. ZKUtil.removeZNode(s"$path/$minDateChild")
  29. }
  30. }

当需要增加配置信息的时候,只要给出诸如之前设计的,包括 project, group, key 等信息,作为 ZK 的节点,然后添加需要的数据 value 就可以了。关于如何通过 Crurator 来控制添加节点数据的操作,可以进一步在项目中进行跳转来阅读。

然后添加配置信息,可以通过 Swagger2 的页面提供的 RESTful Api 来进行绑定。

  1. @RequestMapping(value = Array("/add"), method = Array(RequestMethod.POST))
  2. @ApiOperation(value = "添加配置", notes = "添加配置")
  3. def add(@RequestBody conf: CommonStringConfig): ResponseMsg = {
  4. try {
  5. ConfigManager.addNewConf(conf.project, conf.group, conf.key, conf.value)
  6. ResponseMsg()
  7. } catch {
  8. case NonFatal(e) =>
  9. logger.error("add error.", e)
  10. ResponseMsg(-1, e.toString)
  11. }
  12. }

测试该方法可以在页面中进行操作,点解 Try it out 就可以在页面中添加配置信息。

image_1cf1j1b8ra5ebk91hjs11431u749.png-91.3kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注