diff --git a/socketserver/server/backend.go b/socketserver/server/backend.go index 7d782a29..e456c9df 100644 --- a/socketserver/server/backend.go +++ b/socketserver/server/backend.go @@ -307,9 +307,10 @@ func httpError(statusCode int) error { func GenerateKeys(outputFile, serverID, theirPublicStr string) { var err error output := ConfigFile{ - ListenAddr: "0.0.0.0:8001", - SocketOrigin: "localhost:8001", - BackendURL: "http://localhost:8002/ffz", + ListenAddr: "0.0.0.0:8001", + SocketOrigin: "localhost:8001", + BackendURL: "http://localhost:8002/ffz", + MinMemoryBytes: 1024 * 1024 * 24, } output.ServerID, err = strconv.Atoi(serverID) diff --git a/socketserver/server/handlecore.go b/socketserver/server/handlecore.go index 0d8499d6..5cb9584a 100644 --- a/socketserver/server/handlecore.go +++ b/socketserver/server/handlecore.go @@ -107,6 +107,13 @@ var BannerHTML []byte // It either uses the SocketUpgrader or writes out the BannerHTML. func HTTPHandleRootURL(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Connection") == "Upgrade" { + updateSysMem() + + if Statistics.SysMemTotal-Statistics.SysMemFree < Configuration.MinMemoryBytes { + w.WriteHeader(503) + return + } + conn, err := SocketUpgrader.Upgrade(w, r, nil) if err != nil { fmt.Fprintf(w, "error: %v", err) diff --git a/socketserver/server/stats.go b/socketserver/server/stats.go index dd4f4b55..fe692a00 100644 --- a/socketserver/server/stats.go +++ b/socketserver/server/stats.go @@ -8,6 +8,7 @@ import ( "time" linuxproc "github.com/c9s/goprocinfo/linux" + "sync" ) type StatsData struct { @@ -24,6 +25,8 @@ type StatsData struct { PubSubChannelCount int + SysMemTotal uint64 + SysMemFree uint64 MemoryInUse uint64 MemoryRSS uint64 @@ -72,6 +75,7 @@ func newStatsData() *StatsData { } } +// SetBuildStamp should be called from the main package to identify the git build hash and build time. func SetBuildStamp(buildTime, buildHash string) { Statistics.BuildTime = buildTime Statistics.BuildHash = buildHash @@ -107,6 +111,7 @@ func updatePeriodicStats() { Statistics.MemoryRSS = uint64(pstat.Rss * pageSize) Statistics.MemoryPerClient = Statistics.MemoryRSS / Statistics.CurrentClientCount } + updateSysMem() } { @@ -124,6 +129,27 @@ func updatePeriodicStats() { } } +var sysMemLastUpdate time.Time +var sysMemUpdateLock sync.Mutex + +func updateSysMem() { + if time.Now().Add(-2 * time.Second).After(sysMemLastUpdate) { + sysMemUpdateLock.Lock() + defer sysMemUpdateLock.Unlock() + if !time.Now().Add(-2 * time.Second).After(sysMemLastUpdate) { + return + } + } else { + return + } + sysMemLastUpdate = time.Now() + memInfo, err := linuxproc.ReadMemInfo("/proc/meminfo") + if err == nil { + Statistics.SysMemTotal = memInfo.MemTotal + Statistics.SysMemFree = memInfo.MemAvailable + } +} + func HTTPShowStatistics(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") diff --git a/socketserver/server/types.go b/socketserver/server/types.go index 2eecea38..e851961b 100644 --- a/socketserver/server/types.go +++ b/socketserver/server/types.go @@ -20,6 +20,9 @@ type ConfigFile struct { // URL to the backend server BackendURL string + // Minimum memory to accept a new connection + MinMemoryBytes uint64 + // SSL/TLS UseSSL bool SSLCertificateFile string