Я использую Go TCP Client для подключения к нашему Go TCP Server.
Я могу подключиться к серверу и правильно выполнить команды, но время от времени мой TCP-клиент сообщает о необычно большом количестве последовательных ошибок подключения TCP при попытке подключения к нашему TCP-серверу или при отправке сообщения. после подключения:
dial tcp kubernetes_node_ip:exposed_kubernetes_port:
connectex: A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because connected
host has failed to respond.
read tcp unfamiliar_ip:unfamiliar_port->kubernetes_node_ip:exposed_kubernetes_port
wsarecv: A connection attempt failed because the connected party did not properly
respond after a period of time, or established connection failed because connected
host has failed to respond.
Я говорю «необычно высокий», потому что я предполагаю, что число раз, когда эти ошибки происходят, должно быть очень минимальным (около 5 или меньше в течение часа). Обратите внимание, что я не исключаю, что это может быть вызвано нестабильностью соединения, так как я также заметил, что можно выполнять несколько команд подряд без каких-либо ошибок.
Однако я все еще собираюсь опубликовать свой код на случай, если я что-то не так делаю.
Ниже приведен код, который мой TCP-клиент использует для подключения к нашему серверу:
serverAddress, err := net.ResolveTCPAddr("tcp", kubernetes_ip+":"+kubernetes_port)
if err != nil {
fmt.Println(err)
return
}
// Never stop asking for commands from the user.
for {
// Connect to the server.
serverConnection, err := net.DialTCP("tcp", nil, serverAddress)
if err != nil {
fmt.Println(err)
continue
}
defer serverConnection.Close()
// Added to prevent connection timeout errors, but doesn't seem to be helping
// because said errors happen within just 1 or 2 minutes.
err = serverConnection.SetDeadline(time.Now().Add(10 * time.Minute))
if err != nil {
fmt.Println(err)
continue
}
// Ask for a command from the user and convert to JSON bytes...
// Send message to server.
_, err = serverConnection.Write(clientMsgBytes)
if err != nil {
err = merry.Wrap(err)
fmt.Println(merry.Details(err))
continue
}
err = serverConnection.CloseWrite()
if err != nil {
err = merry.Wrap(err)
fmt.Println(merry.Details(err))
continue
}
// Wait for a response from the server and print...
}
Ниже приведен код, который использует наш TCP-сервер для приема клиентских запросов:
// We only supply the port so the IP can be dynamically assigned:
serverAddress, err := net.ResolveTCPAddr("tcp", ":"+server_port)
if err != nil {
return err
}
tcpListener, err := net.ListenTCP("tcp", serverAddress)
if err != nil {
return err
}
defer tcpListener.Close()
// Never stop listening for client requests.
for {
clientConnection, err := tcpListener.AcceptTCP()
if err != nil {
fmt.Println(err)
continue
}
go func() {
// Add client connection to Job Queue.
// Note that `clientConnections` is a buffered channel with a size of 1500.
// Since I am the only user connecting to our server right now, I do not think
// this is a channel blocking issue.
clientConnections <- clientConnection
}()
}
Ниже приведен код, который использует наш TCP-сервер для обработки клиентских запросов:
defer clientConnection.Close()
// Added to prevent connection timeout errors, but doesn't seem to be helping
// because said errors happen within just 1 or 2 minutes.
err := clientConnection.SetDeadline(time.Now().Add(10 * time.Minute))
if err != nil {
return err
}
// Read full TCP message.
// Does not stop until an EOF is reported by `CloseWrite()`
clientMsgBytes, err := ioutil.ReadAll(clientConnection)
if err != nil {
err = merry.Wrap(err)
return nil, err
}
// Process the message bytes...
Мои вопросы:
Я что-то не так делаю в вышеприведенном коде или он достаточно приличный для базовых операций клиент-сервер TCP?
Это нормально, что и у клиента TCP, и у сервера TCP есть код, который откладывает закрытие одного соединения?
Кажется, я помню, что вызов defer
внутри цикла ничего не делает. Как правильно закрыть клиентские подключения перед запуском новых?
Некоторая дополнительная информация:
- Указанные ошибки не регистрируются TCP-сервером, кроме
нестабильности соединения, это также может быть
Проблема, связанная с Kubernetes / Docker.