springBoot2集成shardingsphere4做讀寫分離並記錄sql


 

本文記錄springboot2集成shardingsphere4實現業務層讀寫分離,其余相關涉及組件 :mybatis-plus,hikari, postgresql , logback ,p6spy

1. pom文件引入shardingsphere4依賴      

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.1</version>
</dependency>

2.shardingsphere4相關配置項

 1 spring:
 2   shardingsphere:
 3     datasource:
 4       names: master,slave0,slave1
 5       master:
 6         type: com.zaxxer.hikari.HikariDataSource
 7         driver-class-name: com.p6spy.engine.spy.P6SpyDriver
 8 #        連接池配置項
 9         jdbc-url: jdbc:p6spy:postgresql://a:5432/bb
10         username: postgres
11         password: postgres
12         autoCommit: false
13         maximum-pool-size: 10
14         validation-timeout: 5_000
15         connection-timeout: 30_000
16         idle-timeout: 600_000
17         max-lifetime: 1_800_000
18       slave0:
19         type: com.zaxxer.hikari.HikariDataSource
20         driver-class-name: com.p6spy.engine.spy.P6SpyDriver
21         jdbc-url: jdbc:p6spy:postgresql://b:5432/bb
22         username: postgres
23         password: postgres
24         autoCommit: false
25         maximum-pool-size: 10
26         validation-timeout: 5_000
27         connection-timeout: 30_000
28         idle-timeout: 600_000
29         max-lifetime: 1_800_000
30       slave1:
31         type: com.zaxxer.hikari.HikariDataSource
32         driver-class-name: com.p6spy.engine.spy.P6SpyDriver
33         jdbc-url: jdbc:p6spy:postgresql://c:5432/bb
34         username: postgres
35         password: postgres
36         autoCommit: false
37         maximum-pool-size: 10
38         validation-timeout: 5_000
39         connection-timeout: 30_000
40         idle-timeout: 600_000
41         max-lifetime: 1_800_000
42 #        讀寫分離配置項
43     masterslave:
44       load-balance-algorithm-type: round_robin  # random
45       master-data-source-name: master
46       slave-data-source-names: slave0,slave1
47       name: ms
48     props:
49       sql:
50         show: true

3.p6spy相關配置項 (resources下創建spy.properties文件,內容如下)

 1 #開啟模塊sql記錄和長時sql記錄
 2 module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
 3 logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
 4 #自定義sql輸出格式
 5 customLogMessageFormat=%(currentTime) | TIME\uFF1A %(executionTime) ms | SQL\uFF1A %(sql)
 6 #日志輸出方式
 7 appender=com.p6spy.engine.spy.appender.Slf4JLogger
 8 excludecategories=info,debug,result,resultset
 9 deregisterdrivers=true
10 dateformat=yyyy-MM-dd HH:mm:ss
11 driverlist=org.postgresql.Driver
12 #開啟長時sql記錄
13 outagedetection=true
14 #觸發長時記錄時限
15 outagedetectioninterval=2

