使用阿里云ACM简化你的Spring Cloud微服务环境配置管理

摘要: 本文咱们就如何使用阿里云ACM这样的配置管理产品在Spring Cloud中替代Spring Cloud Config帮助简化环境配置管理作一个简单的示例,帮助你理解基于ACM来简化微服务环境配置管理的方案,并会简单比较一下ACM与Spring Cloud Config方案的优劣。java

  1. 配置的环境属性

毫无疑问,在系统持续交付的过程当中,系统最终运行环境的多样性及复杂性毫无疑问增长了咱们在配置管理工做上的负担,有时候,甚至不夸张的说,配置就是因环境而生。mysql

这在Eugen Paraschiv的博文 Configuration Must Be Environment Specific里有简单的阐述,在个人博文《现代应用架构中的配置管理面临的挑战》 的容器化、调度与配置管理小节也有深刻的阐述。web

若是要问,是什么致使了咱们应用的构建物(artifact)在各个环境不能保持同样,有时候Docker没法轻易达成“Build Once, Run Anywhere!"的承诺,其答案每每就是环境配置的差别,为帮助你理解,举一些简单的例子:spring

在开发环境中将logLevel设置为DEBUG,在预发环境logLevel设置为INFO,生产环境里logLevel设置为WARNING
在开发环境中使用4核8G的机器跑数据库,而在生产中用32核96G机器跑数据库
在平常环境执行线程池的最大线程数应该设置为15,而生产环境上这个值应该大一点,默认设为150
在线上环境中,中心机房,应用数据源须要链接A库,而深圳机房,应用应该就近链接使用B库
只有在小淘宝环境,双向同步开关才应该关闭
此次的改动有点大,新的特性仅在线上的杭州单元把该特性开放出来,其它的单元环境先不要开放出来
本文咱们就如何使用阿里云ACM这样的配置管理产品在Spring Cloud中替代Spring Cloud Config帮助简化环境配置管理作一个简单的示例,帮助你理解基于ACM来简化微服务环境配置管理的方案,并会简单比较一下ACM与Spring Cloud Config方案的优劣。sql

  1. 场景故事

为了帮助理解需求和场景,在平常工程实践中,咱们通常会用用户故事(User Story)的方式,预设一个简单的场景,以此来作阐释和交流,熟悉微服务历史的兄弟必定熟悉下面这张早期的布道图:数据库

图片描述

本文中咱们就以Movie Service为例,假设咱们须要从关系数据库MySQL(RDS)检索全部电影信息列表,可是在测试环境、预发和生产环境咱们须要使用不一样的数据库,由于只有生产库才须要顶配的机器。这样咱们的应用须要在不一样的环境配置不一样的数据源配置、链接池配置、数据库安全配置等等,咱们会介绍如何基于阿里云ACM的Namespace映射不一样环境的能力,为movie service在不一样运行环境设置不一样的数据源配置。浏览器

以下图所示:安全

图片描述

  1. 建立微服务 Movie Service

新建Spring Boot Starter 微服务应用 movie service
movie service的业务逻辑很简单,从MySQL(RDS)里列出全部的movie列表,以下简图所示:服务器

图片描述

这里咱们建立了一个标准的jpa应用(相似Spring官网的样例工程 Accessing data with MySQL,咱们的工程结构以下图所示:架构

图片描述

引入JPA、MySQL、链接池HikariCP以及WEB依赖

<dependency>

<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>2.7.6</version>
</dependency>

建立 MySQL(RDS) 数据库及用户

mysql> create database db_example; -- Create the new database
mysql> create user 'springuser'@'localhost' identified by 'ThePassword'; -- Creates the user
mysql> grant all on db_example.* to 'springuser'@'localhost'; -- Gives all the privileges to the new user on the newly created database

具体可参考 Accessing data with MySQL 中的 'Create the database'小节

建立 WEB Controller

package com.alibaba.demo.microsvc.controller;
import org.springframework.beans.factory.annotation.Autowired;
org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.demo.microsvc.dao.MovieRepository;
import com.alibaba.demo.microsvc.model.Movie;

@RestController
public class MovieController {

@Autowired
MovieRepository movieRepository;

@RequestMapping("/list-movies")
public @ResponseBody Iterable<Movie> listMovies() {
    return movieRepository.findAll();
   }

}
</pre>
  1. 在ACM中使用Namespace建立隔离的环境配置

注: 在阿里云上使用ACM的前提是开通了该项服务,具体开通流程能够参考文档ACM 快速入门,开通服务并登录以后,便可进入 ACM 控制台 建立命名空间及配置

在ACM中建立3个环境 (dev,stage,prod)

图片描述

为 dev,stage,prod 不一样环境分别建立配置

图片描述

注意 咱们完成了什么?

在上一步中,咱们为相同配置项针对不一样环境的设置了不一样的值,例如 'spring.datasource.url'这个配置项,咱们经过设置不一样的url来为各环境链接不一样的数据库,而且仅在生产环境开启SSL (useSSL=true)

dev:
        spring.datasource.url=jdbc:mysql://localhost:3306/db_example?useSSL=false
>        
    prod:
        spring.datasource.url=jdbc:mysql://30.5.101.169:3306/db_example?useSSL=true
>

同时,咱们也为生产环境(prod)设置了更大的数据库链接池和更小的链接超时时间

dev:
        spring.datasource.hikari.connection-timeout=60000
        spring.datasource.hikari.maximum-pool-size=10
>        
    prod:
        spring.datasource.hikari.connection-timeout=15000
        spring.datasource.hikari.maximum-pool-size=200
>

而为了方便开发调试,咱们仅在开发环境打开了SQL Trace

dev:

spring.jpa.show-sql=true
  1. Movie Service与配置中心ACM集成

如今咱们将集成Movie Service与ACM以便从ACM中获取对应环境的配置. 关于如何在Spring Cloud中使用ACM,具体能够参考ACM官方文档 开发指南 > SDK 参考 > Spring Cloud ACM

为movie service引入ACM依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-acm</artifactId>
    <version>1.0.1</version>
 </dependency>

在application.properties配置ACM链接信息、namespace、accessKey、secretKey等信息

spring.application.name=movie-service
spring.application.group=com.alibaba.cloud.acm
  
alibaba.acm.endpoint=acm.aliyun.com
alibaba.acm.namespace=<your_namespace_id>
alibaba.acm.accessKey=<your_ak>        
alibaba.acm.secretKey=<your_sk>

注意: 你能够在ACM的'命名空间详情'或者'配置的示例代码'里找到你的namespace_id,accessKey,secretKey等信息,以下图所示:

图片描述

  1. 在浏览器里访问Movie Service

图片描述

  1. 查看ACM配置推送刷新信息

若是在movie service引入了spring-boot-starter-actuator依赖而且在application.properties设置了management.security.enabled=false,能够经过端点 http://&lt;>/acm 看到应用的配置消费及刷新状况,以下图:

图片描述

也能够在ACM控制台上查看配置的推送轨迹、配置版本等信息,具体使用方法可参考ACM官方文档,在此再也不赘述。

在个人博文《现代应用架构中的配置管理面临的挑战》 里有长篇幅的侧面论述。
若是测试、生产由于配置打出来的包不同,如何保证你的测试是有效的?

关注微服务的开发者必定拜读过下面这本微服务圣经

微服务设计

在上书中的第6.7及6.8小节对于环境和配置有很是精彩的阐述,这里将原文引用在此

6.8 服务配置

服务须要一些配置。理想状况下,这些配置的工做量应该很小,并且仅仅局限于环境间配置的差别。若是你的配置修改了不少服务的基本行为,或者不一样环境之间的配置差别很大,那么你可能就只能在一套环境中发现某个特定的问题,这是极其痛苦的事情。
因此,若是存在不一样环境之间的配置差别,应该如何在部署流程中对其进行处理呢?一种方法是对每一个环境建立不一样的构建物,并把配置内建在该构建物中。刚开始看这种方法好像挺有道理。配置已经被内建了,只须要简单的部署,它应该就可以正常工做了,对吧?其实这是有问题的。还记得持续交付的概念吗?咱们想要建立一个构建物做为候选发布版本,并使其沿着流水线向前移动,最终确认它可以被发布到生产环境。想象一下,我构建了一个Customer-Service-Test构建物和Customer-Service-Prod构建物。若是Customer-Service-Test构建物经过了测试,但我真正要部署的构建物倒是Customer-Service-Prod,又要如何验证这个软件最终会真正运行在生产环境中呢?
还有一些其余的挑战。首先,建立这些构建物比较耗时。其次,你须要在构建的时候知道存在哪些环境。你要如何处理敏感的配置数据?我可不想把生产环境的数据库密码提交到源代码中,可是若是在建立这些构建物时须要的话,一般这也是难以免的。
一个更好的方法是只建立一个构建物,并将其配置单独管理。从形式上来讲,这针对的多是每一个环境一个属性文件,或者是传入到安装过程当中的一些参数。还有一个在应对大量微服务时比较流行的方法是,使用专用系统来提供配置,第11章会详细讨论这个话题。
配置漂移
当应用部署以后运行过程当中,尤为是部署在多台服务器上以后,若是使用开发人员或者运维人员手工维护配置文件的方式,日积月累以后,会产生咱们所谓的"配置飘移"问题,即因为应用以及依赖的组件的版本变动带来的配置差别,以及不一样的团队或者人的屡次不一样时间点作的不一样的修改会致使数据中心中每台机器上的相同的应用的配置在各台机器上或多或少都有细微的差异,而这每每是bug和重大故障隐藏之所。

  1. 总结

在本文中,咱们以一个测试和生产链接不一样的数据库,配置不一样的数据源(包括链接池)参数为例,介绍了如何将阿里云配置中心ACM与Spring Cloud一块儿使用,帮助你在微服务架构中简化你的环境配置管理。

原文连接:http://click.aliyun.com/m/100...