Rumah  >  Artikel  >  pembangunan bahagian belakang  >  io.Salin tamat masa apabila keepalive dilumpuhkan

io.Salin tamat masa apabila keepalive dilumpuhkan

PHPz
PHPzke hadapan
2024-02-13 21:36:081156semak imbas

禁用 keepalive 时 io.Copy 超时

editor php Yuzai hari ini akan memperkenalkan kepada anda masalah tentang "io.Copy timeout when keepalive is disabled". Apabila menggunakan fungsi io.Copy dalam bahasa Go untuk penghantaran data, jika keepalive dilumpuhkan, tamat masa penghantaran mungkin berlaku. Masalah ini mungkin menyebabkan beberapa masalah kepada pembangun, jadi kita perlu mengetahui beberapa penyelesaian untuk mengelakkan masalah ini daripada berlaku. Mari kita lihat bagaimana untuk menyelesaikan masalah ini!

Kandungan soalan

Apabila saya melumpuhkan linux keepalive

sudo sysctl -w net.ipv4.tcp_keepalive_probes=0

Dan jalankan kod berikut

package main

import (
    "fmt"
    "io"
    "net"
    "os"
    "sync"
    "time"
)

func main() {
    go func() {
        listen, err := net.Listen("tcp", "127.0.0.1:9390")
        if err != nil {
            fmt.Printf("net listen fail, reason: [%s]\n", err.Error())
            os.Exit(1)
        }
        defer listen.Close()

        for {
            conn, err := listen.Accept()
            if err != nil {
                fmt.Printf("net accept fail, reason: [%s]\n", err.Error())
                continue
            }

            _, err = io.Copy(conn, conn)
            if err != nil {
                fmt.Printf("net Copy fail, reason: [%s]\n", err.Error())
                continue
            }
            conn.Close()
        }
    }()

    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        for {
            time.Sleep(1 * time.Second)
            tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:9390")
            fmt.Println("tcp client resolve success: ", tcpAddr.String())
            tcpConn, err := net.DialTCP("tcp", nil, tcpAddr)
            if err != nil {
                fmt.Println("tcp connect fail: ", err.Error())
                return
            }

            time.Sleep(100 * time.Second)
            tcpConn.Close()
            fmt.Println("tcp end")
        }
    }()

    wg.Wait()

}

io.Copy akan mengembalikan "splice: sambungan tamat masa"

Jika saya mendayakan keepalive

sudo sysctl -w net.ipv4.tcp_keepalive_probes=3

io.Copy sudah memadai

Saya mencuba klien tcp untuk menghantar paket pada selang 1 saat dan melumpuhkan tcp_keepalive, itu juga berkesan.

Saya menulis kod lain untuk menggantikan io.Copy

            buf := make([]byte, 10)
            for {
                conn.SetReadDeadline(time.Now().Add(30 * time.Second))
                n, err := conn.Read(buf)
                if err != nil {
                    fmt.Println("read fail: ", err.Error())
                    break
                }

                _, err = conn.Write(buf[:n])
                if err != nil {
                    fmt.Println("write fail: ", err.Error())
                    break
                }
            }
            conn.Close()

Baca tamat masa selepas 15 saat, tidak berfungsi selama 30 saat

Mengapa ini berlaku?

Penyelesaian

Jawapan: Apabila "kernel tcp stack" menggunakan keepalive untuk mengesan rangkaian, apabila "kernel tcp stack" perlu menghantar keepalive, net.ipv4.tcp_keepalive_probes = 0 akan tamat masa

Atas ialah kandungan terperinci io.Salin tamat masa apabila keepalive dilumpuhkan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam