Skip to content

Commit

Permalink
Version 0.1.0 Ready
Browse files Browse the repository at this point in the history
 * Create new workers if cached are exausted
 * Support to cancelled requests
 * Graceful shutdown
 * Added support to websocket
 * Cleanup the structure
 * Better configuration
 * Better JSON config file check
 * Default values
 * Tests for configuration files
 * Restructuring the server
 * Removed races and useless structs
 * Cleanup and better command display
 * Readme
  • Loading branch information
eduardonunesp committed Oct 26, 2015
1 parent 1c1b168 commit 1320e89
Show file tree
Hide file tree
Showing 22 changed files with 1,119 additions and 623 deletions.
18 changes: 17 additions & 1 deletion Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 48 additions & 25 deletions README.md
@@ -1,7 +1,22 @@
# SSLB (Super Simple Load Balancer)
# SSLB (Super Simple Load Balancer) ver 0.1.0

It's a Super Simples Load Balancer, just a little project to achieve some kind of performance.

## Features
* High availability (improving with time the speed)
* Support to WebSockets
* Monitoring the internal state (improving)
* Really easy to configure, just a little JSON file

## Next features
* Manage configurations in runtime without downtime
* Complete internal status and diagnostics
* HTTP/2 support
* Cache
* HTTPS support

If you have any suggestion don't hesitate to open an issue, pull requests are welcome too.

## Install

