目录
1 Spring Cloud Stream
![](https://img-blog.csdnimg.cn/3a9948341deb4f9ea73787cec41f0a39.png)
在实际的企业开发中,消息中间件是至关重要的组件之一。消息中间件主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。不同的中间件其实现方式,内部结构是不一样的。如常见的RabbitMQ
和
Kafka
,由于这两个消息中间件的架构上的不同,像
RabbitMQ
有
exchange
,
kafka
有
Topic
,
partitions
分区,这些中间件的差异性导致我们实际项目开发给我们造成了一定的困扰,我们如果用了两个消息队列的其中一种,后面的业务需求,我想往另外一种消息队列进行迁移,这时候无疑就是一个灾难性的,一大堆东西都要重新推倒重新做,因为它跟我们的系统耦合了,这时候 springcloud Stream
给我们提供了一种解耦合的方式。
1.1 概述
Spring Cloud Stream
由一个中间件中立的核组成。应用通过
Spring Cloud Stream
插入的
input(
相当于消费者consumer
,它是从队列中接收消息的
)
和
output(
相当于生产者
producer
,它是从队列中发送消息的。)
通道与外界交流。通道通过指定中间件的
Binder
实现与外部代理连接。业务开发者不再关注具体消息中间件,只需关注Binder
对应用程序提供的抽象概念来使用消息中间件实现业务即可。
![](https://img-blog.csdnimg.cn/f30c2b957bb04caf853d3067d09d6fd7.png)
说明:
最底层是消息服务,中间层是绑定层,绑定层和底层的消息服务进行绑定,顶层是消息生产者和消息消费者,顶层可以向绑定层生产消息和和获取消息消费
1.2 核心概念
绑定器
Binder
绑定器是
Spring Cloud Stream
中一个非常重要的概念。在没有绑定器这个概念的情况下,我们的Spring Boot
应用要直接与消息中间件进行信息交互的时候,由于各消息中间件构建的初衷不同,它们的实现细节上会有较大的差异性,这使得我们实现的消息交互逻辑就会非常笨重,因为对具体的中间件实现细节有太重的依赖,当中间件有较大的变动升级、或是更换中间件的时候,我们就需要付出非常大的代价来实施。
通过定义绑定器作为中间层,实现了应用程序与消息中间件
(Middleware)
细节之间的隔离。通过向应用程序暴露统一的Channel
通过,使得应用程序不需要再考虑各种不同的消息中间件的实现。当需要升级消息中间件,或者是更换其他消息中间件产品时,我们需要做的就是更换对应的Binder
绑定器而不需要修改任何应用逻辑 。甚至可以任意的改变中间件的类型而不需要修改一行代码。
Spring Cloud Stream
支持各种
binder
实现,下表包含
GitHub
项目的链接。
![](https://img-blog.csdnimg.cn/5ad8a6eb9b5f4f209ab9e54aa06580cd.png)
通过配置把应用和
spring cloud stream
的
binder
绑定在一起,之后我们只需要修改
binder
的配置来达到动态修改topic
、
exchange
、
type
等一系列信息而不需要修改一行代码。
发布
/
订阅模型
在
Spring Cloud Stream
中的消息通信方式遵循了发布
-
订阅模式,当一条消息被投递到消息中间件之后,它会通过共享的 Topic
主题进行广播,消息消费者在订阅的主题中收到它并触发自身的业务逻辑处理。这里所提到的 Topic
主题是
Spring Cloud Stream
中的一个抽象概念,用来代表发布共享消息给消费者的地方。在不同的消息中间件中, Topic
可能对应着不同的概念,比如:在
RabbitMQ
中的它对应了Exchange
、而在
Kakfa
中则对应了
Kafka
中的
Topic
。
![](https://img-blog.csdnimg.cn/be089b244f21416b8eb8f80f3347d68b.png)
1.3 入门案例
1.3.1 准备工作
案例中通过
rabbitMQ
作为消息中间件,完成
SpringCloud Stream
的案例。需要自行安装
1.3.2 消息生产者
(
1
)创建工程引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
(
2
)定义
bingding
发送消息时需要定义一个接口,不同的是接口方法的返回对象是
MessageChannel
,下面是
Spring Cloud Stream 内置的接口:
public interface Source {
String OUTPUT = "output";
@Output("output")
MessageChannel output();
}
这就接口声明了一个
binding
命名为
“output”
。这个
binding
声明了一个消息输出流,也就是消息的生产者。
(
3
)配置
application.yml
server:
port: 7001 #服务端口
spring:
application:
name: stream_producer #指定服务名
rabbitmq:
addresses: 127.0.0.1
username: guest
password: guest
cloud:
stream:
bindings:
output:
destination: itcast-default #指定消息发送的目的地,在rabbitmq中,发送到一个itcast-default的exchange中
binders: #配置绑定器
defaultRabbit:
type: rabbit
- contentType:用于指定消息的类型。具体可以参考 spring cloud stream docs
- destination:指定了消息发送的目的地,对应 RabbitMQ,会发送到 exchange 是 itcastdefault 的所有消息队列中。
(
4
)测试发送消息
@SpringBootApplication
@EnableBinding(Source.class)
public class Application implements CommandLineRunner {
@Autowired
@Qualifier("output")
MessageChannel output;
@Override
public void run(String... strings) throws Exception {
//发送MQ消息
output.send(MessageBuilder.withPayload("hello world").build());
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
1.3.3 消息消费者
(
1
)创建工程引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
(
2
)定义
bingding
同发送消息一致,在
Spring Cloud Stream
中接受消息,需要定义一个接口,如下是内置的一个接口。 注释 @Input
对应的方法,需要返回
SubscribableChannel
,并且参入一个参数值。 这就接口声明了一个 binding
命名为
“
input
”
。
public interface Sink {
String INPUT = "input";
@Input("input")
SubscribableChannel input();
}
(
3
)配置
application.yml
destination
:指定了消息获取的目的地,对应于
MQ
就是
exchange
,这里的
exchange
就是
itcastdefault
server:
port: 7002 #服务端口
spring:
application:
name: rabbitmq-consumer #指定服务名
rabbitmq:
addresses: 127.0.0.1
username: guest
password: guest
cloud:
stream:
bindings:
input: #内置的获取消息的通道 , 从itcast-default中获取消息
destination: itcast-default
binders:
defaultRabbit:
type: rabbit
(
4
)
测试
@SpringBootApplication
@EnableBinding(Sink.class)
public class Application {
// 监听 binding 为 Sink.INPUT 的消息
@StreamListener(Sink.INPUT)
public void input(Message<String> message) {
System.out.println("监听收到:" + message.getPayload());
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
定义一个
class
(这里直接在启动类),并且添加注解
@EnableBinding(Sink.class)
,其中Sink 就是上述的接口。同时定义一个方法(此处是
input
)标明注解为
启动后,默认是会创建一个临时队列,临时队列绑定的exchange
为
“itcast-default ”
,
routing key 为 “#”
。所有发送 exchange
为
“itcast-default ”
的
MQ
消息都会被投递到这个临时队列,并且触发上述的方法。
1.4 自定义消息通道
Spring Cloud Stream
内置了两种接口,分别定义了
binding
为
“input”
的输入流,和
“output”
的输出流,而在我们实际使用中,往往是需要定义各种输入输出流。使用方法也很简单。
interface OrderProcessor {
String INPUT_ORDER = "inputOrder";
String OUTPUT_ORDER = "outputOrder";
@Input(INPUT_ORDER)
SubscribableChannel inputOrder();
@Output(OUTPUT_ORDER)
MessageChannel outputOrder();
}
- 一个接口中,可以定义无数个输入输出流,可以根据实际业务情况划分。上述的接口,定义了一个订单输入,和订单输出两个 binding。
- 使用时,需要在 @EnableBinding 注解中,添加自定义的接口。
- 使用 @StreamListener 做监听的时候,需要指定 OrderProcessor.INPUT_ORDER
spring:
cloud:
stream:
defaultBinder: defaultRabbit
bindings:
inputOrder:
destination: mqTestOrder
outputOrder:
destination: mqTestOrder
如上配置,指定了
destination
为
mqTestOrder
的输入输出流。
1.5 消息分组
通常在生产环境,我们的每个服务都不会以单节点的方式运行在生产环境,当同一个服务启动多个实例的时候,这些实例都会绑定到同一个消息通道的目标主题(Topic
)上。默认情况下,当生产者发出一条消息到绑定通道上,这条消息会产生多个副本被每个消费者实例接收和处理,但是有些业务场景之下,我们希望生产者产生的消息只被其中一个实例消费,这个时候我们需要为这些消费者设置消费组来实现这样的功能。
i
实现的方式非常简单,我们只需要在服务消费者端设置spring.cloud.stream.bindings.input.group 属性即可,比如我们可以这样实现:在同一个group
中的多个消费者只有一个可以获取到消息并消费
cloud:
stream:
instanceCount: 2 #消费者总数
instanceIndex: 0 #当前消费者的索引
bindings:
input: #内置的获取消息的通道 , 从itcast-default中获取消息
destination: itcast-default
myinput:
destination: itcast-custom-output
group: group1
consumer:
partitioned: true #开启分区支持
binders:
defaultRabbit:
type: rabbit
1.6 消息分区
消息消费者配置
有一些场景需要满足
,
同一个特征的数据被同一个实例消费
,
比如同一个
id
的传感器监测数据必须被同一个实例统计计算分析,
否则可能无法获取全部的数据。又比如部分异步任务,首次请求启动
task
,二次请求取消task
,此场景就必须保证两次请求至同一实例
.
cloud:
stream:
instanceCount: 2 #消费者总数
instanceIndex: 0 #当前消费者的索引
bindings:
input: #内置的获取消息的通道 , 从itcast-default中获取消息
destination: itcast-default
myinput:
destination: itcast-custom-output
group: group1
consumer:
partitioned: true #开启分区支持
binders:
defaultRabbit:
type: rabbit
从上面的配置中,我们可以看到增加了这三个参数:
- 1. spring.cloud.stream.bindings.input.consumer.partitioned :通过该参数开启消费者分区功能;
- 2. spring.cloud.stream.instanceCount :该参数指定了当前消费者的总实例数量;
- 3. spring.cloud.stream.instanceIndex :该参数设置当前实例的索引号,从0开始,最大值为spring.cloud.stream.instanceCount 参数 - 1。我们试验的时候需要启动多个实例,可以通过运行参数来为不同实例设置不同的索引值。
消息生产者配置
cloud:
stream:
bindings:
output:
destination: itcast-default #指定消息发送的目的地,在rabbitmq中,发送到一个itcast-default的exchange中
myoutput:
destination: itcast-custom-output
producer:
partition-key-expression: payload #分区关键字 对象中的id,对象
partition-count: 2 #分区大小
binders: #配置绑定器
defaultRabbit:
type: rabbit
从上面的配置中,我们可以看到增加了这两个参数:
- 1. pring.cloud.stream.bindings.output.producer.partitionKeyExpression :通过该参数指定了分区键的表达式规则,我们可以根据实际的输出消息规则来配置SpEL来生成合适的分区键;
- 2. spring.cloud.stream.bindings.output.producer.partitionCount :该参数指定了消息分区的数量。
到这里消息分区配置就完成了,我们可以再次启动这两个应用,同时消费者启动多个,但需要注意的是要为消费者指定不同的实例索引号,这样当同一个消息被发给消费组时,我们可以发现只有一个消费实例在接收和处理这些相同的消息。
2 SpringCloud Config
2.1 什么是配置中心
2.1.1 配置中心概述
对于传统的单体应用而言,常使用配置文件来管理所有配置,比如
SpringBoot
的
application.yml
文件,但是在微服务架构中全部手动修改的话很麻烦而且不易维护。微服务的配置管理一般有以下需求:
- 集中配置管理,一个微服务架构中可能有成百上千个微服务,所以集中配置管理是很重要的。
- 不同环境不同配置,比如数据源配置在不同环境(开发,生产,测试)中是不同的。
- 运行期间可动态调整。例如,可根据各个微服务的负载情况,动态调整数据源连接池大小等
- 配置修改后可自动更新。如配置内容发生变化,微服务可以自动更新配置
综上所述对于微服务架构而言,一套统一的,通用的管理配置机制是不可缺少的总要组成部分。常见的做法就是通过配置服务器进行管理。
2.1.2 常见配置中心
- Spring Cloud Confifig为分布式系统中的外部配置提供服务器和客户端支持。
- Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
- Disconf 专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」包括 百度、滴滴出行、银联、网易、拉勾网、苏宁易购、顺丰科技 等知名互联网公司正在使用! 「disconf」在「2015 年度新增开源软件排名 TOP 100(OSC开源中国提供)」中排名第16强。
2.2 Spring Cloud Config简介
Spring Cloud Confifig
项目是一个解决分布式系统的配置管理方案。它包含了
Client
和
Server
两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,
client
通过接口获取数据、并依据此数据初始化自己的应用。
![](https://img-blog.csdnimg.cn/1e559111949648d194580248aa126f1c.png)
Spring Cloud Confifig
为分布式系统中的外部配置提供服务器和客户端支持。使用
Confifig Server
,您可以为所有环境中的应用程序管理其外部属性。它非常适合spring
应用,也可以使用在其他语言的应用上。随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认实现使用git
,因此它轻松支持标签版本的配置环境,以及可以访问用于管理内容的各种工具。
Spring Cloud Confifig
服务端特性:
- HTTP,为外部配置提供基于资源的API(键值对,或者等价的YAML内容)
- 属性值的加密和解密(对称加密和非对称加密)
- 通过使用@EnableConfifigServer在Spring boot应用中非常简单的嵌入。
Confifig客户端的特性(特指Spring应用)
- 绑定Confifig服务端,并使用远程的属性源初始化Spring环境。
- 属性值的加密和解密(对称加密和非对称加密)
2.3 Spring Cloud Confifig入门
2.3.1 准备工作
Confifig Server
是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git
存储配置文件内容,也可以使用
SVN
存储,或者是本地文件存储。这里使用
git
作为学习的环境
使用
GitHub
时,国内的用户经常遇到的问题是访问速度太慢,有时候还会出现无法连接的情况。如果我们希望体验Git
飞一般的速度,可以使用国内的
Git
托管服务
——
码云(
gitee.com
)。和
GitHub
相比,码云也提供免费的Git
仓库。此外,还集成了代码质量检测、项目演示等功能。对于团队协作开发,码云还提供了项目管理、代码托管、文档管理的服务。
(
1
)浏览器打开
gitee.com
,注册用户 ,注册后登陆码云管理控制台
(
2
)创建项目
confifig-repo
(
3
)上传配置文件,将
product_service
工程的
application.yml
改名为
product-dev.yml
后上传
文件命名规则:
- {application}-{profifile}.yml
- {application}-{profifile}.properties
- application为应用名称 profifile指的开发环境(用于区分开发环境,测试环境、生产环境等)
2.3.2
搭建服务端程序
(
1
)
引入依赖
创建工程
shop_config_server
并引入对应依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
(
2
)
配置启动类
@EnableConfigServer :
通过此注解开启注册中心服务端功能
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
(
3
)
配置
application.yml
server:
port: 10000 #服务端口
spring:
application:
name: config-server #指定服务名
cloud:
config:
server:
git:
uri: https://gitee.com/awen991129/config-repostrey.git
#注意这边一定要配置用户名,密码和跳过ssl验证,不然连接不上远端git
skip-ssl-validation: true
username: awen991129
password: awen991128
- 通过 spring.cloud.config.server.git.uri : 配置git服务地址
- 通过`spring.cloud.confifig.server.git.username: 配置git用户名
- 通过`spring.cloud.confifig.server.git.password: 配置git密码
(
4
)
测试
启动此微服务,可以在浏览器上,通过
server
端访问到
git
服务器上的文件
![](https://img-blog.csdnimg.cn/56c88eb4f02e4561bb281136e550a192.png)
2.3.3 修改客户端程序
(
1
)
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
(
2
)
删除
application.yml
springboot
的应用配置文件,需要通过
Confifig-server
获取,这里不再需要。
(
3
)
添加
bootstrap.yml
使用加载级别更高的
bootstrap.yml
文件进行配置。启动应用时会检查此配置文件,在此文件中指定配置中心的服务地址。会自动的拉取所有应用配置并启用
spring:
cloud:
config:
name: product #应用名称,需要对应git中配置文件名称的前半部分
profile: dev #开发环境
label: master #git中的分支
uri: http://localhost:10000 #config-server的请求地址
2.3.4 手动刷新
我们已经在客户端取到了配置中心的值,但当我们修改
GitHub
上面的值时,服务端(
Confifig Server
)能实时获取最新的值,但客户端(Confifig Client
)读的是缓存,无法实时获取最新值。
SpringCloud
已经为我们解决了这个问题,那就是客户端使用post
去触发
refresh
,获取最新数据,需要依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
对应的
controller
类加上
@RefreshScope
@RestController
@RequestMapping("/product")
@RefreshScope //开启动态刷新
public class ProductController {
@Autowired
private ProductService productService;
@Value("${name}")
private String name;
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
return productService.findById(id);
}
@RequestMapping(value = "/test")
public String test() {
return name;
}
}
配置文件中开发端点
#配置动态刷新
management:
endpoints:
web:
exposure:
include: /refresh
在postman中访问http://localhost:9002/actuator/bus-refresh,使用post提交,查看数据已经发生了变
化。
2.4 配置中心的高可用
在之前的代码中,客户端都是直接调用配置中心的
server
端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server
端要做集群,客户端只能通过原始的方式来路由,server端改变
IP
地址的时候,客户端也需要修改配置,不符合
springcloud
服务治理的理念。
springcloud
提供了这样的解决方案,我们只需要将
server
端当做一个服务注册到
eureka
中,
client
端去eureka中去获取配置中心
server
端的服务既可。
2.4.1 服务端改造
(
1
)
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(
2
)
配置文件
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:9000/eureka/
instance:
preferIpAddress: true
instance-id: ${spring.cloud.client.ip-address}:${server.port} #spring.cloud.client.ip-address:获取ip地址
这样
server
端的改造就完成了。先启动
eureka
注册中心,在启动
server
端,在浏览器中访问:
http://localhost:8761/
就会看到
server
端已经注册了到注册中心了。
2.4.2 服务端改造
(
1
)
添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(
2
)
配置文件
spring:
cloud:
config:
name: product #应用名称,需要对应git中配置文件名称的前半部分
profile: dev #开发环境
label: master #git中的分支
#通过注册中心获取config-server配置
discovery:
enabled: true #开启服务发现
service-id: config-server
2.4.3 高可用
为了模拟生产集群环境,我们改动
server
端的端口为
1000
,再启动一个
server
端来做服务的负载,提供高可用的server
端支持。
如上图就可发现会有两个
server
端同时提供配置中心的服务,防止某一台
down
掉之后影响整个系统的使用。
我们先单独测试服务端,分别访问:
http://localhost:10000/product
-
pro.yml
、
2.5 消息总线bus
在微服务架构中,通常会使用轻量级的消息代理来构建一个共用的消息主题来连接各个微服务实例,它广播的消息会被所有在注册中心的微服务实例监听和消费,也称消息总线。SpringCloud中也有对应的解决方案,
SpringCloud Bus
将分布式的节点用轻量的消息代理连接起来,可以很容易搭建消息总线,配合SpringCloud confifig
实现微服务应用配置信息的动态更新。
![](https://img-blog.csdnimg.cn/03f3e8bd1b9143789eb76c0309f3e62b.png)
- 提交代码触发post请求给bus/refresh
- server端接收到请求并发送给Spring Cloud Bus
- Spring Cloud bus接到消息并通知给其它客户端
- 其它客户端接收到通知,请求Server端获取最新配置
- 全部客户端均获取到最新的配置
2.6 消息总线整合配置中心
(
1
)
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
(
2
)服务端配置
server:
port: 10000 #服务端口
spring:
application:
name: config-server #指定服务名
cloud:
config:
server:
git:
uri: https://gitee.com/awen991129/config-repostrey.git
#注意这边一定要配置用户名,密码和跳过ssl验证,不然连接不上远端git
skip-ssl-validation: true
username: awen991129
password: awen991128
#配置rabbitmq发送异步消息
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
#配置的动态刷新
management:
endpoints:
web:
exposure:
include: bus-refresh
eureka:
client:
serviceUrl:
defaultZone: http://127.0.0.1:9000/eureka/
instance:
preferIpAddress: true
instance-id: ${spring.cloud.client.ip-address}:${server.port} #spring.cloud.client.ip-address:获取ip地址
(
3
)微服务客户端配置
spring:
cloud:
config:
name: product #应用名称,需要对应git中配置文件名称的前半部分
profile: dev #开发环境
label: master #git中的分支
#通过注册中心获取config-server配置
discovery:
enabled: true #开启服务发现
service-id: config-server
需要在码云对应的配置文件中添加
rabbitmq
的配置信息
![](https://img-blog.csdnimg.cn/17066f7f030d436cbadda31e0871ef2f.png)
重新启动对应的
eureka-server
,
confifig-server
,
product-service
。配置信息刷新后,只需要向配置 中心发送对应的请求,即可刷新每个客户端的配置。
3 开源配置中心Apollo
Apollo
(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。服务端基于Spring Boot
和
Spring Cloud
开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。
3.1 Apollo概述
pollo
(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。正是基于配置的特殊性,所以Apollo
从设计之初就立志于成为一个有治理能力的配置发布平台,目前提供了以下的特性:
统一管理不同环境、不同集群的配置
- Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。
- 同一份代码部署在不同的集群,可以有不同的配置,比如zookeeper的地址等
- 通过命名空间(namespace)可以很方便地支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
配置修改实时生效(热发布)
- 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
版本发布管理
- 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
灰度发布
- 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
权限管理、发布审核、操作审计
- 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
- 所有的操作都有审计日志,可以方便地追踪问题
客户端配置信息监控
- 可以在界面上方便地看到配置在被哪些实例使用
提供
Java
和
.Net
原生客户端
- 提供了Java和.Net的原生客户端,方便应用集成
- 支持Spring Placeholder, Annotation和Spring Boot的ConfifigurationProperties,方便应用使用(需要Spring 3.1.1+)
- 同时提供了Http接口,非Java和.Net应用也可以方便地使用
提供开放平台
API
- Apollo自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。不过Apollo出于通用性考虑,不会对配置的修改做过多限制,只要符合基本的格式就能保存,不会针对不同的配置值进行针对性的校验,如数据库用户名、密码,Redis服务地址等
- 对于这类应用配置,Apollo支持应用方通过开放平台API在Apollo进行配置的修改和发布,并且具备完善的授权和权限控制
部署简单
- 配置中心作为基础服务,可用性要求非常高,这就要求Apollo对外部依赖尽可能地少
- 目前唯一的外部依赖是MySQL,所以部署非常简单,只要安装好Java和MySQL就可以让Apollo跑起来
- Apollo还提供了打包脚本,一键就可以生成所有需要的安装包,并且支持自定义运行时参数
3.2 Apollo的实现方式
![](https://img-blog.csdnimg.cn/7c3cfd0391b44f3783bc351b81813e37.png)
上图简要描述了
Apollo
客户端的实现原理:
1.
客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。
2.
客户端还会定时从
Apollo
配置中心服务端拉取应用的最新配置。
- 这是一个fallback机制,为了防止推送机制失效导致配置不更新
- 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 - Not Modifified
- 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property:apollo.refreshInterval 来覆盖,单位为分钟。
3.
客户端从
Apollo
配置中心服务端获取到应用的最新配置后,会保存在内存中
4.
客户端会把从服务端获取到的配置在本地文件系统缓存一份
- 在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
5.
应用程序从
Apollo
客户端获取最新的配置、订阅配置更新通知
3.3 搭建Apollo服务端
3.3.1 环境要求
Java
Apollo
服务端:
1.8+
Apollo
客户端:
1.7+
由于需要同时运行服务端和客户端,所以建议安装
Java 1.8+
。
MySQL
版本要求:
5.6.5+
Apollo
的表结构对
timestamp
使用了多个
default
声明,所以需要
5.6.5
以上版本
3.3.2 环境搭建
(
1
)
下载
Apollo
通过官网提供的
下载连接
下载安装包
(
2
)
配置数据库
Apollo
服务端共需要两个数据库:
ApolloPortalDB
和
ApolloConfigDB
,我们把数据库、表的创建和样例数据都分别准备了sql
文件,只需要导入数据库即可。
ApolloPortalDB数据库
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# Create Database
# ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS ApolloConfigDB DEFAULT CHARACTER SET = utf8mb4;
Use ApolloConfigDB;
# Dump of table app
# ------------------------------------------------------------
DROP TABLE IF EXISTS `App`;
CREATE TABLE `App` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',
`OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',
`OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',
`OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',
`OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `AppId` (`AppId`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Name` (`Name`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表';
# Dump of table appnamespace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `AppNamespace`;
CREATE TABLE `AppNamespace` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字,注意,需要全局唯一',
`AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id',
`Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',
`IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',
`Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_AppId` (`AppId`),
KEY `Name_AppId` (`Name`,`AppId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';
# Dump of table audit
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Audit`;
CREATE TABLE `Audit` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`EntityName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '表名',
`EntityId` int(10) unsigned DEFAULT NULL COMMENT '记录ID',
`OpName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '操作类型',
`Comment` varchar(500) DEFAULT NULL COMMENT '备注',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志审计表';
# Dump of table cluster
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Cluster`;
CREATE TABLE `Cluster` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT '集群名字',
`AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'App id',
`ParentClusterId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父cluster',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_AppId_Name` (`AppId`,`Name`),
KEY `IX_ParentClusterId` (`ParentClusterId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群';
# Dump of table commit
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Commit`;
CREATE TABLE `Commit` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`ChangeSets` longtext NOT NULL COMMENT '修改变更集',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',
`Comment` varchar(500) DEFAULT NULL COMMENT '备注',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `AppId` (`AppId`(191)),
KEY `ClusterName` (`ClusterName`(191)),
KEY `NamespaceName` (`NamespaceName`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='commit 历史表';
# Dump of table grayreleaserule
# ------------------------------------------------------------
DROP TABLE IF EXISTS `GrayReleaseRule`;
CREATE TABLE `GrayReleaseRule` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',
`NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',
`BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'branch name',
`Rules` varchar(16000) DEFAULT '[]' COMMENT '灰度规则',
`ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '灰度对应的release',
`BranchStatus` tinyint(2) DEFAULT '1' COMMENT '灰度分支状态: 0:删除分支,1:正在使用的规则 2:全量发布',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='灰度规则表';
# Dump of table instance
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Instance`;
CREATE TABLE `Instance` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`DataCenter` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Data Center Name',
`Ip` varchar(32) NOT NULL DEFAULT '' COMMENT 'instance ip',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_UNIQUE_KEY` (`AppId`,`ClusterName`,`Ip`,`DataCenter`),
KEY `IX_IP` (`Ip`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='使用配置的应用实例';
# Dump of table instanceconfig
# ------------------------------------------------------------
DROP TABLE IF EXISTS `InstanceConfig`;
CREATE TABLE `InstanceConfig` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`InstanceId` int(11) unsigned DEFAULT NULL COMMENT 'Instance Id',
`ConfigAppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config App Id',
`ConfigClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Cluster Name',
`ConfigNamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Namespace Name',
`ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',
`ReleaseDeliveryTime` timestamp NULL DEFAULT NULL COMMENT '配置获取时间',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_UNIQUE_KEY` (`InstanceId`,`ConfigAppId`,`ConfigNamespaceName`),
KEY `IX_ReleaseKey` (`ReleaseKey`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Valid_Namespace` (`ConfigAppId`,`ConfigClusterName`,`ConfigNamespaceName`,`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用实例的配置信息';
# Dump of table item
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Item`;
CREATE TABLE `Item` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',
`Key` varchar(128) NOT NULL DEFAULT 'default' COMMENT '配置项Key',
`Value` longtext NOT NULL COMMENT '配置项值',
`Comment` varchar(1024) DEFAULT '' COMMENT '注释',
`LineNum` int(10) unsigned DEFAULT '0' COMMENT '行号',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_GroupId` (`NamespaceId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置项目';
# Dump of table namespace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Namespace`;
CREATE TABLE `Namespace` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',
`NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `AppId_ClusterName_NamespaceName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_NamespaceName` (`NamespaceName`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='命名空间';
# Dump of table namespacelock
# ------------------------------------------------------------
DROP TABLE IF EXISTS `NamespaceLock`;
CREATE TABLE `NamespaceLock` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT 'default' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`IsDeleted` bit(1) DEFAULT b'0' COMMENT '软删除',
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_NamespaceId` (`NamespaceId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='namespace的编辑锁';
# Dump of table release
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Release`;
CREATE TABLE `Release` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',
`Name` varchar(64) NOT NULL DEFAULT 'default' COMMENT '发布名字',
`Comment` varchar(256) DEFAULT NULL COMMENT '发布说明',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',
`Configurations` longtext NOT NULL COMMENT '发布配置',
`IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否废弃',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_ReleaseKey` (`ReleaseKey`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布';
# Dump of table releasehistory
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ReleaseHistory`;
CREATE TABLE `ReleaseHistory` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`AppId` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',
`BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT '发布分支名',
`ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联的Release Id',
`PreviousReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '前一次发布的ReleaseId',
`Operation` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '发布类型,0: 普通发布,1: 回滚,2: 灰度发布,3: 灰度规则更新,4: 灰度合并回主分支发布,5: 主分支发布灰度自动发布,6: 主分支回滚灰度自动发布,7: 放弃灰度',
`OperationContext` longtext NOT NULL COMMENT '发布上下文信息',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`,`BranchName`),
KEY `IX_ReleaseId` (`ReleaseId`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布历史';
# Dump of table releasemessage
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ReleaseMessage`;
CREATE TABLE `ReleaseMessage` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Message` varchar(1024) NOT NULL DEFAULT '' COMMENT '发布的消息内容',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Message` (`Message`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布消息';
# Dump of table serverconfig
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ServerConfig`;
CREATE TABLE `ServerConfig` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',
`Cluster` varchar(32) NOT NULL DEFAULT 'default' COMMENT '配置对应的集群,default为不针对特定的集群',
`Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',
`Comment` varchar(1024) DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_Key` (`Key`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';
# Config
# ------------------------------------------------------------
INSERT INTO `ServerConfig` (`Key`, `Cluster`, `Value`, `Comment`)
VALUES
('eureka.service.url', 'default', 'http://localhost:8080/eureka/', 'Eureka服务Url,多个service以英文逗号分隔'),
('namespace.lock.switch', 'default', 'false', '一次发布只能有一个人修改开关'),
('item.value.length.limit', 'default', '20000', 'item value最大长度限制'),
('config-service.cache.enabled', 'default', 'false', 'ConfigService是否开启缓存,开启后能提高性能,但是会增大内存消耗!'),
('item.key.length.limit', 'default', '128', 'item key 最大长度限制');
# Sample Data
# ------------------------------------------------------------
INSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`)
VALUES
('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com');
INSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`)
VALUES
('application', 'SampleApp', 'properties', 0, 'default app namespace');
INSERT INTO `Cluster` (`Name`, `AppId`)
VALUES
('default', 'SampleApp');
INSERT INTO `Namespace` (`Id`, `AppId`, `ClusterName`, `NamespaceName`)
VALUES
(1, 'SampleApp', 'default', 'application');
INSERT INTO `Item` (`NamespaceId`, `Key`, `Value`, `Comment`, `LineNum`)
VALUES
(1, 'timeout', '100', 'sample timeout配置', 1);
INSERT INTO `Release` (`ReleaseKey`, `Name`, `Comment`, `AppId`, `ClusterName`, `NamespaceName`, `Configurations`)
VALUES
('20161009155425-d3a0749c6e20bc15', '20161009155424-release', 'Sample发布', 'SampleApp', 'default', 'application', '{\"timeout\":\"100\"}');
INSERT INTO `ReleaseHistory` (`AppId`, `ClusterName`, `NamespaceName`, `BranchName`, `ReleaseId`, `PreviousReleaseId`, `Operation`, `OperationContext`, `DataChange_CreatedBy`, `DataChange_LastModifiedBy`)
VALUES
('SampleApp', 'default', 'application', 'default', 1, 0, 0, '{}', 'apollo', 'apollo');
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
ApolloConfigDB数据库
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# Create Database
# ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS ApolloPortalDB DEFAULT CHARACTER SET = utf8mb4;
Use ApolloPortalDB;
# Dump of table app
# ------------------------------------------------------------
DROP TABLE IF EXISTS `App`;
CREATE TABLE `App` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',
`OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',
`OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',
`OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',
`OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `AppId` (`AppId`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Name` (`Name`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表';
# Dump of table appnamespace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `AppNamespace`;
CREATE TABLE `AppNamespace` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字,注意,需要全局唯一',
`AppId` varchar(32) NOT NULL DEFAULT '' COMMENT 'app id',
`Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',
`IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',
`Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_AppId` (`AppId`),
KEY `Name_AppId` (`Name`,`AppId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';
# Dump of table consumer
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Consumer`;
CREATE TABLE `Consumer` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',
`OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',
`OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',
`OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',
`OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `AppId` (`AppId`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API消费者';
# Dump of table consumeraudit
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ConsumerAudit`;
CREATE TABLE `ConsumerAudit` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',
`Uri` varchar(1024) NOT NULL DEFAULT '' COMMENT '访问的Uri',
`Method` varchar(16) NOT NULL DEFAULT '' COMMENT '访问的Method',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_ConsumerId` (`ConsumerId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer审计表';
# Dump of table consumerrole
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ConsumerRole`;
CREATE TABLE `ConsumerRole` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',
`RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_RoleId` (`RoleId`),
KEY `IX_ConsumerId_RoleId` (`ConsumerId`,`RoleId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer和role的绑定表';
# Dump of table consumertoken
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ConsumerToken`;
CREATE TABLE `ConsumerToken` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'ConsumerId',
`Token` varchar(128) NOT NULL DEFAULT '' COMMENT 'token',
`Expires` datetime NOT NULL DEFAULT '2099-01-01 00:00:00' COMMENT 'token失效时间',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_Token` (`Token`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer token表';
# Dump of table favorite
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Favorite`;
CREATE TABLE `Favorite` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`UserId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '收藏的用户',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Position` int(32) NOT NULL DEFAULT '10000' COMMENT '收藏顺序',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `AppId` (`AppId`(191)),
KEY `IX_UserId` (`UserId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COMMENT='应用收藏表';
# Dump of table permission
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Permission`;
CREATE TABLE `Permission` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`PermissionType` varchar(32) NOT NULL DEFAULT '' COMMENT '权限类型',
`TargetId` varchar(256) NOT NULL DEFAULT '' COMMENT '权限对象类型',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_TargetId_PermissionType` (`TargetId`(191),`PermissionType`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='permission表';
# Dump of table role
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Role`;
CREATE TABLE `Role` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`RoleName` varchar(256) NOT NULL DEFAULT '' COMMENT 'Role name',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_RoleName` (`RoleName`(191)),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
# Dump of table rolepermission
# ------------------------------------------------------------
DROP TABLE IF EXISTS `RolePermission`;
CREATE TABLE `RolePermission` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',
`PermissionId` int(10) unsigned DEFAULT NULL COMMENT 'Permission Id',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_RoleId` (`RoleId`),
KEY `IX_PermissionId` (`PermissionId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和权限的绑定表';
# Dump of table serverconfig
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ServerConfig`;
CREATE TABLE `ServerConfig` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',
`Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',
`Comment` varchar(1024) DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_Key` (`Key`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';
# Dump of table userrole
# ------------------------------------------------------------
DROP TABLE IF EXISTS `UserRole`;
CREATE TABLE `UserRole` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`UserId` varchar(128) DEFAULT '' COMMENT '用户身份标识',
`RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DataChange_CreatedBy` varchar(32) DEFAULT '' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(32) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_RoleId` (`RoleId`),
KEY `IX_UserId_RoleId` (`UserId`,`RoleId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和role的绑定表';
# Dump of table Users
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Users`;
CREATE TABLE `Users` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Username` varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户名',
`Password` varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码',
`Email` varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱地址',
`Enabled` tinyint(4) DEFAULT NULL COMMENT '是否有效',
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
# Dump of table Authorities
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Authorities`;
CREATE TABLE `Authorities` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Username` varchar(64) NOT NULL,
`Authority` varchar(50) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# Config
# ------------------------------------------------------------
INSERT INTO `ServerConfig` (`Key`, `Value`, `Comment`)
VALUES
('apollo.portal.envs', 'dev', '可支持的环境列表'),
('organizations', '[{\"orgId\":\"TEST1\",\"orgName\":\"样例部门1\"},{\"orgId\":\"TEST2\",\"orgName\":\"样例部门2\"}]', '部门列表'),
('superAdmin', 'apollo', 'Portal超级管理员'),
('api.readTimeout', '10000', 'http接口read timeout'),
('consumer.token.salt', 'someSalt', 'consumer token salt'),
('admin.createPrivateNamespace.switch', 'true', '是否允许项目管理员创建私有namespace'),
('configView.memberOnly.envs', 'dev', '只对项目成员显示配置信息的环境列表,多个env以英文逗号分隔');
INSERT INTO `Users` (`Username`, `Password`, `Email`, `Enabled`)
VALUES
('apollo', '$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS', 'apollo@acme.com', 1);
INSERT INTO `Authorities` (`Username`, `Authority`) VALUES ('apollo', 'ROLE_user');
# Sample Data
# ------------------------------------------------------------
INSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`)
VALUES
('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com');
INSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`)
VALUES
('application', 'SampleApp', 'properties', 0, 'default app namespace');
INSERT INTO `Permission` (`Id`, `PermissionType`, `TargetId`)
VALUES
(1, 'CreateCluster', 'SampleApp'),
(2, 'CreateNamespace', 'SampleApp'),
(3, 'AssignRole', 'SampleApp'),
(4, 'ModifyNamespace', 'SampleApp+application'),
(5, 'ReleaseNamespace', 'SampleApp+application');
INSERT INTO `Role` (`Id`, `RoleName`)
VALUES
(1, 'Master+SampleApp'),
(2, 'ModifyNamespace+SampleApp+application'),
(3, 'ReleaseNamespace+SampleApp+application');
INSERT INTO `RolePermission` (`RoleId`, `PermissionId`)
VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 4),
(3, 5);
INSERT INTO `UserRole` (`UserId`, `RoleId`)
VALUES
('apollo', 1),
('apollo', 2),
('apollo', 3);
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
注意:如果本地已经创建过
Apollo
数据库,请注意备份数据。我们准备的
sql
文件会清空
Apollo相关的表。
(
3
)
配置数据库连接
Apollo
服务端需要知道如何连接到你前面创建的数据库,所以需要编辑
demo.sh
,修改
ApolloPortalDB和ApolloConfifigDB
相关的数据库连接串信息。
#apollo config db info
apollo_config_db_url=jdbc:mysql://localhost:3306/ApolloConfigDB?
characterEncoding=utf8
apollo_config_db_username=用户名
apollo_config_db_password=密码(如果没有密码,留空即可)
# apollo portal db info
apollo_portal_db_url=jdbc:mysql://localhost:3306/ApolloPortalDB?
characterEncoding=utf8
apollo_portal_db_username=用户名
apollo_portal_db_password=密码(如果没有密码,留空即可)
(
4
)
启动
Apollo
配置中心
启动脚本会在本地启动
3
个服务,分别使用
8070, 8080, 8090
端口,请确保这
3
个端口当前没有被使用。
//linux启动命令
./demo.sh start
//Windows启动命令 且进入cmd模式启动
demo.sh start
当看到如下输出后,就说明启动成功了!
![](https://img-blog.csdnimg.cn/52c07afdc17246b9887ecac2f4b9c4c3.png)
(
5
)
测试
通过浏览器打开
http://ip:8070
即可访问Apollo配置中心的前端页面。
![](https://img-blog.csdnimg.cn/cd25b38e82e448eb8569912f44655acb.png)
输入默认用户名密码apollo/admin即可登录到应用中。
3.4 客户端集成
(
1
)
引入依赖
Apollo
的客户端
jar
包已经上传到中央仓库,应用在实际使用时只需要按照如下方式引入即可。
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.1.0</version>
</dependency>
(
2
)
Spring Boot
集成
Spring Boot
支持通过
application.properties/bootstrap.properties
来配置,该方式能使配置在更早的阶段注入,比如使用 @ConditionalOnProperty
的场景或者是有一些
spring-boot-starter
在启动阶段就需要读取配置做一些事情(如
dubbo-spring-boot-project
),所以对于
Spring Boot
环境建议通过以下方式来接入Apollo(
需要
0.10.0
及以上版本)。
使用方式很简单,只需要在
application.properties/bootstrap.properties
中按照如下样例配置即可。
1.
注入默认
application
namespace
的配置示例
apollo:
bootstrap: #开启apollo
enabled: true
meta: http://192.168.137.1:8080
app:
id: product-service #指定apollo配置中心中的appid
2.
注入非默认
application
namespace
或多个
namespace
的配置示例
apollo.bootstrap.enabled = true
apollo.bootstrap.namespaces = application,FX.apollo,application.yml
3.
将
Apollo
配置加载提到初始化日志系统之前
(1.2.0+) 从1.2.0
版本开始,如果希望把日志相关的配置(如
logging.level.root=info
或
logbackspring.xml 中的参数)也放在
Apollo
管理,那么可以额外配置apollo.bootstrap.eagerLoad.enabled=true 来使
Apollo
的加载顺序放到日志系统加载之前,不过这会导致Apollo
的启动过程无法通过日志的方式输出
(
因为执行
Apollo
加载的时候,日志系统压根没有准备好呢!所以在Apollo
代码中使用
Slf4j
的日志输出便没有任何内容
)
,更多信息可以参考
PR 1614
。参考
配置示例如下:
# will inject 'application' namespace in bootstrap phase
apollo.bootstrap.enabled = true
# put apollo initialization before logging system initialization
apollo.bootstrap.eagerLoad.enabled=true