跳轉到

tapio-core 日誌判讀

啟動順序

以下各節依時序排列。

等待期交所盤前檔

core 啟動後等待 fetcher 下載完成。若 core 卡住,最後一行通常是:

[main] Starting TAIFEX File Registry
[TaifexFileRegistry] dayDir=.../taifex/YYYYMMDD/ configuredSysTypes=10,20,11,21

出現以下 log 才代表盤前檔載入完成,core 繼續啟動:

[TaifexFileRegistry] bootstrap core complete for all configured sysTypes

載入交易帳號

[loadUserSessions] session created for investorAcc(XXXXXXX)
...
[loadUserSessions] load N user sessions, reportPool capacity 500000

load N user sessions 是最終小計。若預期帳號未出現,代表該帳號設定檔未載入或格式有誤。

低延遲配置

應出現以下兩行,代表 CPU 綁定與記憶體鎖定均已生效:

[pinThreadToCpu] Pinned NetThread to CPU Y
[main] mlockall: all pages locked into RAM

CalcThread 預設 calc_thread_cpu = -1(不綁定),由 kernel scheduler 與 OS / helper threads 共用未隔離核心,因此 log 不會出現 Pinned CalcThread。任一行缺失代表對應配置未套用,可能影響效能:

  • NetThread 未綁 CPU → 檢查 Tapio.tomlnet_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,在時間窗口外啟動時不會進入此階段,而是顯示:

[checkConnection] systemType(11) sessionId(154) outside active window, marking Inactive

到達啟用時間後自動恢復:

[checkConnection] systemType(11) sessionId(154) inside active window, resuming connection

接著重新走 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_typesession_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。

解法

  1. 確認 Tapio.toml 中每個交易的 system_type 都填了 session_id;缺值用 tapio-p12-sessionid 取得(見 Tapio.toml — session_id(必填))。

  2. 確認 [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 相符:

[gateway]
interface_name = '<NIC 名稱,例如 enp3s0>'
host           = '<監聽位址,通常為 0.0.0.0>'
port           = <監聽 port>

TMP log 出現 DNS resolution failed for '...', will retry after 30s

原因:DNS 查詢失敗,常見原因:

  • 內部 DNS 伺服器尚未啟動(開機順序問題)
  • TMP.toml[system].nameservers 填錯 IP

解法

# 確認 DNS 伺服器可達(指定 nameservers 中的 IP)
dig @<nameserver-ip> f002000.test.session152.tmp.opt.taifex

若 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 後斷線

原因:主機時間與交易所時間偏差過大,交易所主動切斷連線。

解法

# 確認目前偏差
chronyc tracking

# 立即強制對時(step,不等待漸進調整)
sudo chronyc makestep

預防:在 crontab 加入每日開盤前強制對時,例如:

# 每天 08:30 強制對時
30 8 * * 1-5 /usr/bin/chronyc makestep

確認 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 找客戶端對應人問。