背景說明和問題描述
自從數據庫遷移到其它機房后,應用經常反饋有會話超時的問題(而且會出現900多秒才返回超時報錯的現象),雖然量很小,但也影響用戶感知
而未割接的數據庫訪問一直無超時現象
兩者的區別:異機房訪問跨防火牆,同機房訪問不涉及防火牆
異常日志
2020-02-04T20:43:28.882055+08:00 Fatal NI connect error 12170. VERSION INFORMATION: TNS for Linux: Version 12.2.0.1.0 - Production Oracle Bequeath NT Protocol Adapter for Linux: Version 12.2.0.1.0 - Production TCP/IP NT Protocol Adapter for Linux: Version 12.2.0.1.0 - Production Time: 04-FEB-2020 20:43:28 Tracing not turned on. Tns error struct: ns main err code: 12535 TNS-12535: TNS:operation timed out ns secondary err code: 12560 nt main err code: 505 TNS-00505: Operation timed out nt secondary err code: 110 nt OS err code: 0 Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=*.*.*.*)(PORT=37852))
分析過程
先說下思路,涉及數據庫出現訪問超時,無非考慮的幾點
1、網絡異常(防火牆層面)
2、數據庫負載高,建立會話響應超時(數據庫層面)
3、主機會話異常(主機層面)
防火牆層面:
因為是遷移到異機房后出現的超時問題,流量經過防火牆是唯一的變數,所以第一時間想到的是防火牆問題導致
從目前架構看,跨機房后涉及兩種型號的防火牆:華為防火牆,華三防火牆
防火牆層對建立的會話有過期策略,華為防火牆默認20分鍾,華三防火牆默認1小時
也就是說,如果業務在訪問數據庫時,如果會話停留超過20分鍾無流量交互,防火牆會主動將會話斷開
這是防火牆層面的超時機制,通過修改防火牆會話過期策略,可以解決超時問題
此類會話在主機層面是以非正常TCP策略斷開,屬於異常會話,而主機有針對異常會話的回收機制
主機層面:
主機層面提供針對會話存活的探測機制:tcp_keepalive
[root ~]# sysctl -a | grep keepalive(默認配置) net.ipv4.tcp_keepalive_time = 7200 #代表每隔7200s發起ack探測 net.ipv4.tcp_keepalive_probes = 9 #探測頻次,如果超過9次對方無ack響應,第10次發送rst net.ipv4.tcp_keepalive_intvl = 75 #每次相隔75s發送一次ack
當防火牆將會話過期后,主機在2個小時后會按時發起ack探測包
而在防火牆會話沒有過期時,假設net.ipv4.tcp_keepalive_time=960,則主機每16分鍾發送一次ack探測包,防火牆會話過期倒計時會重置
針對兩種結果的得出的結論:
1)如果net.ipv4.tcp_keepalive_time >= 防火牆會話過期時間,會話會正常被防火牆過期,keepalive探測發現后,會正常中斷進程,回收資源
2)如果net.ipv4.tcp_keepalive_time < 防火牆會話過期時間,keepalive機制正常發送ack探測包,防火牆會話過期倒計時會被重置,會話一直處於active狀態
數據庫層面:
提取問題時間點的awr和主機性能報告分析,並未出現負載高峰
涉及監聽鏈接超時設置雖然默認值,但從應用反饋的情況來看,業務是dblink訪問的(長鏈接),跟此參數影響不大
從上面防火牆和主機分析來看,是由於防火牆會話過期導致,針對這種情況,Oracle數據庫也提供了一種會話存活探測機制:DCD(dead connection detection)
具體設置方法:
vi $ORACLE_HOME/network/admin/sqlnet.ora SQLNET.EXPIRE_TIME=10
#代表的意思是會話處於inactive 10分鍾后,服務端會發送10字節的小包到客戶端,進行存活探測,如果無響應,則會話關閉,資源回收
需要注意的是:
1)如果SQLNET.EXPIRE_TIME設置時間小於防火牆會話超時限制,防火牆會話會一直保持active狀態,不會發生過期
2)如果SQLNET.EXPIRE_TIME設置時間大於防火牆會話超時限制,防火牆會話過期就會正常發生,此時數據庫實例會探測到會話異常,並且正常關閉鏈接,回收資源
針對應用經常出現900多s才返回超時報錯日志的問題:
該問題是由系統參數tcp_retries2的設置決定的
該參數表示在丟棄激活(已建立通訊狀況)的TCP連接之前﹐需要進行多少次重試。默認值為15
該參數的值是根據RTO值來的,一般響應超時時間為retransmit N次=(N+1)th RTO,默認15次,需要924s
在系統優化時,該參數建議設置為5
總結
為了避免數據庫跨防火牆訪問出現超時,可以做如下優化:
1、調整防火牆會話過期策略,明確來源IP,目標IP,目標端口,避免范圍過大,在線會話過多,影響防火牆性能
2、主機keepalive合理設置,如果防火牆會話過期策略不能調整,建議設置小於防火牆會話超時時間
3、數據庫啟用DCD策略,設置值小於防火牆會話超時時間