Zookeeper发布订阅之SpringBoot+Mybatis多数据源

   1.前言

   数据发布/订阅系统,即所谓的配置中心,顾名思义就是发布者将数据发布到Zookeeper的一个或一系列节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中管理和数据的动态更新。

          发布订阅一般有两种模式,分别是推(Push)和拉(Pull)模式。在推拉模式中,服务端主动将数据更新发送给所有订阅的客户端;而拉模式则是客户端主动发起请求来获取最新数据。Zookeeper采取推和拉相结合的方式:客户端会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据。

     “配置管理”的实际案例来展示Zookeeper在"数据发布/订阅"场景下的使用方式。

   2.案例

           将敏感的配置信息存放与Zookeeper中。启动项目时,自动从Zookeeper中获取。

          Maven坐标:

      

 1  <dependency>
 2             <groupId>org.springframework.boot</groupId>
 3             <artifactId>spring-boot-starter-web</artifactId>
 4         </dependency>
 5         <dependency>
 6             <groupId>org.springframework.boot</groupId>
 7             <artifactId>spring-boot-starter-jdbc</artifactId>
 8         </dependency>
 9         <dependency>
10             <groupId>org.projectlombok</groupId>
11             <artifactId>lombok</artifactId>
12             <optional>true</optional>
13         </dependency>
14         <dependency>
15             <groupId>org.apache.zookeeper</groupId>
16             <artifactId>zookeeper</artifactId>
17             <version>3.4.10</version>
18         </dependency>
19         <dependency>
20             <groupId>org.apache.curator</groupId>
21             <artifactId>curator-framework</artifactId>
22             <version>2.9.0</version>
23         </dependency>
24         <dependency>
25             <groupId>org.apache.curator</groupId>
26             <artifactId>curator-recipes</artifactId>
27             <version>2.9.0</version>
28         </dependency>
29         <dependency>
30             <groupId>org.mybatis</groupId>
31             <artifactId>mybatis</artifactId>
32             <version>3.4.3</version>
33         </dependency>
34         <dependency>
35             <groupId>org.mybatis</groupId>
36             <artifactId>mybatis-spring</artifactId>
37             <version>1.3.1</version>
38         </dependency>
39         <dependency>
40             <groupId>mysql</groupId>
41             <artifactId>mysql-connector-java</artifactId>
42         </dependency>
43         <dependency>
44             <groupId>com.zaxxer</groupId>
45             <artifactId>HikariCP</artifactId>
46             <version>2.7.4</version>
47         </dependency>
48         <dependency>
49             <groupId>org.springframework.boot</groupId>
50             <artifactId>spring-boot-starter-test</artifactId>
51             <scope>test</scope>
52         </dependency>

         自动从Zookeeper中获取”配置信息“,并放入Enviroment中

 

             配置ApplicationContextInitializer,项目在启动先调用该类,进行加载环境变量到Enviroment中去(这里采用在classpath路径下新建META-INF/spring.factories文件方式,其它两种方式为:

    1.使用SpringApplication 对象,调用 addInitializers()

    2.在配置文件中配置 context.initializer.classes =xx)

               spring.factories文件

     

1 # Initializers
2 org.springframework.context.ApplicationContextInitializer=\
3 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环境

 1 @Slf4j
 2 public class GlobalConfigInit implements ApplicationContextInitializer<ConfigurableApplicationContext> {
 3 
 4     @Override
 5     public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
 6         ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment();
 7         String zkUri = environment.getProperty("com.zookeeper.url");
 8         if (null == zkUri) {
 9             log.warn("could not find zk uri,unconf not configured..");
10         } else {
11             ZookeeperUtils zookeeperUtils = new ZookeeperUtils();
12             zookeeperUtils.setZkUri(zkUri);
13             String unconf = environment.getProperty("com.unconfig.info");
14             if (null != unconf) {
15                 log.info("config uniconf .. {}", unconf);
16                 ZkPropertySource propertySource = new ZkPropertySource("default", zookeeperUtils.getEnv(unconf));
17                 environment.getPropertySources().addLast(propertySource);
18             } else {
19                 log.warn("unconf not configured..");
20             }
21         }
22     }
23 
24     public String getEnv(Environment environment) {
25         String zkUrl = environment.getProperty("com.zookeeper.url");
26         if (null != zkUrl && !zkUrl.isEmpty()) {
27             return zkUrl;
28         } else {
29             String unConfig = environment.getProperty("com.unconfig.info");
30             if (unConfig != null && !unConfig.isEmpty()) {
31                 ZookeeperURI parse = ZookeeperURI.parse(unConfig);
32                 String inferZkUrl = "zk://" + parse.getServers();
33                 System.setProperty("com.zookeeper.url", inferZkUrl);
34                 log.info("inferred zk uri from unconf zk {}", inferZkUrl);
35                 return inferZkUrl;
36             } else {
37                 return null;
38             }
39         }
40     }
41 }

     这里不再多说,接下来配置数据源。

  

 1 @Configuration
 2 @MapperScan(basePackages = {"com.example.zkconfig.dao.write"}, sqlSessionFactoryRef = "writeSqlSessionFactory")
 3 public class WriteDataSourceConfig {
 4 
 5     @Value("${write.datasource.mappers}")
 6     private String location;
 7 
 8     @Bean(name = "writeDataSource")
 9     @ConfigurationProperties(prefix = "write.datasource")
10     public DataSource dataSource() {
11         return DataSourceBuilder.create().type(HikariDataSource.class).build();
12     }
13 
14     @Bean(name = "writeSqlSessionFactory")
15     public SqlSessionFactory writeSqlSessionFactory(@Qualifier("writeDataSource") DataSource dataSource) throws Exception {
16         SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
17         sqlSessionFactoryBean.setDataSource(dataSource);
18         sqlSessionFactoryBean.setMapperLocations(
19                 new PathMatchingResourcePatternResolver().getResources(location));
20         return sqlSessionFactoryBean.getObject();
21     }
22 
23     @Bean(name = "writeTransactionManager")
24     public DataSourceTransactionManager writeTransactionManager(@Qualifier("writeDataSource") DataSource dataSource) {
25         return new DataSourceTransactionManager(dataSource);
26     }
27 }

      而我实际在zookeeper节点配置的数据

  

    

 

 

 

测试走一波,启动成功。

posted @ 2018-07-19 00:24  coding400  阅读(1175)  评论(0编辑  收藏  举报