To install type:
Expand All @@ -19,20 +34,20 @@ Type `sslb -h` for the command line help
```
sslb -h
NAME:
sslb (SUPER SIMPLE LOAD BALANCER) - sslb
SSLB (github.com/eduardonunesp/sslb) - sslb
USAGE:
sslb [global options] command [command options] [arguments...]
VERSION:
0.0.4
0.1.0
COMMANDS:
status, s Return the internal status
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--verbose, -b activate the verbose output
--config, -c create an example of config file
--filename, -f set the filename as the configuration
--help, -h show help
--version, -v print the version
Expand All @@ -42,34 +57,43 @@ After the configuration file completed you can type only `sslb -b` to start SSLB

```
sslb -b
2015/10/22 12:22:24 4 CPUS available, using only 4
2015/10/22 12:22:24 Create dispatcher pool with [10]
2015/10/22 12:22:24 Create worker pool with [10]
2015/10/22 12:22:24 Run frontend server [Front1] at [0.0.0.0:80]
2015/10/22 12:22:24 Backend active [Backend 2]
2015/10/22 12:22:24 Backend active [Backend 2]
2015/10/25 22:58:33 Start SSLB (Server)
2015/10/25 22:58:33 Create worker pool with [1000]
2015/10/25 22:58:33 Prepare to run server ...
2015/10/25 22:58:33 Setup and check configuration
2015/10/25 22:58:33 Setup ok ...
2015/10/25 22:58:33 Run frontend server [Front1] at [0.0.0.0:80]
2015/10/25 22:58:34 Backend active [Backend 1]
2015/10/25 22:58:34 Backend active [Backend 2]
2015/10/25 22:58:34 Backend active [Backend 3]
```

## Configuration options

* general:
* maxProcs: Number of processors used by Go runtime
* workerPoolSize: Number of workers for processing request
* dispatcherPoolSize: Number of dispatchers for send the requests to the backends
* maxProcs: Number of processors used by Go runtime (default: Number of CPUS)
* workerPoolSize: Number of workers for processing request (default: 10)
* gracefulShutdown: Wait for the last connection closed, before shutdown (default: true)
* websocket: Ready for respond websocket connections (default: true)
* rpchost: Address to expose the internal state (default: 127.0.0.1)
* rpcport: Port to expose the internal state (default: 42555)

* frontends:
* name: Just a identifier to your front server
* host: Host address that serves the HTTP front
* port: Port address that serves the HTTP front
* route: Route to receive the traffic
* timeout: How long can wait for the result (ms) from the backend
* name: Just a identifier to your front server (required)
* host: Host address that serves the HTTP front (required)
* port: Port address that serves the HTTP front (required)
* route: Route to receive the traffic (required)
* timeout: How long can wait for the result (ms) from the backend (default: 30000ms)

* backends:
* name: Just a identifier
* address: Address (URL) for your backend
* hearbeat: Addres to send Head request to test if it's ok
* inactiveAfter: Consider the backend inactive after
* heartbeatTime: The interval to send a "ping"
* retryTime: The interval to send a "ping" after the first failed "ping"
* name: Just a identifier (required)
* address: Address (URL) for your backend (required)
* hearbeat: Addres to send Head request to test if it's ok (required)
* hbmethod: Method used in request to check the heartbeat (default: HEAD)
* inactiveAfter: Consider the backend inactive after the number of checks (default: 3)
* activeAfter: COnsider the backend active after the number of checks (default: 1)
* heartbeatTime: The interval to send a "ping" (default: 30000ms)
* retryTime: The interval to send a "ping" after the first failed "ping" (default: 5000ms)

### Example (config.json)

Expand All @@ -78,7 +102,6 @@ sslb -b
"general": {
"maxProcs": 4,
"workerPoolSize": 10,
"dispatcherPoolSize": 10
},
"frontends" : [
Expand Down
152 changes: 35 additions & 117 deletions cfg/fileparser.go
Expand Up @@ -5,48 +5,13 @@ import (
"io/ioutil"
"log"
"runtime"
"time"

"github.com/eduardonunesp/sslb/lb"
"github.com/eduardonunesp/sslb/lb/endpoint"
)

// General config
type General struct {
MaxProcs int
WorkerPoolSize int
DispatcherPoolSize int
}

// Backend config
type Backend struct {
Name string
Address string
Heartbeat string
HBMethod string
ActiveAfter int
InactiveAfter int
HeartbeatTime int
RetryTime int
}

// Frontend config
type Frontend struct {
Name string
Host string
Port int
Route string
Timeout int
Backends []Backend
}

const DEFAULT_FILENAME = "config.json"

// Config structured used to build the server
type Config struct {
General General
Frontends []Frontend
}

func openFile(filename string) []byte {
var file []byte
var err error
Expand Down Expand Up @@ -79,10 +44,38 @@ func openFile(filename string) []byte {
}

// ConfParser to Parse JSON FILE
func ConfParser(filename string) Config {
file := openFile(filename)
func ConfParser(file []byte) lb.Configuration {
if err := Validate(file); err != nil {
log.Fatal("Can't validate config.json ", err)
}

jsonConfig := lb.Configuration{
GeneralConfig: lb.GeneralConfig{
MaxProcs: runtime.NumCPU(),
WorkerPoolSize: 10,
GracefulShutdown: true,
Websocket: true,
LogLevel: "info",
RPCHost: "127.0.0.1",
RPCPort: 42555,
},
FrontendsConfig: []lb.FrontendConfig{
{
Timeout: time.Millisecond * 30000,
BackendsConfig: []lb.BackendConfig{
{
HBMethod: "HEAD",
ActiveAfter: 1,
InactiveAfter: 3,
Weight: 1,
HeartbeatTime: time.Millisecond * 30000,
RetryTime: time.Millisecond * 5000,
},
},
},
},
}

var jsonConfig Config
err := json.Unmarshal(file, &jsonConfig)

if err != nil {
Expand All @@ -92,83 +85,8 @@ func ConfParser(filename string) Config {
return jsonConfig
}

func CreateConfig(filename string) {
configExample := []byte(`{
"general": {
"maxProcs": 4,
"workerPoolSize": 1000,
"dispatcherPoolSize": 1000
},
"frontends" : [{
"name" : "Frontend App",
"host" : "0.0.0.0",
"port" : 80,
"route" : "/",
"timeout" : 5000,
"backends" : [
{
"name" : "Backend 1",
"address" : "http://127.0.0.1:9001",
"heartbeat" : "http://127.0.0.1:9001/heartbeat",
"inactiveAfter" : 3,
"heartbeatTime" : 15000,
"retryTime" : 1000
},{
"name" : "Backend 2",
"address" : "http://127.0.0.1:9002",
"heartbeat" : "http://127.0.0.1:9002/heartbeat",
"hbmethod" : "HEAD",
"inactiveAfter" : 3,
"activeAfter" : 1,
"heartbeatTime" : 15000,
"retryTime" : 1000
},{
"name" : "Backend 3",
"address" : "http://127.0.0.1:9003",
"heartbeat" : "http://127.0.0.1:9003/heartbeat",
"hbmethod" : "HEAD",
"activeAfter" : 1,
"inactiveAfter" : 1,
"heartbeatTime" : 5000,
"retryTime" : 1000
}
]
}]
}`)

err := ioutil.WriteFile(filename, configExample, 0644)
if err != nil {
log.Fatal("Can't create file config.json example", err)
}
}

// Setup will build everything and let the server run
func Setup(filename string) *lb.Server {
config := ConfParser(filename)

cpus := runtime.NumCPU()
log.Printf("%d CPUS available, using only %d", cpus, config.General.MaxProcs)

runtime.GOMAXPROCS(config.General.MaxProcs)

server := lb.NewServer(config.General.WorkerPoolSize, config.General.DispatcherPoolSize)

for _, frontendConfig := range config.Frontends {
frontend := endpoint.NewFrontend(
frontendConfig.Name, frontendConfig.Host,
frontendConfig.Port, frontendConfig.Route, frontendConfig.Timeout)

for _, backendConfig := range frontendConfig.Backends {
backend := endpoint.NewBackend(backendConfig.Name, backendConfig.Address, backendConfig.Heartbeat,
backendConfig.HBMethod, backendConfig.ActiveAfter, backendConfig.InactiveAfter, backendConfig.HeartbeatTime,
backendConfig.RetryTime)
frontend.AddBackend(backend)
}

server.AddFrontend(frontend)
}

return server
func Setup(filename string) lb.Configuration {
file := openFile(filename)
return ConfParser(file)
}

0 comments on commit 1320e89

Please sign in to comment.