简介
为了更好地支撑日益增长的庞大业务量,我们常常需要把服务进行整合、拆分,使我们的服务不仅能通过集群部署抵挡流量的冲击,又能根据业务在其上进行灵活的扩展。随着分布式的普及、服务的快速增长与云计算技术的进步,微服务架构也因其特有的优势而备受关注。微服务架构的本质,是把整体的业务拆分成很多有特定明确功能的服务,通过很多分散的小服务之间的配合,去解决更大,更复杂的问题。对被拆分后的服务进行分类和管理,彼此之间使用统一的接口来进行交互。
而随着服务数量的剧增,这些服务所依赖的配置文件则需要实现统一管理并且能够实时更新;否则对于分布式环境中多达上千、上百的服务实例来说,单单修改配置这项目工作就会耗费程序员很多时间和精力,甚至更为糟糕的是可能会带来配置不一致、错误的灾难。
本系列讲述了在阿里云Kubernetes容器服务基础之上,如何快速搭建基于Spring Cloud的微服务架构中的基础设施:
- 第一篇:分布式服务注册与发现系统
- 第二篇:分布式配置管理系统
- 第三篇:API网关服务Zuul 系统
- 第四篇:分布式追踪系统
- 第五篇:分布式弹性服务与容错处理框架Hystrix及其监控仪表板
- 第六篇:熔断器聚合监控Hystrix Turbine
本文是系列中的第二篇,着重介绍分布式配置管理系统Spring Cloud Config。
Spring Cloud Config
为了应对分布式系统带来的这些复杂配置管理问题,Spring Cloud Config从以下几个角度提供必要的功能:
- 集中管理的需求:一个使用微服务架构的应用系统可能会包括成百上千个微服务,因此集中管理很有必要;
- 不同环境不同配置:例如数据源在不同的环境(开发,测试,生产)是不同的;
- 运行期间可以动态调整。例如根据各个微服务的负载状况,动态调整数据源连接池大小或者熔断阀值,并且调整时不停止微服务;
- 配置修改后可以自动更新;
针对分布式系统的外部配置,Spring Cloud Config主要提供了服务器端和客户端的支持,包括Config Server和Config Client两部分。由于Config Server和Config Client都实现了对Spring Environment和PropertySource抽象的映射,因此Spring Cloud Config很适合基于Spring Boot的应用程序。
- Config Server: 是一个看横向扩展的,集中式的配置服务器,它用于集中管理应用程序各个环境下配置,默认使用Git存储配置内容。
- Config Client: 是一个Config Server的客户端,用于操作存储在Config Server上的配置属性,所有微服务都指向Config Server,启动的时候会请求它获取所需要的配置属性,然后缓存这些属性以提高性能。
刷新配置机制
尽管使用/refresh 端点手动刷新配置,但是如果所有微服务节点的配置都需要手动去刷新的话,那必然是一个繁琐的工作,并且随着系统的不断扩张,会变得越来越难以维护。因此,实现配置的自动刷新是很有必要的,Spring Cloud Bus实现配置的自动刷新机制是一旦接收到RefreshEvent,就会启动ContextRefresher.refresh。
Spring Cloud Bus提供了批量刷新配置的机制,它使用轻量级的消息代理(例如RabbitMQ、Kafka等)连接分布式系统的节点,这样就可以通过Spring Cloud Bus广播配置的变化或者其他的管理指令。
下面讲述一下在阿里云Kubernetes容器服务基础之上,如何快速搭建一套分布式配置管理系统。
准备Kubernetes环境
阿里云容器服务Kubernetes 1.9.3目前已经上线,可以通过容器服务管理控制台非常方便地快速创建 Kubernetes 集群。具体过程可以参考创建Kubernetes集群。
体验通过服务目录简便部署RabbitMQ
搭建RabbitMQ
以RabbitMQ为例,点击左侧的服务目录
,在右侧选中rabbitmq-broker
。
点击参数
, 可以通过修改参数配置进行定制化,例如指定服务名称等。此处注意一点的是,为了后面Config Client端能远程访问RabbitMQ,服务网络类型指定为LoadBalancer。修改之后,在右侧点击创建
按钮。
几分钟之后,一个RabbitMQ代理就可以安装完毕。
注册RabbitMQ代理
安装完成之后,首先需要通过kubectl命令注册RabbitMQ代理。
建立一个名为rabbitmq-broker.yaml的文件,内容如下:
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ClusterServiceBroker
metadata:
name: rabbitmq-broker
spec:
url: http://aliacs-rabbitmq-broker-rabbitmq-broker.catalog.svc.cluster.local
执行kubectl create -f rabbitmq-broker.yaml
,注册RabbitMQ代理。
其中:
name
项可以根据需要进行修改;url
项为上述RabbitMQ代理的地址,格式为:{Kubernetes Service名称}.{Kubernetes 命名空间名称}.svc.cluster.local;{Kubernetes 命名空间名称}
默认为catalog,也就是说从上述页面点击创建RabbitMQ代理对应的命名空间名称为catalog;{Kubernetes Service名称}
可以通过kubectl get svc -n catalog
来获取;
执行如下命令可以查看broker状态、service plan服务计划等,如下:
创建RabbitMQ实例
服务目录中的RabbitMQ Broker提供了多种配置参数,来支持不同实例类型的创建。
建立一个名为rabbitmq-instance.yaml的文件,内容如下:
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceInstance
metadata:
name: rabbitmq-instance
namespace: catalog
spec:
clusterServiceClassExternalName: rabbitmq-service
clusterServicePlanExternalName: self-define
Parameters:
PersistenceEnabled: false
ServiceType: LoadBalancer
其中:
spec.clusterServicePlanExternalName
指定为self-define
,意味着可以进行定制化配置;spec.Parameters.PersistenceEnabled
指定为false
,意味着不进行序列化存储;spec.Parameters.ServiceType
指定为LoadBalancer
,意味着服务类型为LoadBalancer;
执行命令kubectl create -f rabbitmq-instance.yaml
,创建实例。
创建集群角色
首先,建立一个名为rabbitmq-clusterrole.yaml的文件,内容如下:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: resources-holder-rabbitmq
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["secrets","services","endpoints","nodes"]
verbs: ["get", "watch", "list","create", "update", "patch", "delete"]
执行命令kubectl create -f rabbitmq-clusterrole.yaml
,创建集群角色。
创建集群角色绑定
其次,建立一个名为rabbitmq-clusterrolebinding.yaml的文件,内容如下:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-resources-rabbitmq
subjects:
- kind: User
name: system:serviceaccount:catalog:default
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: resources-holder-rabbitmq
apiGroup: rbac.authorization.k8s.io
执行命令kubectl create -f rabbitmq-clusterrolebinding.yaml
,创建集群角色绑定。
创建服务绑定
其次,建立一个名为rabbitmq-binding.yaml的文件,内容如下:
apiVersion: servicecatalog.k8s.io/v1beta1
kind: ServiceBinding
metadata:
name: rabbitmq-binding
namespace: catalog
spec:
instanceRef:
name: rabbitmq-instance
secretName: rabbitmq-instance-credentials
执行命令kubectl create -f rabbitmq-binding.yaml
,创建服务绑定。
至此,RabbitMQ服务实例已经创建并且绑定信息可以从rabbitmq-instance-credentials
中获取到。
$ kubectl get secret -n catalog
NAME TYPE DATA AGE
rabbitmq-instance-credentials Opaque 6 2m
点击左侧的服务
,在右侧选中刚创建的RabbitMQ服务,可以查看到对应的Web地址,如下:
体验通过应用目录简便部署Config Server
创建Spring Config Server
点击左侧的应用目录
,在右侧选中ack-springcloud-configserver
,如下:
点击参数
, 可以通过修改参数配置进行定制化,重点注意spring.cloud.config.server.git部分的配置信息。
- 指定
global.rabbitmq.host
为访问上述创建的RabbitMQ服务的地址; - 指定
global.rabbitmq.username
为访问上述创建的RabbitMQ服务的访问用户; - 指定
global.rabbitmq.password
为访问上述创建的RabbitMQ服务的访问用户密码; - 指定
spring.cloud.config.server.git.uri
为存放配置属性文件的git仓库地址,如https://github.com/spring-cloud-samples/config-repo - 指定
spring.cloud.config.server.git.searchPaths
为配置仓库路径,以逗号隔开 - 指定
spring.cloud.config.label
为配置仓库的分支 - 指定
spring.cloud.config.server.git.username
为访问git仓库的用户名 - 指定
spring.cloud.config.server.git.password
为访问git仓库的用户密码
修改之后,在右侧选择对应的集群、命名空间,指定发布名称,然后点击部署。
几分钟之后,一个挂载了RabbitMQ的Spring Config Server实例就可以创建出来。
体验Spring Config Server
点击左侧的服务
,在右侧点击刚创建的Spring Config Server服务提供的访问地址,
如果访问http://{public-ip}:8888/foo/development,可以看到如下类似的内容,则证明Spring Config Server已正常启动。
自动同步刷新
Spring Cloud Bus提供了批量刷新配置的机制,它使用轻量级的消息代理(例如RabbitMQ、Kafka等)连接分布式系统的节点,这样就可以通过Spring Cloud Bus广播配置的变化或者其他的管理指令。
一旦某个Config Server上 /refresh
被触发,则该Config Server会向Spring Cloud Bus(本例中使用了RabbitMQ)发布RefreshRemoteApplicationEvent事件。
与此同时,其他的Config Server和Config Client会接收到该事件进行刷新,执行如下逻辑:
总结
我们可以利用阿里云Kubernetes容器服务,快速搭建一套分布式配置管理系统,应对分布式系统带来的这些复杂配置管理问题。欢迎大家使用阿里云上的容器服务,快速搭建一套基于Spring Cloud的分布式配置管理系统Config Server,比较简单地集成到自己项目的微服务开发中。