您好,登錄后才能下訂單哦!
1、用戶反饋同個ECS啟動了多個容器,其中一個容器無法與Anytunnel 100.64.0.1通信,TCP建聯失敗。不通的容器IP是172.16.0.13。其他能通的容器比如 172.16.0.15。
2、在Anytunnel 100.64.0.1的后端RS上抓包,發現有172.16.0.13 TCP 建聯成功的的記錄。說明有其他VPC也有用172.16.013地址來訪問,并且是通的。
PS:AnyTunnel地址指的是每個VPC中100.64.0.0/10內的地址,用于VPC中DNS、YUM、NTP、OSS或SLS等云服務中使用。簡單可以理解為在VPC下為了解決不同VPC內網互通的特殊的SLB。這個SLB能被同個Region下所有的VPC訪問。
排查過程
1、首先我們要確定VPC1下172.16.0.13的請求有沒有到達AnyTunnel后端RS上,最簡單的方法就是在172.16.0.13和后端RS上同時抓包進行分析。
客戶端和RS上抓包通過“tcp.analysis.retransmission”條件過濾出有問題的重傳報文,發都是SYN的重傳。
重傳報文數量都是7個,并且源端口一致,那么說明請求報文已經到達RS上,但是RS沒有響應SYN-ACK,導致TCP建聯失敗。
2、在RS上查看TCP計數發現:
netstat?-ts?|grep?SYNs??? 3631812?SYNs?to?LISTEN?sockets?dropped
有大量tcp syn包被丟棄,數值一直在增長,進一步說明是RS收到客戶端的SYN請求但是沒有響應。
為何RS沒有響應SYN請求分析
netstat中的計數統計,里面定義了TCP連接失敗統計,具體如下:
resets received for embryonic SYN_RECV sockets? ---syn_recv狀態下,收到非重傳的syn包,則返回reset
passive connections rejected because of time stamp ---開啟sysctl_tw_recycle,syn包相應連接的時間戳小于 路由中保存的時間戳;
failed connection attempts --- syn_recv狀態下,socket被關閉, 或者收到syn包(非重傳)
times the listen queue of a socket overflowed? ---收到三次握手ack包,accept隊列滿
SYNs to LISTEN sockets ignored ---收到三次握手ack包,因各種原因(包括accept隊列滿) 創建socket失敗
通過netstat -ts查看到passive connections rejected because of time stamp統計數值非常大,并且接近于SYNs to LISTEN sockets dropped的數量。
3631476?passive?connections?rejected?because?of?time?stamp
說明就是由于syn包相應連接的時間戳問題導致的。
于是再次分析RS的抓包文件:
報文序列 | 是否成功響應SYN | TimeStamp值 |
1 | 成功響應SYN | 2088983548 |
2 | 沒有響應SYN | 271344470 |
3 | 沒有響應SYN | 271345544 |
4 | 沒有響應SYN | 271346612 |
5 | 沒有響應SYN | 271348509 |
6 | 沒有響應SYN | 271351766 |
7 | 成功響應SYN | 2088993553 |
從抓包信息里可以看出,當后面的SYN報文的TimeStamp值小于前面成功響應的SYN報文的TimeStamp值,系統默認就會不響應該SYN請求。
通過上面分析,問題明顯和tcp timestmap有關,發現tcp_tw_recycle/tcp_timestamps都開啟的條件下,60秒內同一源ip主機的socket connect請求中的timestamp必須是遞增的。
源碼函數:tcp_v4_conn_request(),該函數是tcp層三次握手syn包的處理函數(服務端); ????源碼片段: ???????if?(tmp_opt.saw_tstamp?&& ????????????tcp_death_row.sysctl_tw_recycle?&& ????????????(dst?=?inet_csk_route_req(sk,?req))?!=?NULL?&& ????????????(peer?=?rt_get_peer((struct?rtable?*)dst))?!=?NULL?&& ????????????peer->v4daddr?==?saddr)?{ ????????????if?(get_seconds()?<?peer->tcp_ts_stamp?+?TCP_PAWS_MSL?&& ????????????????(s32)(peer->tcp_ts?-?req->ts_recent)?> ????????????????????????????TCP_PAWS_WINDOW)?{ ????????????????NET_INC_STATS_BH(sock_net(sk),?LINUX_MIB_PAWSPASSIVEREJECTED); ????????????????goto?drop_and_release; ????????????} ????????} ???????? tmp_opt.saw_tstamp:該socket支持tcp_timestamp sysctl_tw_recycle:系統開啟tcp_tw_recycle選項 TCP_PAWS_MSL:60s,該條件判斷表示該源ip的上次tcp通訊發生在60s內 TCP_PAWS_WINDOW:1,該條件判斷表示該源ip的上次tcp通訊的timestamp大于本次tcp
Tcp_timestamp 是 RFC1323 定義的優化選項,主要用于 TCP 連接中 RTT(Round Trip Time) 的計算,開啟 tcp_timestamp 有利于系統計算更加準確的 RTT,也就有利于 TCP 性能的提升。
tcp_tw_recycle?(Boolean;?default:?disabled;?since?Linux?2.4) ??????????????Enable?fast?recycling?of?TIME_WAIT?sockets.??Enabling?this?option?is?not?recommended?since?this?causes?problems?when?working?with?NAT?(Network?Address ??????????????Translation).
開啟tcp_tw_recycle會啟用tcp time_wait的快速回收,這個參數不建議在NAT環境中啟用,它會引起相關問題。
官方定義是在NAT環境中使用會引發問題,但是歸根結底就是多個客戶端使用同個地址訪問服務端會出現該問題。我們的問題符合該場景。
解決方案
有兩個方案可選:
客戶端關閉tcp_timestamps,將該值設置為0.
服務器端不要將tcp_tw_recycle字段和tcp_timestamps字段同時設為1?
由于客戶端掌握在客戶的手里,我們無法掌握到每個客戶端的配置,所以還是需要服務端進行配置。
因為在tcp timestamp關閉的條件下,開啟tcp_tw_recycle是不起作用的;而tcp timestamp可以獨立開啟并起作用。所以建議服務關閉tcp_tw_recycle.
服務端(RS端)關閉tcp_tw_recycle具體操作方法。
1、臨時關閉方法: echo?"0"?>?/proc/sys/net/ipv4/tcp_tw_recycle 2、永久關閉方法: 在?/etc/sysctl.conf?文件中添加?net.ipv4.tcp_tw_recycle?=?0 然后使用?sysctl?-p?命令讓配置文件生效
引伸
根據上面的原理,出現多個客戶端同時使用同一個IP訪問同一個服務端的場景要在服務端關閉tcp_tw_recycle。如以下場景:
1、同一個Client訪問四層私網SLB的同時,還有繞過SLB直接訪問SLB后端ECS
2、相同的ECS同時掛在多個四層SLB之后,并且同一個客戶端有同時或者連續訪問多個SLB
3、ECS通過公網地址,NAT網關和EIP直接提供服務的。因為由于目前IPV4地址枯竭,絕大部分的客戶端都是使用SNAT進行訪問。
附錄
參考:
http://blog.sina.com.cn/s/blog_781b0c850101pu2q.html
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。