记一次Connection reset by peer排错

最近工作需要,写了一个简单的 web 程序,程序主体 main.go:

package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"

	"github.com/gin-gonic/gin"
	"github.com/leffss/token/pkg/setting"
)

func init() {
	setting.Setup()
}

func serverName(v string) gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("server", v)
		c.Next()
	}
}

func ipWhiteList() gin.HandlerFunc {
	whitelist := make(map[string]bool)
	for _, ip := range setting.ServerSetting.IpWhiteLists {
		whitelist[ip] = true
	}
	return func(c *gin.Context) {
		if !whitelist[c.ClientIP()] && !whitelist["0.0.0.0"] {
			c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
				"status":  http.StatusForbidden,
				"message": "Permission denied",
			})
			return
		}
	}
}

func token(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		"secret": base64.StdEncoding.EncodeToString([]byte(setting.ServerSetting.Token)),
	})
}

func main() {
	// gin.SetMode("debug")
	gin.SetMode("release")
	gin.DisableConsoleColor()
	router := gin.Default()
	router.Use(serverName("nginx"))
	router.Use(ipWhiteList())
	router.GET("/", token)

	endPoint := fmt.Sprintf("%s:%d", setting.ServerSetting.Host, setting.ServerSetting.Port)

	server := &http.Server{
		Addr:           endPoint,
		Handler:        router,
		ReadTimeout:    15,
		WriteTimeout:   15,
		MaxHeaderBytes: 1048576,
	}
	log.Printf("[info] start http server listen on %s", endPoint)
	go func() {
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("[error] Server Start Error: %s\n", err)
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	ctx, cancel := context.WithTimeout(context.Background(), 15)
	defer cancel()
	if err := server.Shutdown(ctx); err != nil {
		log.Fatal("[error] Server Shutdown Error: ", err)
	}
	log.Println("[info] Server Shutdown")
}

现象:windows 下正常运行并返回结果,但是 linux 正常监听端口后,curl 访问提示:

curl: (56) Recv failure: Connection reset by peer

使用 tcpdump 抓包:

tcpdump -i lo -w 10080.cap

使用 wareshark 查看,可以看到TCP三次握手是正常的,已经到了 get 请求阶段,但是最终返回 RST, ACK

网上查了下资料,可能原因有:

  • 端口未打开

  • 请求超时

  • 提前关闭

  • 在一个已关闭的socket上收到数据

  • 异常终止一个连接

再看了下代码发现设置了超时参数:

	ReadTimeout:    15,
	WriteTimeout:   15,

大意了,这两个参数类型应该是 time.Duration 类型,这里设置了错误的读写超时时间,使用 // 注释掉或者设置正确的超时时间:

        ReadTimeout:    15 * time.Second,
        WriteTimeout:   15 * time.Second,
posted @ 2022-11-05 15:36  leffss  阅读(116)  评论(0编辑  收藏  举报