4.logback相關配置(resource文件夾下創建logback-spring.xml內容如下)

  1 <?xml version="1.0" encoding="UTF-8"?>
  2 <configuration>
  3 
  4     <!--日志格式應用spring boot默認的格式,也可以自己更改-->
  5     <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
  6 
  7     <!--定義日志存放的位置,默認存放在項目啟動的相對路徑的目錄-->
  8     <springProperty scope="context" name="LOG_PATH" source="log.path" defaultValue="log"/>
  9     <springProperty scope="context" name="ZONE" source="quick.zone" defaultValue="default"/>
 10     <springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="app"/>
 11     <springProperty scope="context" name="LOGSTASH_URL" source="logstash.url" defaultValue="localhost:4560"/>
 12 
 13     <!-- ****************************************************************************************** -->
 14     <!-- ****************************** 開發環境日志 ************************************ -->
 15     <!-- ****************************************************************************************** -->
 16     <springProfile name="local">
 17         <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 18             <encoder>
 19                 <pattern>${CONSOLE_LOG_PATTERN}</pattern>
 20                 <charset>utf-8</charset>
 21             </encoder>
 22         </appender>
 23 
 24         <!-- 日志記錄器,日期滾動記錄 -->
 25         <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
 26 
 27             <!-- 正在記錄的日志文件的路徑及文件名 -->
 28             <file>${LOG_PATH}/${ZONE}-${APP_NAME}-local.log</file>
 29 
 30             <!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
 31             <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 32 
 33                 <!-- 歸檔的日志文件的路徑,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
 34                 <fileNamePattern>${LOG_PATH}/all/${ZONE}-${APP_NAME}-%d{yyyy-MM-dd}.%i-local.log</fileNamePattern>
 35 
 36                 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 37                     <maxFileSize>10MB</maxFileSize>
 38                 </timeBasedFileNamingAndTriggeringPolicy>
 39             </rollingPolicy>
 40 
 41             <!-- 追加方式記錄日志 -->
 42             <append>true</append>
 43 
 44             <!-- 日志文件的格式 -->
 45             <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
 46                 <pattern>${FILE_LOG_PATTERN}</pattern>
 47                 <charset>utf-8</charset>
 48             </encoder>
 49         </appender>
 50 
 51         <!--默認所有的包以warn-->
 52         <root level="warn">
 53             <appender-ref ref="STDOUT"/>
 54             <appender-ref ref="FILE"/>
 55         </root>
 56 
 57         <!--ShardingSphere打印sql用-->
 58         <logger name="ShardingSphere-SQL" level="info"/>
 59         <!--p6spy打印sql-->
 60         <logger name="p6spy" level="info"/>
 61         <!--屏蔽getRowIdLifetime未實作警告-->
 62         <logger name="com.zaxxer.hikari.pool.ProxyConnection" level="error"/>
 63 
 64         <!--各個服務的包在本地執行的時候,打開debug模式-->
 65         <logger name="com.myproject" level="debug" additivity="false">
 66             <appender-ref ref="STDOUT"/>
 67             <appender-ref ref="FILE"/>
 68         </logger>
 69     </springProfile>
 70 
 71     <!-- ********************************************************************************************** -->
 72     <!-- **** 放到服務器上不管在什么環境都只在文件記錄日志,控制台(catalina.out)打印logback捕獲不到的日志 **** -->
 73     <!-- ********************************************************************************************** -->
 74     <springProfile name="!local">
 75 
 76         <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 77             <encoder>
 78                 <pattern>${CONSOLE_LOG_PATTERN}</pattern>
 79                 <charset>utf-8</charset>
 80             </encoder>
 81         </appender>
 82 
 83         <!-- 日志記錄器,日期滾動記錄 -->
 84         <appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
 85 
 86             <!-- 正在記錄的日志文件的路徑及文件名 -->
 87             <file>${LOG_PATH}/quick/${ZONE}-${APP_NAME}-log-error.log</file>
 88 
 89             <!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
 90             <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
 91 
 92                 <!-- 歸檔的日志文件的路徑,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
 93                 <fileNamePattern>${LOG_PATH}/quick/${ZONE}-${APP_NAME}-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
 94 
 95                 <!-- 除按日志記錄之外,還配置了日志文件不能超過10M,若超過10M,日志文件會以索引0開始,
 96                 命名日志文件,例如log-error-2013-12-21.0.log -->
 97                 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 98                     <maxFileSize>10MB</maxFileSize>
 99                 </timeBasedFileNamingAndTriggeringPolicy>
100             </rollingPolicy>
101 
102             <!-- 追加方式記錄日志 -->
103             <append>true</append>
104 
105             <!-- 日志文件的格式 -->
106             <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
107                 <pattern>${FILE_LOG_PATTERN}</pattern>
108                 <charset>utf-8</charset>
109             </encoder>
110 
111             <!-- 此日志文件只記錄error級別的 -->
112             <filter class="ch.qos.logback.classic.filter.LevelFilter">
113                 <level>error</level>
114                 <onMatch>ACCEPT</onMatch>
115                 <onMismatch>DENY</onMismatch>
116             </filter>
117         </appender>
118 
119         <!-- 日志記錄器,日期滾動記錄 -->
120         <appender name="FILE_ALL" class="ch.qos.logback.core.rolling.RollingFileAppender">
121 
122             <!-- 正在記錄的日志文件的路徑及文件名 -->
123             <file>${LOG_PATH}/quick/${ZONE}-${APP_NAME}-log-all.log</file>
124 
125             <!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
126             <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
127 
128                 <!-- 歸檔的日志文件的路徑,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
129                 <fileNamePattern>${LOG_PATH}/quick/${ZONE}-${APP_NAME}-all-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
130 
131                 <!-- 除按日志記錄之外,還配置了日志文件不能超過10M,若超過10M,日志文件會以索引0開始,
132                 命名日志文件,例如log-error-2013-12-21.0.log -->
133                 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
134                     <maxFileSize>10MB</maxFileSize>
135                 </timeBasedFileNamingAndTriggeringPolicy>
136             </rollingPolicy>
137 
138             <!-- 追加方式記錄日志 -->
139             <append>true</append>
140 
141             <!-- 日志文件的格式 -->
142             <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
143                 <pattern>${FILE_LOG_PATTERN}</pattern>
144                 <charset>utf-8</charset>
145             </encoder>
146         </appender>
147 
148         <!-- 日志記錄器,日期滾動記錄 紀錄TAM日志-->
149         <appender name="FILE_TAM" class="ch.qos.logback.core.rolling.RollingFileAppender">
150 
151             <!-- 正在記錄的日志文件的路徑及文件名 -->
152             <file>${LOG_PATH}/quick/${ZONE}-${APP_NAME}-log-tam.log</file>
153 
154             <!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
155             <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
156 
157                 <!-- 歸檔的日志文件的路徑,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
158                 <fileNamePattern>${LOG_PATH}/quick/${ZONE}-${APP_NAME}-tam-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
159 
160                 <!-- 除按日志記錄之外,還配置了日志文件不能超過10M,若超過10M,日志文件會以索引0開始,
161                 命名日志文件,例如log-error-2013-12-21.0.log -->
162                 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
163                     <maxFileSize>10MB</maxFileSize>
164                 </timeBasedFileNamingAndTriggeringPolicy>
165             </rollingPolicy>
166 
167             <!-- 追加方式記錄日志 -->
168             <append>true</append>
169 
170             <!-- 日志文件的格式 -->
171             <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
172                 <pattern>${FILE_LOG_PATTERN}</pattern>
173                 <charset>utf-8</charset>
174             </encoder>
175             <!-- 此日志文件只記錄error級別的 -->
176             <filter class="ch.qos.logback.classic.filter.LevelFilter">
177                 <level>error</level>
178                 <onMatch>ACCEPT</onMatch>
179                 <onMismatch>DENY</onMismatch>
180             </filter>
181         </appender>
182 
183         <!-- 日志記錄器,日期滾動記錄 紀錄AUDITLOG日志-->
184         <appender name="FILE_AUDIT" class="ch.qos.logback.core.rolling.RollingFileAppender">
185 
186             <!-- 正在記錄的日志文件的路徑及文件名 -->
187             <file>${LOG_PATH}/auditlog/${ZONE}-${APP_NAME}-log-auditLog.log</file>
188 
189             <!-- 日志記錄器的滾動策略,按日期,按大小記錄 -->
190             <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
191 
192                 <!-- 歸檔的日志文件的路徑,%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
193                 <fileNamePattern>${LOG_PATH}/auditlog/${ZONE}-${APP_NAME}-auditlog-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
194 
195                 <!-- 除按日志記錄之外,還配置了日志文件不能超過10M,若超過10M,日志文件會以索引0開始,
196                 命名日志文件,例如log-error-2013-12-21.0.log -->
197                 <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
198                     <maxFileSize>10MB</maxFileSize>
199                 </timeBasedFileNamingAndTriggeringPolicy>
200             </rollingPolicy>
201 
202             <!-- 追加方式記錄日志 -->
203             <append>true</append>
204 
205             <!-- 日志文件的格式 -->
206             <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
207                 <pattern>${FILE_LOG_PATTERN}</pattern>
208                 <charset>utf-8</charset>
209             </encoder>
210             <!-- 此日志文件只記錄info級別的 -->
211             <filter class="ch.qos.logback.classic.filter.LevelFilter">
212                 <level>info</level>
213                 <onMatch>ACCEPT</onMatch>
214                 <onMismatch>DENY</onMismatch>
215             </filter>
216         </appender>
217 
218         <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
219             <destination>${LOGSTASH_URL}</destination>
220             <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" />
221         </appender>
222 
223 
224         <!--記錄到文件時,記錄兩類一類是error日志,一個是所有日志-->
225         <root level="warn">
226             <appender-ref ref="STDOUT"/>
227             <appender-ref ref="FILE_ERROR"/>
228             <appender-ref ref="FILE_ALL"/>
229         </root>
230 
231         <logger name="com.myproject" level="info"/>
232         <!--ShardingSphere打印sql用-->
233         <logger name="ShardingSphere-SQL" level="info"/>
234         <!--p6spy打印sql-->
235         <logger name="p6spy" level="info"/>
236         <!--屏蔽getRowIdLifetime未實作警告-->
237         <logger name="com.zaxxer.hikari.pool.ProxyConnection" level="error"/>
238     </springProfile>
239 
240 </configuration>

5.集成結果

 

 

 通過以上日志觀察發現已經實現了業務層面讀寫分離和讀庫的輪詢負載策略

 

 

 通過以上日志發現已經實現了線上環境的完整sql記錄,至此已達到預期效果,集成完畢

6.問題總結

  1.從數據層方面shardingsphere4並沒有實現主從庫的數據同步,在其他方案的數據同步過程中主從數據不一致導致的數據差異是否滿足應用場景還需具體評估.

  2.本實例數據庫采用postgres,目前最新版本的postgres數據庫驅動也沒有實現getRowIdLifetime()方法,shardingsphere4緩存數據源元數據的時候會去調用該方法,

驅動程序會拋出一個方法未實作的異常從下面代碼可見框架捕獲后不做處理並緩存該項為UNSUPPORTED,但是因為實例集成hikari連接池,hikar的ProxyConnection類會拋出一個一個警告如下圖二,看起來像是項目啟動報錯,但實際並不影響,程序運行,因此在輸出日志中將項屏蔽,具體配置在上面logback中

 

警告:

 

 

 

 

 3.logback的配置中root節點默認開啟warm級別日志,要想支撐 shardingsphere 和p6spy記錄sql需要單獨配置相應節點,開放對應日志級別,因 shardingsphere 打印出的不完整sql,除了查看數據庫路由外並沒有太大用處,而本項目當前並不關心數據庫路由,因此將對應配置項設為false,並集成p6spy完成完整的sql記錄

4.配置項中的數據庫url連接項名稱視具體連接池可能會有不同,本實例用連接池該名為jdbc-url,有些連接池叫url

7.部分源碼分析

 

該主鍵的入口類,實現了EnvironmentAware接口,在DataSoureAutoConfiguration之前被執行對dataSource經常了包裝處理用於支撐該框架的功能,下圖為datasource實例化過程,該方法的第一個入參dataSourceClassName為配置項的type所以對連接池的配置項需要和type放在同一級,如文章開始配置項所示.

 

 本實例只關心主從分離,其他源碼部分相關類:

 

 

以上,為全部內容,后期發現問題再做補充.


免責聲明!

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



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