pos機(jī)交易超時(shí),Go 驗(yàn)證 TCP SYN 超時(shí)重傳機(jī)制

 新聞資訊  |   2023-07-02 12:07  |  投稿人:pos機(jī)之家

網(wǎng)上有很多關(guān)于pos機(jī)交易超時(shí),Go 驗(yàn)證 TCP SYN 超時(shí)重傳機(jī)制的知識(shí),也有很多人為大家解答關(guān)于pos機(jī)交易超時(shí)的問題,今天pos機(jī)之家(www.rcqwhg.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來看下吧!

本文目錄一覽:

1、pos機(jī)交易超時(shí)

pos機(jī)交易超時(shí)

背景

最近寫了一個(gè)壓測代碼,測試一個(gè) http 接口,代碼大概是這個(gè)樣子,代碼跑在 Linux 機(jī)器上,內(nèi)核版本:3.10.107。

package mainimport ( "context" "fmt" "io/ioutil" "net/http" "time")func main() { for { time.Sleep(time.Millisecond * 10) cli := http.Client{ Timeout: 5 * time.Second, } req, err := http.NewRequestWithContext(context.Background(), "GET", "http://xxx.com", nil) if err != nil { fmt.Println(err) continue } now := time.Now() rsp, err := cli.Do(req) if err != nil { fmt.Printf("%v, cost:%v\", err, time.Since(now)) continue } body, err := ioutil.ReadAll(rsp.Body) defer rsp.Body.Close() if err != nil { fmt.Println(err) continue } fmt.Printf("len of body:%v", len(body)) }}預(yù)期 error

提供 http 服務(wù)的 server,在這樣的壓測條件下會(huì)來不及處理這么多的請(qǐng)求,因此會(huì)存在 5s 超時(shí)的情況。5s 超時(shí)的時(shí)候,cli.Do(req) 會(huì)返回下面的錯(cuò)誤信息。原因是 http.Client 經(jīng)歷 5s 沒有收到結(jié)果,context 到達(dá)了 Deadline。

context deadline exceeded (Client.Timeout exceeded while awaiting headers), cost:5.00031874s其他 error

在壓測過程中,還出現(xiàn)了其他的 error,并且數(shù)量要多于預(yù)期的 context deadline exceeded 錯(cuò)誤。這是錯(cuò)誤信息,錯(cuò)誤信息里隱去了 ip、port。

dial TCP ($ip):($port): connect: connection timed out, cost:3.017266219s

出現(xiàn)這個(gè)錯(cuò)誤的調(diào)用耗時(shí)只有 3s,但是在代碼中初始化 cli 的時(shí)候設(shè)置了 5s 的超時(shí),這是為什么呢?

分析

上面的 dial tcp 錯(cuò)誤顯示是發(fā)起 tcp 調(diào)用時(shí)出的錯(cuò),那就需要從 tcp 的方面進(jìn)行分析。

祖?zhèn)魅挝帐宙?zhèn)樓。

client 向 server 發(fā)起第一次握手的時(shí)候,會(huì)發(fā)送 SYN 信號(hào)。如果 client 等待了一個(gè)超時(shí)時(shí)間之后沒有收到 server 的 ACK,client 則會(huì)重試。如果重試之后還是等待超時(shí)了,就再重試。

在 Linux 中,client 重傳 SYN 的次數(shù)由內(nèi)核參數(shù) net.ipv4.tcp_syn_retries 控制,默認(rèn)為 6。

通過以下指令在壓測機(jī)器上查看 SYN 重傳次數(shù),可以看到壓測機(jī)器上發(fā) tcp 請(qǐng)求時(shí)只會(huì)超時(shí)重傳一次 SYN。

$: sysctl -a | grep tcp_syn_retriesnet.ipv4.tcp_syn_retries = 1

重傳間隔是怎么規(guī)定的呢?

SYN 重傳間隔存在過一個(gè) bug: kernel/git/torvalds/linux.git - Linux kernel source tree

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4d22f7d372f5769c6c0149e427ed6353e2dcfe61

在 bug 修復(fù)前,超時(shí)時(shí)間是由TCP_RTO_MIN這個(gè)參數(shù)計(jì)算的,該參數(shù)在內(nèi)核代碼/include/net/tcp.h中定義。

#define TCP_RTO_MIN ((unsigned(HZ/5))

bug 修復(fù)之后,超時(shí)時(shí)間由TCP_TIMEOUT_INIT計(jì)算,代碼地址:

https://elixir.bootlin.com/linux/v3.10.107/source/include/net/tcp.h#L136

#define TCP_TIMEOUT_INIT((unsigned(1*HZ)

這個(gè)值在RFC 6298中,定義為1秒。在RFC 1122中為3秒。這是最開始的超時(shí)等待時(shí)間,如果在這段時(shí)間內(nèi)沒有收到 ACK,超時(shí)等待時(shí)間按 2 的指數(shù)倍增長。如果重試次數(shù)為 6 次,那么 RFC 6298 的超時(shí)重傳間隔就是 1, 2, 4, 8, 16, 32;RFC 1122 中就是 3, 6, 9, 18, 36, 72。

通過壓測機(jī)器的內(nèi)核版本號(hào),查證源碼得到該機(jī)器的初始超時(shí)重傳時(shí)間為 1s。

那么這就解釋的通了,壓測機(jī)器 SYN 重傳次數(shù)為 1,所以 tcp 握手的時(shí)候第一次發(fā) SYN,等待了 1s 沒有收到 ACK,又重傳一次,等待 2s 也沒有收到 ACK,這樣總共耗時(shí)了 3s,就報(bào)了 dial tcp: connection timeout。

復(fù)現(xiàn)

接下來復(fù)現(xiàn)一下這種情況。

找一臺(tái)服務(wù)器,將 net.ipv4.tcp_syn_retries 設(shè)置為 1。通過編輯 /etc/sysctl.conf 文件實(shí)現(xiàn):

vim /etc/sysctl.confnet.ipv4.tcp_syn_retries = 1

在終端中:

$: iptables -A INPUT --protocol tcp --dport 5000 --syn -j DROP$: tcpdump -i lo -Ss0 -n src 127.0.0.1 and dst 127.0.0.1 and port 5000

開一個(gè)新終端:

$: date '+ %F %T'; telnet 127.0.0.1 5000; date '+ %F %T';

可以看到 tcpdump 中,只收到了兩次 SYN(16:50:20 和 16:50:21),并且兩次間隔為 1s。

而在新終端中,看到整個(gè)調(diào)用的耗時(shí)為 3s(16:50:20 - 16:50:23)。

總結(jié)

http 或 tcp 調(diào)用時(shí)的 dial tcp (ip):(port): connect: connection timed out 錯(cuò)誤是 SYN 的超時(shí)重傳機(jī)制引起的。如果遇到這種錯(cuò)誤,一方面需要考慮 server 可以處理請(qǐng)求的 QPS,另一方面也要檢查 client 端重傳相關(guān)參數(shù)的設(shè)置。

參考文獻(xiàn)

[1] 理解 timeout,這一篇就夠了 - poslua | ms2008 Blog

https://ms2008.github.io/2017/04/14/tcp-timeout/

[2] net.ipv4.tcp_syn_retries參數(shù)的含義_來自萬古的憂傷的博客-CSDN博客

https://blog.csdn.net/weixin_45413603/article/details/113891804

[3] [TCP] tcp連接SYN超時(shí)重傳次數(shù)和超時(shí)時(shí)間_陶士涵的菜地的技術(shù)博客_51CTO博客

https://blog.51cto.com/u_15274085/2919125

[4] 《關(guān)于TCP SYN包的超時(shí)與重傳》——那些你應(yīng)該知道的知識(shí)(四)_BBIE的博客-CSDN博客_syn重傳

https://blog.csdn.net/sinat_17736151/article/details/82804404

[5] SYN retransmits: Add new parameter to retransmits_timed_out()

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4d22f7d372f5769c6c0149e427ed6353e2dcfe61

[6] tcp.h - include/net/tcp.h - Linux source code (v3.10.107) - Bootlin

https://elixir.bootlin.com/linux/v3.10.107/source/include/net/tcp.h#L136

以上就是關(guān)于pos機(jī)交易超時(shí),Go 驗(yàn)證 TCP SYN 超時(shí)重傳機(jī)制的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于pos機(jī)交易超時(shí)的知識(shí),希望能夠幫助到大家!

轉(zhuǎn)發(fā)請(qǐng)帶上網(wǎng)址:http://www.rcqwhg.com/news/76560.html

你可能會(huì)喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 babsan@163.com 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。