今天是在博客園開園的第一天
一時間其實並不能想起來到底該寫什么文章,其實想寫的東西挺多
今天就以logid這個主題開始吧,網上寫這個的文章似乎不多,但是的確是在實際生產中相當重要的一個能力,也是容易被大多數新手程序員所忽視的。
logid:在我的定義里,logid是一個能夠代表一條請求唯一性的字段。完整請求包含請求到達、請求轉發、服務處理、數據存取等多個階段,logid在其中充當的就是一個定位標識,當然這個字段叫法可能不能可以是traceID或者其他XXID等等
以典型的php服務為例,整條請求軌跡可能包含下面的幾個組成部分:
client => 外層網關(四層負載均衡) => nginx集群(七層負載均衡) => 你自己服務的nginx => 業務日志 => rpc日志 => mysqlproxy => mysql
=> redisproxy => redis
=> 其他基礎服務(圖片服務\評論服務等等)
上面展示的是一個比較完善的請求轉發路徑,而這樣的長路徑上,任何一個位置都可能產生問題。大部分情況下,每個階段也都會打日志
如何把這些日志串聯起來、讓問題可追溯、請求可定位,這便是logid做的事情。
典型的使用場景例如:
案例一:業務可用性出現問題,如何排查問題出在哪里?
假設你自己的服務機器nginx出現了大量的499報錯,499錯誤源於客戶端主動斷開連接。
那么問題可能處在哪里?
- 客戶端的超時時間設置有問題,太短了(這個原因引起的499錯誤,只存在於上新服務。如果服務存在很久了,這個原因基本可以忽略)
- 客戶端和你之前的網絡故障,這也是一個常見的引起因素。(這個問題的定位可以把nginx_proc_time和upstream_time都打出來即可辨別)
- 極大的可能問題出在你的服務請求別人或者自己的機器負載過高導致的
今天主要討論第三種,如何定位?
關鍵是看這條請求從nginx => pfm => php執行 => rpc請求這些過程哪些步驟出現了問題
沒有logid的時候你怎么做?
nginx找到問題日志,根據get參數或者post參數去業務日志找,請求少的還好,如果大量重復請求呢?你是沒辦法精確定位到一個請求的
並且大部分rpc的日志不會打get參數,我們的rpc日志每秒百條,所以需要有一個線索,穿起來
logid就是扮演這個角色
nginx把請求上游的logid通過fastcgi帶給php,php通過$SERVER中取到,然后rpc框架和php代碼約定好從哪里取logid
done!下次再來問題,直接一步定位,不需要肉身來定位了
案例二: sql問題反查業務日志
假設某天DBA找到你說Proxy日志發現了大量的sql存在注入風險,並且拋給你一堆sql、來源IP和時間
一般如何處理?找到來源ip機器、找到對應時間的日志、翻譯sql中的關鍵字到你的日志關鍵字(人肉),這個步驟如果沒法對應起來,可能很困難
但是如果你們約定好了sql發出去的時候帶上logid字段,這個情況是不是迎刃而解?你只需要grep相應的logid便可以找到對應的,效率也會高很多
如何在發sql請求帶上logid?可以使用類似下面的sql語句,proxy完成sql日志打印
/*logid=xxx*/select count(1) from tableA
當然還有很多案例
logid存在的核心價值是讓每一個請求都可以被唯一定位!
具體logid的協議如何定制需要具體問題具體分析,但是意識上在遇到類似問題的時候應該想到,你的服務需要在日志中打印線索ID:logid來讓你的每一個請求可以被定位
當然前提是log打的充分、也要恰當