spring cloud微服務自定義數據源


場景說明

      項目整體是使用的是spring cloud架構,配置中心為spring cloud config組件。

      最近項目中有個需求是上線的時候需要新舊服務同時運行, 但數據庫表結構在本期變更中發生了很大的變化,所以這里考慮的使用自定義數據源來實現新舊服務訪問不同的數據源。

 新服務訪問線上的正式數據庫,舊的服務訪問當前線上數據庫的備份庫。新的部署規划如下:

 

 

 

     備注:這里熟悉spring boot的同學會說,這很好辦,可以通過spring boot配置文件的優先級順序,直接在當前服務根路徑下定義config/application.yml文件,然后直接配置spring.datasource

來覆蓋全局的配置即可。大家都知道spring boot 工程目錄下config/application.yml配置優先級是最高的,這在單體項目下,確實是成立的,但是如果使用的spring cloud config配置中心,則配置

中心的配置優先級才是最高的。

 

實現方案  —— mysql

     項目環境: spring boot 1.5.9 +  spring cloud 1.3.6 + durid連接池

1. 在當前項目配置文件添加新數據源配置,這里增加數據源為dbBak, 使用的是druid連接池

spring:
  #數據源
  datasource:
    dbBak:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test?useSSL=false&characterEncoding=utf8&allowMultiQueries=true
      username: root
      password: 123456
      type: com.alibaba.druid.pool.DruidDataSource
    # update at 2021-07-06 by author ,這里的配置durid配置項與password平級 #druid: # 初始化連接池個數 initial
-size: 5 # 最大連接池個數 max-active: 20 # 最小連接池個數 min-idle: 5 # 配置獲取連接等待超時的時間,單位毫秒,缺省啟用公平鎖,並發效率會有所下降 max-wait: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒 time-between-eviction-runs-millis: 60000 # 配置一個連接在池中最小生存的時間,單位是毫秒 min-evictable-idle-time-millis: 300000 # 如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會起作用 validation-query: SELECT 1 FROM DUAL # 建議配置為true,不影響性能,並且保證安全性。 # 申請連接的時候檢測,如果空閑時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測連接是否有效。 test-while-idle: true # 申請連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能 test-on-borrow: false # 歸還連接時執行validationQuery檢測連接是否有效,做了這個配置會降低性能 test-on-return: false # 打開PSCache,並且指定每個連接上PSCache的大小 pool-prepared-statements: true
      # 配置過濾器, 打開sql監控,如果這里不配置,sql監控上沒數據
filters: stat,wall
      # 配置由於疏忽或者使用不當產生數據庫連接泄露的配置
      #開啟超時自動釋放連接
remove-abandoned: true
#檢測時間
remove-abandoned-timeout: 300
#是否顯示連接未釋放的堆棧位置
log-abandoned: true
 
        

 

2. 增加config配置文件,新建配置文件DuridDataSourceConfig配置類

@Configuration
public class DruidDatasourceConfig {

    /**
     * 添加 DruidDataSource 組件到容器中,並綁定屬性:
     * 將自定義的 Druid 數據源添加到容器中,不再讓 Spring Boot 自動創建
     * 這樣做的目的是:綁定全局配置文件中的 druid 數據源屬性到 com.alibaba.druid.pool.DruidDataSource
     * 從而讓它們生效
     *
     * @ConfigurationProperties(prefix = "spring.datasource"):作用就是將 全局配置文件中 前綴為 spring.datasource
     * 的屬性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名參數中
     */
    @ConfigurationProperties(prefix = "spring.datasource.dbBak")
    @Bean
    public DataSource druidDataSource() {
        return new DruidDataSource();
    }

    /**
     * 注冊 Druid 監控之管理后台的 Servlet
     */
    @Bean
    public ServletRegistrationBean servletRegistrationBean() {
        ServletRegistrationBean bean = new ServletRegistrationBean(
                new StatViewServlet(), "/druid/*");

        /**
         * 這些參數可以在 com.alibaba.druid.support.http.StatViewServlet 的父類 com.alibaba.druid.support.http.ResourceServlet 中找到
         * loginUsername:Druid 后台管理界面的登錄賬號
         * loginPassword:Druid 后台管理界面的登錄密碼
         * allow:Druid 白名單,后台允許誰可以訪問,多個用逗號分割, 如果allow沒有配置或者為空,則允許所有訪問
         *      initParams.put("allow", "localhost"):表示只有本機可以訪問
         *      initParams.put("allow", ""):為空或者為null時,表示允許所有訪問
         * deny:Druid 黑名單,后台拒絕誰訪問,多個用逗號分割 (共同存在時,deny優先於allow)
         *      initParams.put("deny", "192.168.1.20");表示禁止此ip訪問
         */
        Map<String, String> initParams = new HashMap<>();
        initParams.put("loginUsername", "admin");
        initParams.put("loginPassword", "88888");
        initParams.put("allow", "");
        initParams.put("allow", "localhost");

        /** 設置初始化參數*/
        bean.setInitParameters(initParams);
        return bean;
    }

