tapio-core 日誌判讀¶
啟動順序¶
以下各節依時序排列。
等待期交所盤前檔¶
core 啟動後等待 fetcher 下載完成。若 core 卡住,最後一行通常是:
[main] Starting TAIFEX File Registry
[TaifexFileRegistry] dayDir=.../taifex/YYYYMMDD/ configuredSysTypes=10,20,11,21
出現以下 log 才代表盤前檔載入完成,core 繼續啟動:
載入交易帳號¶
[loadUserSessions] session created for investorAcc(XXXXXXX)
...
[loadUserSessions] load N user sessions, reportPool capacity 500000
load N user sessions 是最終小計。若預期帳號未出現,代表該帳號設定檔未載入或格式有誤。
低延遲配置¶
應出現以下兩行,代表 CPU 綁定與記憶體鎖定均已生效:
CalcThread 預設 calc_thread_cpu = -1(不綁定),由 kernel scheduler 與 OS / helper threads 共用未隔離核心,因此 log 不會出現 Pinned CalcThread。任一行缺失代表對應配置未套用,可能影響效能:
NetThread未綁 CPU → 檢查Tapio.toml的net_thread_cpu是否對應isolcpus隔離核mlockall未出現(僅出現 warning)→ 非致命,但記憶體頁面可能被 swap 出去,延遲穩定性下降
TMP 連線¶
依序出現以下四個階段代表連線正常。
階段 1:Session 對應
[TmpClientSession] systemType(10) sessionId(152) ... recovery last msg seq num (exchange) = 0
[TmpClientConnection] [init] systemType(10) sessionId(152) interface(10.x.x.x) local_port(40152)
每個 systemType 都應出現一對,代表從 socket port 找到對應 session ID。
階段 2:DNS 查詢與連線
[reconnect] systemType(10) sessionId(152) ... submit DNS query for '...' (gen=1)
[pollDnsSlot] systemType(10) sessionId(152) ... DNS '...' -> 192.168.x.x, connecting to 192.168.x.x:xxxxx...
[onConnected] systemType(10) sessionId(152) connected
若設有 active window,在時間窗口外啟動時不會進入此階段,而是顯示:
到達啟用時間後自動恢復:
接著重新走 DNS 查詢與連線流程。
階段 3:握手(L30/L40/L50)
[handleL30] systemType(10) sessionId(152) ...
[sendL40] systemType(10) sessionId(152) requestStartSeq(0) ...
[handleL50] systemType(10) sessionId(152) maxFlowCtrlCnt=16 heartBtInt=30
L50 出現代表握手完成,進入正常工作狀態。
階段 4:流程群組訂閱
[sendR11] systemType(10) sessionId(152) subscribe status changes of flow group X
[handleR12] systemType(10) sessionId(152) flowGroup(X) status(Open) enabled(true)
每個 flow group 都應回報 status(Open) enabled(true)。若某 flow group 為 Closed,對應商品類型的委託將被拒絕。
若啟動後 TMP 未連上,依上述四個階段逐一確認卡在哪個步驟。
關機序列¶
tapioctl stop 後約 3–5 秒完成,log 依序出現:
[shutdownCoordinator] shutdown: flag set, draining for 3s before exit
[shutdownCoordinator] shutdown: stopping gRPC admin server
[shutdownCoordinator] shutdown: joining CalcThread
[shutdownCoordinator] shutdown: stopping AsyncNameResolver helper
[shutdownCoordinator] shutdown: stopping QuoteSharedMemory updater
[shutdownCoordinator] shutdown: fsync + close FileStorage writers
[shutdownCoordinator] shutdown: releasing NetThread from io.run()
[main] Terminating...
若超過 10 秒仍未到 Terminating...,確認卡在哪一行後再決定是否 kill -9。
常見異常¶
完全沒有 TMP 連線相關 log¶
原因:core 已不再讀 P12(sessionId 改由 [trade.socket_ports] 的 session_id 提供,見 Tapio.toml)。看不到某子系統的 TMP 連線 log,現在只有兩種情況:
- 該
system_type缺session_id:core 啟動時直接exit(-1),daemon 根本沒起來。這是大聲失敗,log 末尾會有 critical:
[critical] no session_id configured for system_type 20 in [trade.socket_ports]; run tapio-p12-sessionid to extract it
- 該
system_type根本沒列在socket_ports:不會為它建連線(屬設定遺漏,非錯誤)。
舊版「interface_addr 填錯 → P12 三欄比對 miss → 連線靜默不建立、無任何 log」的路徑已移除。現在無論 session_id 為何(含合法的 0)都會建立連線物件,interface_addr 只用於 socket bind;填錯不再靜默,而是在連線階段出現 connect 失敗 log。
解法:
-
確認
Tapio.toml中每個交易的system_type都填了session_id;缺值用tapio-p12-sessionid取得(見 Tapio.toml — session_id(必填))。 -
確認
[trade]的interface_name/interface_addr對應實際連往交易所的網路介面:
[trade]
connection_mode = 'direct'
interface_name = '<NIC 名稱,例如 enp1s0>'
interface_addr = '<該 NIC 的 IP>'
interface_addr 是否與 P12 登錄一致,由 tapio-p12-sessionid 在取值時驗證——比對 miss 會印 no P12 row matches fcmNo=... ip=... port=...。若 IP 未登錄,須向交易所申請更新。
P14 empty for systemType(XX) / P14.XX entirely missing¶
該子系統的 P14 部位限制檔缺失。系統仍會繼續啟動,但受影響子系統的所有委託會被拒絕(GW_MISSING_POSITION_LIMIT)。
常見子系統對應:
| systemType | 對應 |
|---|---|
| 10 | 日盤期貨 |
| 11 | 夜盤期貨 |
| 20 | 日盤選擇權 |
| 21 | 夜盤選擇權 |
影響評估:缺哪個 systemType 的 P14,該時段就無法交易。日盤缺檔須立即處理;僅夜盤缺檔則在夜盤開盤前補齊即可。
解法:查 tapio-taifex-fetcher log 確認 P14 下載失敗原因,排除後重新觸發下載並重啟。
啟動 log 出現 mlockall failed¶
非致命警告,系統仍繼續啟動。記憶體頁面無法鎖進 RAM,可忽略,但延遲穩定性可能稍微下降。
[critical] bind: listenSock_: Cannot assign requested address 後 crash¶
原因:客戶端監聽介面設定錯誤,bind 失敗,程式直接 crash。
解法:確認 TMP.toml 中以下三個值正確且與實際 NIC 相符:
TMP log 出現 DNS resolution failed for '...', will retry after 30s¶
原因:DNS 查詢失敗,常見原因:
- 內部 DNS 伺服器尚未啟動(開機順序問題)
TMP.toml的[system].nameservers填錯 IP
解法:
若 IP 填錯,修正 [system].nameservers 後重啟。排除後 Tapio 會在 30 秒後自動重試,無需手動重啟。
TMP log 出現 Invalid key value. Please check the password in TMP.toml.¶
原因:TMP 登入密碼錯誤。
解法:確認 TMP.toml 中 [broker].password 與交易所核發的相符,修正後重啟。
TMP log 出現 The difference between exchange and us is N seconds 後斷線¶
原因:主機時間與交易所時間偏差過大,交易所主動切斷連線。
解法:
預防:在 crontab 加入每日開盤前強制對時,例如:
確認 chronyd 服務有啟用(systemctl is-enabled chronyd);若 NTP 服務未跑,chronyc makestep 無效。
core log 出現 kicking old connection connId(...) for investorAcno(...)¶
說明:每帳號限一條 TCP 連線。新連線登入時,舊連線會被踢掉,新連線正常建立。此為 INFO 等級,非錯誤。
若此 log 頻繁出現,代表客戶端 SDK 重連邏輯有 race window,重試間隔過短導致連線反覆重建。
處理:
- 確認客戶端只開一條連線
- 若用 NAT,多客戶端共用 source IP 不影響(Tapio 認 investorAcno 不認 IP)
- 頻繁出現 → 該客戶端 SDK 重試太快,請客戶調整重連間隔
core log 出現 seq mismatch (...) != (...)¶
說明:客戶端程式的 seq 編制有誤,非 Tapio 問題。可忽略,請客戶檢查其 SDK 或程式的 seq 遞增邏輯。
啟動 log 出現 skip_source_ip_check=true: source IP binding disabled¶
說明:登入來源 IP 檢測已被關閉。測試環境可接受;正式環境應啟用來源 IP 檢測,若正式機出現此警告須確認設定是否正確。
客戶端連線數異常突增¶
解法:
# 看當前連線數
ss -tnp | grep -c ":<tapio-port>"
# 看每個 source IP 的連線數
ss -tn state established sport = :<tapio-port> | awk 'NR>1 {print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn
異常 source 找客戶端對應人問。