跨機房(跨防火牆)數據庫訪問超時問題分析TNS-12535、TNS-00505


背景說明和問題描述

自從數據庫遷移到其它機房后,應用經常反饋有會話超時的問題(而且會出現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策略,設置值小於防火牆會話超時時間


免責聲明!

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



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