    /**
     * 配置 Druid 監控之 web 監控的 filter
     * 這個過濾器的作用就是統計 web 應用請求中所有的數據庫信息,
     * 比如 發出的 sql 語句,sql 執行的時間、請求次數、請求的 url 地址、以及seesion 監控、數據庫表的訪問次數 等等。
     */
    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        /** exclusions:設置哪些請求進行過濾排除掉,從而不進行統計*/
        Map<String, String> initParams = new HashMap<>();
        initParams.put("exclusions", "*.js,*.gif,*.jpg,*,png,*.css,/druid/*");
        bean.setInitParameters(initParams);

        /** "/*" 表示過濾所有請求*/
        bean.setUrlPatterns(Arrays.asList("/*"));
        return bean;
    }

}

 

3. 正常啟動項目后,訪問 http://localhost:8080/druid/ ,會打開durid控制台頁面,切換到【數據源】頁面,就會看到連接已經更新

 

4. 控制台打印DataSource調試信息

@Order(1)
@Component
public class DemoCommandLineRunner implements CommandLineRunner {

    private final static Logger logger = LoggerFactory.getLogger(DemoCommandLineRunner.class);

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void run(String... strings) throws Exception {
        // 這里可打印 啟動參數
        logger.info("當前項目啟動參數為:{}", strings);

        logger.debug("打印連接池信息..");
        //這行為測試信息,DataSource在第一次sql查詢后初始化
        jdbcTemplate.queryForList("select 1 from dual", Integer.class);
        logger.debug("DataSource:{}", DruidStatManagerFacade.getInstance().getDataSourceStatDataList());
    }
}

 5. 優化JdbcTemplate顯示調用產生數據庫連接泄露的方法

#反例寫法
Connection conn = jdbcTemplate.getDataSource().getConnection();

#正確寫法
Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource())

  

實現方案  —— mongodb

     項目環境: spring boot 1.5.9 +  spring cloud 1.3.6 + spring data mongodb

1. 在當前項目配置文件添加新數據源配置,這里增加數據源為mongodb2, 使用的是spring data mongodb連接方式

spring:
#mongodb 配置
data:
mongodb2:
host: localhost
port: 27017
database: demo_bak
username: admin
password: 123456

 

2. 增加config配置文件,新建配置文件MongodbConfig 配置類

@Configuration
@ConfigurationProperties(
prefix = "spring.data.mongodb2", ignoreInvalidFields = true
)
@Setter
public class MongodbConfig {

private String host;

private Integer port = null;

private String username;

private char[] password;

private String database;

@Bean
public MongoClient mongoClient(){
//配置連接mongo客戶端,一共三個參數
List<MongoCredential> credentialList = new ArrayList<MongoCredential>();
credentialList.add(MongoCredential.createCredential(username,database,password));
//主機端口,賬號密碼,超時時間等的配置
return new MongoClient(new ServerAddress(host,port),
credentialList,
MongoClientOptions.builder()
.socketTimeout(3000)
.minHeartbeatFrequency(25)
.heartbeatSocketTimeout(3000)
.build());
}

@Bean
public MongoDbFactory mongoDbFactory(){
//注冊一個MongoDbFactory,連接到指定數據庫
return new SimpleMongoDbFactory(mongoClient(),database);
}

@Bean
public MongoTemplate mongoTemplate(){
//將MongoDbFactory作為參數,注冊MongoTemplate
return new MongoTemplate(mongoDbFactory());
}


}

 

3. 正常啟動項目后,查看控制太日志,會看到大致如下內容,證明自定義數據源生效了

2021-06-26 22:55:32.522  INFO xx --- [           main] o.m.d.cluster                            : Cluster created with settings {hosts=[localhost:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2021-06-26 22:55:32.729  INFO xx --- [0.201.105:27018] o.m.d.connection                         : Opened connection [connectionId{localValue:1, serverValue:1558}] to localhost:27017

2021-06-26 22:55:32.733 INFO xx --- [0.201.105:27018] o.m.d.cluster : Monitor thread successfully connected to server with description ServerDescription{address=localhost:27017, type=STANDALONE, state=CONNECT

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM