+ Removed the fixed shutdown time
+ Added the configuration for the public web server
+ Refactored the old web server settings
+ Improved the handling of shutdown handlers. It is not save!
+ Bugfix: The server start was no longer blocking
This commit is contained in:
Thorsten 2014-11-07 13:00:55 +01:00
parent 96bcb5da8f
commit 3348e552cc
10 changed files with 63 additions and 20 deletions

View File

@ -15,6 +15,10 @@ func checkConfiguration() {
CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerReadTimeoutSeconds`, `10`) CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerReadTimeoutSeconds`, `10`)
CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerWriteTimeoutSeconds`, `10`) CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerWriteTimeoutSeconds`, `10`)
CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerMaxHeaderLenBytes`, `1048576`) CheckSingleConfigurationPresentsAndAddIfMissing(`AdminWebServerMaxHeaderLenBytes`, `1048576`)
CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerPort`, `60000`)
CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerReadTimeoutSeconds`, `10`)
CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerWriteTimeoutSeconds`, `10`)
CheckSingleConfigurationPresentsAndAddIfMissing(`PublicWebServerMaxHeaderLenBytes`, `1048576`)
CheckSingleConfigurationPresentsAndAddIfMissing(`InternalCommPassword`, `please replace this with e.g. a random GUID, etc.`) CheckSingleConfigurationPresentsAndAddIfMissing(`InternalCommPassword`, `please replace this with e.g. a random GUID, etc.`)
CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBHost`, `localhost:27017`) CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBHost`, `localhost:27017`)
CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBDatabase`, `Ocean`) CheckSingleConfigurationPresentsAndAddIfMissing(`CustomerDBDatabase`, `Ocean`)
@ -36,8 +40,6 @@ func checkConfiguration() {
CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenActiveHosts`, `please replace this with the correct hostname of the host which is the master number generator`) CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenActiveHosts`, `please replace this with the correct hostname of the host which is the master number generator`)
CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenGetHandler`, `http://localhost:80/next/number`) CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenGetHandler`, `http://localhost:80/next/number`)
CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenBufferSize`, `12`) CheckSingleConfigurationPresentsAndAddIfMissing(`NumGenBufferSize`, `12`)
CheckSingleConfigurationPresentsAndAddIfMissing(`OceanHostnameAndPort`, `:60000`)
CheckSingleConfigurationPresentsAndAddIfMissing(`OceanServerPort`, `60000`)
CheckSingleConfigurationPresentsAndAddIfMissing(`OceanUtilizeCPUs`, `2`) CheckSingleConfigurationPresentsAndAddIfMissing(`OceanUtilizeCPUs`, `2`)
CheckSingleConfigurationPresentsAndAddIfMissing(`FilenameWebResources`, `web.zip`) CheckSingleConfigurationPresentsAndAddIfMissing(`FilenameWebResources`, `web.zip`)
CheckSingleConfigurationPresentsAndAddIfMissing(`MapStaticFiles2Root`, `false`) CheckSingleConfigurationPresentsAndAddIfMissing(`MapStaticFiles2Root`, `false`)

View File

@ -14,7 +14,7 @@ func init() {
cacheListenerDatabase = list.New() cacheListenerDatabase = list.New()
listeners = make(map[string]func(data map[string][]string)) listeners = make(map[string]func(data map[string][]string))
// Using the local IP address and NOT the configuration "OceanHostnameAndPort": // Using the local IP address:
correctAddressWithPort = Tools.LocalIPAddressAndPort() correctAddressWithPort = Tools.LocalIPAddressAndPort()
initDB() initDB()

View File

@ -2,7 +2,6 @@ package Log
import ( import (
"github.com/SommerEngineering/Ocean/Log/Device" "github.com/SommerEngineering/Ocean/Log/Device"
"time"
) )
/* /*
@ -14,8 +13,7 @@ func Flush() {
close(entriesBuffer) close(entriesBuffer)
mutexChannel.Unlock() mutexChannel.Unlock()
// This is a bad design, but the scheduler need some time to write the last messages. <-schedulerExitSignal
time.Sleep(15 * time.Second)
mutexDeviceDelays.Lock() mutexDeviceDelays.Lock()
dataArray := logEntryListToArray(deviceDelayBuffer) dataArray := logEntryListToArray(deviceDelayBuffer)
@ -26,10 +24,7 @@ func Flush() {
for entry := devices.Front(); entry != nil; entry = entry.Next() { for entry := devices.Front(); entry != nil; entry = entry.Next() {
dev := entry.Value.(Device.Device) dev := entry.Value.(Device.Device)
dev.Log(dataArray) // Want to wait to complete, therefore no new thread here dev.Log(dataArray) // Want to wait to complete, therefore no new thread here
go dev.Flush() dev.Flush()
} }
mutexDevices.RUnlock() mutexDevices.RUnlock()
// This is a bad design, but the devices need (may) some time to write the last messages:
time.Sleep(15 * time.Second)
} }

View File

@ -41,6 +41,7 @@ func init() {
preChannelBuffer = list.New() preChannelBuffer = list.New()
deviceDelayBuffer = list.New() deviceDelayBuffer = list.New()
devices = list.New() devices = list.New()
schedulerExitSignal = make(chan bool)
initTimer() initTimer()
initCode() initCode()

View File

@ -37,4 +37,5 @@ func scheduler(logBuffer chan Meta.Entry) {
} }
LogFull(senderName, Meta.CategorySYSTEM, Meta.LevelWARN, Meta.SeverityCritical, Meta.ImpactNone, Meta.MessageNameSHUTDOWN, `The scheduler is down now.`) LogFull(senderName, Meta.CategorySYSTEM, Meta.LevelWARN, Meta.SeverityCritical, Meta.ImpactNone, Meta.MessageNameSHUTDOWN, `The scheduler is down now.`)
schedulerExitSignal <- true
} }

View File

@ -8,6 +8,7 @@ import (
var ( var (
entriesBuffer chan Meta.Entry = nil entriesBuffer chan Meta.Entry = nil
schedulerExitSignal chan bool = nil
logBufferSize int = 500 logBufferSize int = 500
logBufferTimeoutSeconds int = 4 logBufferTimeoutSeconds int = 4
logDeviceDelayNumberEvents int = 600 logDeviceDelayNumberEvents int = 600

View File

@ -1,6 +1,8 @@
package Shutdown package Shutdown
import ( import (
"container/list"
"fmt"
"github.com/SommerEngineering/Ocean/Log" "github.com/SommerEngineering/Ocean/Log"
LM "github.com/SommerEngineering/Ocean/Log/Meta" LM "github.com/SommerEngineering/Ocean/Log/Meta"
"os" "os"
@ -20,12 +22,22 @@ func executeShutdown() {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system was called to shutting down.`, sig.String(), `Call now all shutdown handlers.`) Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system was called to shutting down.`, sig.String(), `Call now all shutdown handlers.`)
for handler := shutdownHandlers.Front(); handler != nil; handler = handler.Next() { for handler := shutdownHandlers.Front(); handler != nil; handler = handler.Next() {
h := handler.Value.(ShutdownHandler) safeCall(handler)
h.Shutdown()
} }
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system is shutting down now.`) Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameSHUTDOWN, `The system is shutting down now.`)
Log.Flush() Log.Flush()
os.Exit(0)
os.Exit(6) }
func safeCall(handler *list.Element) {
defer func() {
if err := recover(); err != nil {
errObj := fmt.Errorf("%v", err)
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.SeverityNone, LM.ImpactNone, LM.MessageNameSHUTDOWN, `An error occurs for a shutdown handler.`, errObj.Error())
}
}()
h := handler.Value.(ShutdownHandler)
h.Shutdown()
} }

View File

@ -2,8 +2,12 @@ package System
import ( import (
"github.com/SommerEngineering/Ocean/WebServer" "github.com/SommerEngineering/Ocean/WebServer"
"time"
) )
func StartAndBlockForever() { func StartAndBlockForever() {
WebServer.Start() WebServer.Start()
for {
time.Sleep(1 * time.Second)
}
} }

View File

@ -29,6 +29,6 @@ func init() {
// Build the local IP address and port: // Build the local IP address and port:
allHostsIPAddresses := ReadAllIPAddresses4ThisHost() allHostsIPAddresses := ReadAllIPAddresses4ThisHost()
port := ConfigurationDB.Read(`OceanServerPort`) port := ConfigurationDB.Read(`PublicWebServerPort`)
localIPAddressAndPort = allHostsIPAddresses[0] + `:` + port localIPAddressAndPort = allHostsIPAddresses[0] + `:` + port
} }

View File

@ -26,9 +26,32 @@ func init() {
serverPublic.Handler = Handlers.GetPublicMux() serverPublic.Handler = Handlers.GetPublicMux()
serverPublic.SetKeepAlivesEnabled(true) serverPublic.SetKeepAlivesEnabled(true)
serverPublic.ReadTimeout = 10 * time.Second // Public Web Server: Read Timeout
serverPublic.WriteTimeout = 10 * time.Second if readTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`PublicWebServerReadTimeoutSeconds`)); errTimeout != nil {
serverPublic.MaxHeaderBytes = 1024 Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the public server's read timeout value. Use the default of 10 seconds instead.`, errTimeout.Error())
serverPublic.ReadTimeout = 10 * time.Second
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The public web server's read timeout was set to %d seconds.", readTimeoutSeconds))
serverPublic.ReadTimeout = time.Duration(readTimeoutSeconds) * time.Second
}
// Public Web Server: Write Timeout
if writeTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`PublicWebServerWriteTimeoutSeconds`)); errTimeout != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the public server's write timeout value. Use the default of 10 seconds instead.`, errTimeout.Error())
serverPublic.WriteTimeout = 10 * time.Second
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The public web server's write timeout was set to %d seconds.", writeTimeoutSeconds))
serverPublic.WriteTimeout = time.Duration(writeTimeoutSeconds) * time.Second
}
// Public Web Server: Max. Header Size
if maxHeaderBytes, errHeaderBytes := strconv.Atoi(ConfigurationDB.Read(`PublicWebServerMaxHeaderLenBytes`)); errHeaderBytes != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the public server's max. header size. Use the default of 1048576 bytes instead.`, errHeaderBytes.Error())
serverPublic.MaxHeaderBytes = 1048576
} else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The public web server's max. header size was set to %d bytes.", maxHeaderBytes))
serverPublic.MaxHeaderBytes = maxHeaderBytes
}
if strings.ToLower(ConfigurationDB.Read(`AdminWebServerEnabled`)) == `true` { if strings.ToLower(ConfigurationDB.Read(`AdminWebServerEnabled`)) == `true` {
serverAdmin = &http.Server{} serverAdmin = &http.Server{}
@ -36,6 +59,7 @@ func init() {
serverAdmin.Handler = Handlers.GetAdminMux() serverAdmin.Handler = Handlers.GetAdminMux()
serverAdmin.SetKeepAlivesEnabled(true) serverAdmin.SetKeepAlivesEnabled(true)
// Admin Web Server: Read Timeout
if readTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerReadTimeoutSeconds`)); errTimeout != nil { if readTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerReadTimeoutSeconds`)); errTimeout != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's read timeout value. Use the default of 10 seconds instead.`, errTimeout.Error()) Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's read timeout value. Use the default of 10 seconds instead.`, errTimeout.Error())
serverAdmin.ReadTimeout = 10 * time.Second serverAdmin.ReadTimeout = 10 * time.Second
@ -44,6 +68,7 @@ func init() {
serverAdmin.ReadTimeout = time.Duration(readTimeoutSeconds) * time.Second serverAdmin.ReadTimeout = time.Duration(readTimeoutSeconds) * time.Second
} }
// Admin Web Server: Write Timeout
if writeTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerWriteTimeoutSeconds`)); errTimeout != nil { if writeTimeoutSeconds, errTimeout := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerWriteTimeoutSeconds`)); errTimeout != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's write timeout value. Use the default of 10 seconds instead.`, errTimeout.Error()) Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's write timeout value. Use the default of 10 seconds instead.`, errTimeout.Error())
serverAdmin.WriteTimeout = 10 * time.Second serverAdmin.WriteTimeout = 10 * time.Second
@ -52,14 +77,16 @@ func init() {
serverAdmin.WriteTimeout = time.Duration(writeTimeoutSeconds) * time.Second serverAdmin.WriteTimeout = time.Duration(writeTimeoutSeconds) * time.Second
} }
// Admin Web Server: Max. Header Size
if maxHeaderBytes, errHeaderBytes := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerMaxHeaderLenBytes`)); errHeaderBytes != nil { if maxHeaderBytes, errHeaderBytes := strconv.Atoi(ConfigurationDB.Read(`AdminWebServerMaxHeaderLenBytes`)); errHeaderBytes != nil {
Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's maximum count of bytes for the headers. Use the default of 1048576 bytes instead.`, errHeaderBytes.Error()) Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelWARN, LM.SeverityLow, LM.ImpactLow, LM.MessageNameCONFIGURATION, `Was not able to read the admin server's max. header size. Use the default of 1048576 bytes instead.`, errHeaderBytes.Error())
serverAdmin.MaxHeaderBytes = 1048576 serverAdmin.MaxHeaderBytes = 1048576
} else { } else {
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The admin web server's count of maximal bytes for the headers was set to %d bytes.", maxHeaderBytes)) Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameCONFIGURATION, fmt.Sprintf("The admin web server's max. header size was set to %d bytes.", maxHeaderBytes))
serverAdmin.MaxHeaderBytes = maxHeaderBytes serverAdmin.MaxHeaderBytes = maxHeaderBytes
} }
} else { } else {
// Admin Web Server is disabled
Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The admin web server is disabled.`) Log.LogShort(senderName, LM.CategorySYSTEM, LM.LevelINFO, LM.MessageNameSTARTUP, `The admin web server is disabled.`)
} }
} }