Browse Source

Fix server-side proxy inappropriate quit when met `accept: too many open files` error (#2467)

Fishbone 3 years ago
parent
commit
df5859b5f7

+ 1 - 0
conf/systemd/frpc.service

@@ -9,6 +9,7 @@ Restart=on-failure
 RestartSec=5s
 ExecStart=/usr/bin/frpc -c /etc/frp/frpc.ini
 ExecReload=/usr/bin/frpc reload -c /etc/frp/frpc.ini
+LimitNOFILE=1048576
 
 [Install]
 WantedBy=multi-user.target

+ 2 - 1
conf/systemd/frpc@.service

@@ -3,12 +3,13 @@ Description=Frp Client Service
 After=network.target
 
 [Service]
-Type=idle
+Type=simple
 User=nobody
 Restart=on-failure
 RestartSec=5s
 ExecStart=/usr/bin/frpc -c /etc/frp/%i.ini
 ExecReload=/usr/bin/frpc reload -c /etc/frp/%i.ini
+LimitNOFILE=1048576
 
 [Install]
 WantedBy=multi-user.target

+ 1 - 0
conf/systemd/frps.service

@@ -8,6 +8,7 @@ User=nobody
 Restart=on-failure
 RestartSec=5s
 ExecStart=/usr/bin/frps -c /etc/frp/frps.ini
+LimitNOFILE=1048576
 
 [Install]
 WantedBy=multi-user.target

+ 1 - 0
conf/systemd/frps@.service

@@ -8,6 +8,7 @@ User=nobody
 Restart=on-failure
 RestartSec=5s
 ExecStart=/usr/bin/frps -c /etc/frp/%i.ini
+LimitNOFILE=1048576
 
 [Install]
 WantedBy=multi-user.target

+ 18 - 1
server/proxy/proxy.go

@@ -21,6 +21,7 @@ import (
 	"net"
 	"strconv"
 	"sync"
+	"time"
 
 	"github.com/fatedier/frp/pkg/config"
 	"github.com/fatedier/frp/pkg/msg"
@@ -151,12 +152,28 @@ func (pxy *BaseProxy) startListenHandler(p Proxy, handler func(Proxy, net.Conn,
 	xl := xlog.FromContextSafe(pxy.ctx)
 	for _, listener := range pxy.listeners {
 		go func(l net.Listener) {
+			var tempDelay time.Duration // how long to sleep on accept failure
+
 			for {
 				// block
 				// if listener is closed, err returned
 				c, err := l.Accept()
 				if err != nil {
-					xl.Info("listener is closed")
+					if err, ok := err.(interface{ Temporary() bool }); ok && err.Temporary() {
+						if tempDelay == 0 {
+							tempDelay = 5 * time.Millisecond
+						} else {
+							tempDelay *= 2
+						}
+						if max := 1 * time.Second; tempDelay > max {
+							tempDelay = max
+						}
+						xl.Info("met temporary error: %s, sleep for %s ...", err, tempDelay)
+						time.Sleep(tempDelay)
+						continue
+					}
+
+					xl.Warn("listener is closed: %s", err)
 					return
 				}
 				xl.Info("get a user connection [%s]", c.RemoteAddr().String())