Zookeeper发布订阅之SpringBoot+Mybatis多数据源
1.前言
数据发布/订阅系统,即所谓的配置中心,顾名思义就是发布者将数据发布到Zookeeper的一个或一系列节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中管理和数据的动态更新。
发布订阅一般有两种模式,分别是推(Push)和拉(Pull)模式。在推拉模式中,服务端主动将数据更新发送给所有订阅的客户端;而拉模式则是客户端主动发起请求来获取最新数据。Zookeeper采取推和拉相结合的方式:客户端会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据。
“配置管理”的实际案例来展示Zookeeper在"数据发布/订阅"场景下的使用方式。
2.案例
将敏感的配置信息存放与Zookeeper中。启动项目时,自动从Zookeeper中获取。
Maven坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>2.7.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
自动从Zookeeper中获取”配置信息“,并放入Enviroment中
配置ApplicationContextInitializer,项目在启动先调用该类,进行加载环境变量到Enviroment中去(这里采用在classpath路径下新建META-INF/spring.factories文件方式,其它两种方式为:
1.使用SpringApplication 对象,调用 addInitializers()
2.在配置文件中配置 context.initializer.classes =xx)
spring.factories文件
# Initializers
org.springframework.context.ApplicationContextInitializer=\
com.example.zkconfig.config.GlobalConfigInit
GlobalConfigIn类进行一系列配置文件加载及Zk连接,我用的Curator框架 我的application.properties此刻内容
server.port=8076
#zk 配置信息
com.unconfig.info=/config/zk-config
application-dev 则对应具体连接机器
#zk
com.zookeeper.url=zk://192.168.159.129:2181
从zk取配置信息放入spring环境
@Slf4j
public class GlobalConfigInit implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
String zkUri = environment.getProperty("com.zookeeper.url");
if (null == zkUri) {
log.warn("could not find zk uri,unconf not configured..");
} else {
ZookeeperUtils zookeeperUtils = new ZookeeperUtils();
zookeeperUtils.setZkUri(zkUri);
String unconf = environment.getProperty("com.unconfig.info");
if (null != unconf) {
log.info("config uniconf .. {}", unconf);
ZkPropertySource propertySource = new ZkPropertySource("default", zookeeperUtils.getEnv(unconf));
environment.getPropertySources().addLast(propertySource);
} else {
log.warn("unconf not configured..");
}
}
} public String getEnv(Environment environment) {
String zkUrl = environment.getProperty("com.zookeeper.url");
if (null != zkUrl && !zkUrl.isEmpty()) {
return zkUrl;
} else {
String unConfig = environment.getProperty("com.unconfig.info");
if (unConfig != null && !unConfig.isEmpty()) {
ZookeeperURI parse = ZookeeperURI.parse(unConfig);
String inferZkUrl = "zk://" + parse.getServers();
System.setProperty("com.zookeeper.url", inferZkUrl);
log.info("inferred zk uri from unconf zk {}", inferZkUrl);
return inferZkUrl;
} else {
return null;
}
}
}
}
这里不再多说,接下来配置数据源。
@Configuration
@MapperScan(basePackages = {"com.example.zkconfig.dao.write"}, sqlSessionFactoryRef = "writeSqlSessionFactory")
public class WriteDataSourceConfig { @Value("${write.datasource.mappers}")
private String location; @Bean(name = "writeDataSource")
@ConfigurationProperties(prefix = "write.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
} @Bean(name = "writeSqlSessionFactory")
public SqlSessionFactory writeSqlSessionFactory(@Qualifier("writeDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources(location));
return sqlSessionFactoryBean.getObject();
} @Bean(name = "writeTransactionManager")
public DataSourceTransactionManager writeTransactionManager(@Qualifier("writeDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
而我实际在zookeeper节点配置的数据

测试走一波,启动成功。
Zookeeper发布订阅之SpringBoot+Mybatis多数据源的更多相关文章
- springboot + mybatis + 多数据源
此文已由作者赵计刚薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验 在实际开发中,我们一个项目可能会用到多个数据库,通常一个数据库对应一个数据源. 代码结构: 简要原理: 1) ...
- spring-boot (四) springboot+mybatis多数据源最简解决方案
学习文章来自:http://www.ityouknow.com/spring-boot.html 配置文件 pom包就不贴了比较简单该依赖的就依赖,主要是数据库这边的配置: mybatis.confi ...
- 第九章 springboot + mybatis + 多数据源 (AOP实现)
在第八章 springboot + mybatis + 多数据源代码的基础上,做两点修改 1.ShopDao package com.xxx.firstboot.dao; import org.spr ...
- 【第九章】 springboot + mybatis + 多数据源 (AOP实现)
在第八章 springboot + mybatis + 多数据源代码的基础上,做两点修改 1.ShopDao package com.xxx.firstboot.dao; import org.spr ...
- springboot mybatis 多数据源配置
首先导入mybatis等包,这里就不多说. 下面是配置多数据源和mybatis,每个数据源对应一套mybatis模板 数据源1: package com.aaaaaaa.config.datasour ...
- 第八章 springboot + mybatis + 多数据源(转载)
本篇博客转发自:http://www.cnblogs.com/java-zhao/p/5413845.html 在实际开发中,我们一个项目可能会用到多个数据库,通常一个数据库对应一个数据源. 代码结构 ...
- 【第八章】 springboot + mybatis + 多数据源
在实际开发中,我们一个项目可能会用到多个数据库,通常一个数据库对应一个数据源. 代码结构: 简要原理: 1)DatabaseType列出所有的数据源的key---key 2)DatabaseConte ...
- 第八章 springboot + mybatis + 多数据源2(解决循环引用)
解决了循环引用 1.application.properties #the first datasource jdbc.names:1,2 jdbc1.driverClassName = com.my ...
- spring boot(七):springboot+mybatis多数据源最简解决方案
说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多,大都是根据jpa来做多数据源解决方案,要不就是老的spring多数据源解 ...
随机推荐
- JAVA数据类型(转)
java中数据的基本类型分为: 基本数据类型和引用数据类型,对此不多介绍: 接下来讨论一下java中数据类型存储在哪 基本数据类型存储在哪,取决于基本类型在哪声明: 1 ...
- c++对象内存的分配
1 关于c++的对象 只要是用了class或者struct定义的,都是对象,不管有没有方法.不过,一般情况下,没有方法的对象用struct关键字来定义. 2 不用new关键字定义对象 要看这样的对象在 ...
- 图床QAQ
- Wannafly挑战赛12 A 银行存款 【DP】【DFS】
链接:https://www.nowcoder.com/acm/contest/79/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536 ...
- 校园网络 usaco
这道题和上一道[最受欢迎的牛]差不多,都是强连通分量的练习题: 第一问实际上就是问缩点后入度为0的点有多少,第二问就是问添加几条边能使缩点后的图变成强连通图: 第一问好做,第二问需要动下脑子,也不难: ...
- github 博客模板
http://www.jianshu.com/p/d658ba3b4351 http://jekyllthemes.org/
- 9--RESTful支持
1.对url进行规范,写RESTful格式的url 非REST的url:http://...../queryItems.action?id=001&type=T01 REST的url风格:ht ...
- ES搜索排序,文档相关度评分介绍——Vector Space Model
Vector Space Model The vector space model provides a way of comparing a multiterm query against a do ...
- storm源码剖析(2):storm的配置项
storm的配置项,可以从backtype/storm/Config.java中找到所有配置项及其描述
- k8s-flannel容器集群网络部署
[root@k8s-master src]# wget https://github.com/coreos/flannel/releases/download/v0.9.1/flannel-v0.9. ...