Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
hjr265 committed Sep 6, 2015
0 parents commit 6b129f5
Show file tree
Hide file tree
Showing 30 changed files with 1,789 additions and 0 deletions.
27 changes: 27 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Copyright (c) 2015, The Loadcat Authors
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of Loadcat nor the names of its contributors may be used
to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
89 changes: 89 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Loadcat

Loadcat is an Nginx configurator that allows you to use Nginx as a load balancer. The project is inspired by the various Nginx load balancing tutorial articles available online and also the existence of Linode's load balancer service [NodeBalancers](https://www.linode.com/nodebalancers). So far the tool covers some of HTTP and HTTPS load balancing features, such as SSL termination, adding servers on the fly, marking them as unavailable or backup as necessary, and setting their weights to distribute load fairly.

## Installation

### Arch Linux

Install Loadcat using a pre-built .pkg file:

~~~
$ wget https://github.com/hjr265/loadcat/releases/download/v0.1-alpha.1/loadcat-0.1_alpha.1-1-x86_64.pkg.tar.xz
# pacman -U loadcat-0.1_alpha.1-1-x86_64.pkg.tar.xz
~~~

Or, from AUR using Yaourt:

~~~
$ yaourt loadcat
~~~

Or, manually:

~~~
$ git clone https://aur.archlinux.org/loadcat.git
$ cd loadcat
$ makepkg
# pacman -U loadcat-0.1_alpha.1-1-x86_64.pkg.tar.xz
~~~

### From Source

Install Loadcat using the go get command:

```
$ go get github.com/hjr265/loadcat/cmd/loadcatd
```

## Usage

If you installed Loadcat using the distribution specific package, you can start it as a service using systemctl:

```
# systemctl start loadcat.service
```

If you installed Loadcat from source, you can launch it with:

```
$ cd $GOPATH/src/github.com/hjr265/loadcat
# $GOPATH/bin/loadcatd
```

Loadcat parses a TOML encoded configuration file. In case one is not found, Loadcat will create one with same sane defaults. The location of the configuration file can be specified with the _-config_ flag.

Loadcat works by generating Nginx configuration files under a particular directory (a directory named "out" under Loadcat's working directory, as set in loadcat.conf). Nginx must be configured to load configuration files from this directory. For example on Arch Linux, when installed from AUR, Loadcat uses /var/lib/loadcat/out as the directory where generated Nginx configuration files are stored. You must include the following line inside the `http {}` block of /etc/nginx/nginx.conf to load configuration files generated by Loadcat:

```
include /var/lib/loadcat/out/*/nginx.conf
```

Once Loadcat is running, you can navigate to http://{host}:26590 on your web browser, where _{host}_ is the domain name or IP address of the machine where Loadcat is running (for example http://localhost:26590 when running locally). To save a thousand words, here is a (kind of big) picture:

![4 steps primer](http://i.imgur.com/7l6zN5n.png)

Make sure that Nginx is running as a systemd service and is configured to load generated configuration files from the appropriate directory.

## Caution

As this is a very young project, and pretty experimental, you may encounter bugs and issues here and there. It would be really appreciated if you could open an issue outlining details of the bug or issue, or any feature that you would like to request. Any contribution or criticism (constructive or destructive) is really appreciated.

A lot of Nginx load balancing features is still not covered by this tool and at this moment that makes this rather limited in context of practical applications. However, solving this problem is just a matter of time. Although Nginx Plus specific features may have to wait for a while - at least until I get my hands on an instance or someone else with access to Nginx Plus starts contributing.

## Documentation

- [Reference](http://godoc.org/github.com/hjr265/loadcat)

## Resources

- [DigitalOcean's Tutorial on Using Nginx as a Load Balancer](https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-load-balancing)
- [Nginx's HTTP Load Balancing Documentation](http://nginx.org/en/docs/http/load_balancing.html)

## Contributing

Contributions are welcome.

## License

Loadcat is available under the [BSD (3-Clause) License](http://opensource.org/licenses/BSD-3-Clause).
9 changes: 9 additions & 0 deletions api/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2015 The Loadcat Authors. All rights reserved.

package api

import (
"github.com/gorilla/mux"
)

var Router = mux.NewRouter()
57 changes: 57 additions & 0 deletions cfg/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2015 The Loadcat Authors. All rights reserved.

package cfg

import (
"os"

"github.com/naoina/toml"
)

var Current = struct {
Core struct {
Address string
Dir string
Driver string
}
Nginx struct {
Mode string
Systemd struct {
Service string
}
}
}{}

func LoadFile(name string) error {
f, err := os.Open(name)
if os.IsNotExist(err) {
f, err = os.Create(name)
if err != nil {
return err
}
err = toml.NewEncoder(f).Encode(Current)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}
if err != nil {
return err
}
err = toml.NewDecoder(f).Decode(&Current)
if err != nil {
return err
}
return nil
}

func init() {
Current.Core.Address = ":26590"
Current.Core.Driver = "nginx"
Current.Nginx.Mode = "systemd"
Current.Nginx.Systemd.Service = "nginx.service"
}
63 changes: 63 additions & 0 deletions cmd/loadcatd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2015 The Loadcat Authors. All rights reserved.

package main

import (
"flag"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"

"github.com/hjr265/loadcat/api"
"github.com/hjr265/loadcat/cfg"
"github.com/hjr265/loadcat/data"
"github.com/hjr265/loadcat/feline"
_ "github.com/hjr265/loadcat/feline/nginx"
"github.com/hjr265/loadcat/ui"
)

func main() {
fconfig := flag.String("config", "loadcat.conf", "")
flag.Parse()
err := cfg.LoadFile(*fconfig)
if err != nil {
log.Fatal(err)
}

err = feline.SetBase(filepath.Join(cfg.Current.Core.Dir, "out"))
if err != nil {
log.Fatal(err)
}

err = data.OpenDB(filepath.Join(cfg.Current.Core.Dir, "loadcat.db"))
if err != nil {
log.Fatal(err)
}
defer func() {
err := data.DB.Close()
if err != nil {
log.Print(err)
}
}()
err = data.InitDB()
if err != nil {
log.Fatal(err)
}

http.Handle("/api", api.Router)
http.Handle("/", ui.Router)

go func() {
err = http.ListenAndServe(cfg.Current.Core.Address, nil)
if err != nil {
log.Fatal(err)
}
}()

c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)

log.Printf("Received %s; exiting..", <-c)
}
21 changes: 21 additions & 0 deletions data/algorithm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2015 The Loadcat Authors. All rights reserved.

package data

type Algorithm string

var Algorithms = []Algorithm{
"round-robin",
"least-connections",
"source-ip",
}

func (a Algorithm) Label() string {
return AlgorithmLabels[a]
}

var AlgorithmLabels = map[Algorithm]string{
"round-robin": "Round-robin",
"least-connections": "Least Connections",
"source-ip": "Source IP",
}
21 changes: 21 additions & 0 deletions data/availability.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2015 The Loadcat Authors. All rights reserved.

package data

type Availability string

var Availabilities = []Availability{
"unavailable",
"available",
"backup",
}

func (a Availability) Label() string {
return AvailabilityLabels[a]
}

var AvailabilityLabels = map[Availability]string{
"unavailable": "Unavailable",
"available": "Available",
"backup": "Backup",
}
Loading

0 comments on commit 6b129f5

Please sign in to comment.