【原创】packetbeat 之“request-response 错误关联”问题
2019獨角獸企業重金招聘Python工程師標準>>>
問題描述
在基于 packetbeat 分析 redis 協議時發現,在某些情況下,基于 request-response 關聯出的 transaction 信息是錯誤的,示例如下:
responsetime(947201 microseconds) ==> No.<1> ---- {"@timestamp":"2016-12-29T07:21:24.657Z","beat":{"hostname":"xg-mesos-39","name":"xg-mesos-39","version":"6.0.0-alpha1"},"bytes_in":14,"bytes_out":40,"client_ip":"10.0.242.43","client_port":7125,"client_proc":"","client_server":"","ip":"10.0.246.114","method":"PING","port":48877,"proc":"","query":"PING","redis":{"return_value":"[REPLCONF, ACK, 5372098]"},"resource":"","responsetime":947201,"server":"","status":"OK","type":"redis"}從上述信息可以明顯看出,當前 transaction 中關聯的 request 為 PING 命令,response 為 [REPLCONF, ACK, 5372098] 命令;
注意:因為 transaction 的構建是基于 TCP 連接的,因此不會出現將不同 TCP 連接上的請求應答錯亂匹配的問題;
問題原因
上面錯誤在于,將 PING 和 [REPLCONF, ACK, 5372098] 進行了關聯,而這兩者明顯不是對應關系;
通過梳理 Redis 協議相關資料可以知道:
-
PING 的使用
-
[客戶端-服務器] 使用客戶端向 Redis 服務器發送一個 PING ,如果服務器運作正常的話,會返回一個 PONG 。通常用于測試與服務器的連接是否仍然生效,或者用于測量延遲值;
-
[Sentinel] 在默認情況下,Sentinel 會以每秒一次的頻率向所有與它創建了命令連接的實例(包括主服務器、從服務器、其他 Sentinel 在內)發送 PING 命令,并通過實例返回的 PING 命令回復(有效回復為 +PONG/-LOADING/-MASTERDOWN)來判斷實例是否在線(主觀下線狀態檢測);
-
[主從復制] 當從服務器成為主服務器的客戶端后,做的第一件事就是向主服務器發送一個 PING 命令;兩個作用:a) 檢查套接字的讀寫狀態是否正常;b) 檢查主服務器能否正常處理命令請求;只有從服務器在規定時間內讀取到主服務器返回的 PONG 才算成功;
-
[主從復制] Slaves 以預定義的周期向 server 發送 PING;該周期通過 repl_ping_slave_period 選項進行配置,默認為 10 秒; The original replication protocol was vulnerable to network/Internet outages where the master detects the outage and closes the connection, but the slave does not. The slave thinks the connection is still open and the master simply has no updates to send (low traffic or no traffic). So the slave never disconnects and re-connects to restart the replication. I know this very well. I have some v2.0.x Redis instances that replicate across 3,000 miles and once or twice a month this problem occurs. Adding PING to the replication protocol solved that. The slave now detects the connection problem when the PING replies stop coming from the master. The slave can close its end of the connection and re-connect again.
-
[集群] 集群里的每個節點默認每隔一秒鐘就會從已知節點列表中隨機選出五個節點,然后對這五個節點中最長時間沒有發送過 PING 消息的節點發送 PING 消息,以此來檢測被選中的節點是否在線;除此之外,如果節點 A 最后一次收到節點 B 發送的 PONG 消息的時間,距離當前時間已經超過了節點 A 的 cluster-node-timeout 選項設置時長的一半,那么節點 A 也會向節點 B 發送 PING 消息,這可以防止節點 A 因為長時間沒有隨機選中節點 B 作為 PING 消息的發送對象,而導致對節點 B 的信息更新滯后;
-
[REPLCONF, ACK, <replication_offset>] 的使用
在命令傳播階段,從服務器默認會以每秒一次的頻率,向主服務器發送該命令;該命令的作用為:a) 檢測主從服務器的網絡連接狀態;b) 輔助實現 min-slaves 選項;c) 檢測命令丟失;
具體抓包數據如下
*3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *3 $8 REPLCONF $3 ACK $11 81234009046 *1 $4 PING *3 $8 REPLCONF $3 ACK $11 81234009060可以看到,在一個 10s 的抓包周期中,出現了 10 個 [REPLCONF, ACK, xxxx] 和 1 個 PING ;可以確定,該 PING 為基于 repl_ping_slave_period 選項的保活 PING ;
解決辦法
可以確認的是,出現 [REPLCONF, ACK, xxx] 命令的連接一定是 master 和 slave 進行通信的連接;因此,一種簡單的解決辦法就是針對該命令進行過濾,從而避免 transaction 的構建中出現 [REPLCONF, ACK, xxx],但這種方式可能會導致統計數據輸出時,多出一些 unmatched 的內容;一種高級的解決辦法就是在檢測出該命令后,直接將該命令屬于的 TCP 流徹底剔除;
轉載于:https://my.oschina.net/moooofly/blog/849634
總結
以上是生活随笔為你收集整理的【原创】packetbeat 之“request-response 错误关联”问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: git入门使用摘录
- 下一篇: 绝对定位元素设置水平居中