Add basic load balancing (server groups)
parent
8da8634c3d
commit
29e68f0200
15
README.md
15
README.md
|
@ -69,6 +69,21 @@ Leave this empty to require no special privilege. Note that this only affects th
|
|||
players can still be connected to this server if it is the default server, a minetest server requests it
|
||||
or if a different command is used.
|
||||
```
|
||||
> `groups`
|
||||
```
|
||||
Type: Dictionary
|
||||
Description: List of all server groups
|
||||
```
|
||||
> `groups.*`
|
||||
```
|
||||
Type: List
|
||||
Description: Contains server group members
|
||||
```
|
||||
> `group_privs`
|
||||
```
|
||||
Type: Dictionary
|
||||
Description: List of all server groups and the required privilege (on the proxy), can be omitted
|
||||
```
|
||||
> `default_server`
|
||||
```
|
||||
Type: String
|
||||
|
|
11
conn.go
11
conn.go
|
@ -191,3 +191,14 @@ func ConnCount() int {
|
|||
|
||||
return connectedConns
|
||||
}
|
||||
|
||||
// ConnsServer returns the client Conns that are connected to a server
|
||||
func ConnsServer(server string) []*Conn {
|
||||
var r []*Conn
|
||||
for _, c := range Conns() {
|
||||
if c.ServerName() == server {
|
||||
r = append(r, c)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
|
21
igutils.go
21
igutils.go
|
@ -162,6 +162,7 @@ func init() {
|
|||
c.SendChatMsg("Current server: " + c.ServerName() + " | All servers: " + r)
|
||||
} else {
|
||||
servers := ConfKey("servers").(map[interface{}]interface{})
|
||||
groups := ConfKey("groups").(map[interface{}]interface{})
|
||||
srv := c.ServerName()
|
||||
|
||||
if srv == param {
|
||||
|
@ -169,17 +170,35 @@ func init() {
|
|||
return
|
||||
}
|
||||
|
||||
if servers[param] == nil {
|
||||
nogrp := true
|
||||
for grp := range groups {
|
||||
name, ok := grp.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if name == param {
|
||||
nogrp = false
|
||||
}
|
||||
}
|
||||
|
||||
if servers[param] == nil && nogrp {
|
||||
c.SendChatMsg("Unknown servername " + param)
|
||||
return
|
||||
}
|
||||
|
||||
reqprivs := make(map[string]bool)
|
||||
|
||||
reqpriv, ok := ConfKey("servers:" + param + ":priv").(string)
|
||||
if ok {
|
||||
reqprivs[reqpriv] = true
|
||||
}
|
||||
|
||||
reqpriv, ok = ConfKey("group_privs:" + param).(string)
|
||||
if ok {
|
||||
reqprivs[reqpriv] = true
|
||||
}
|
||||
|
||||
allow, err := c.CheckPrivs(reqprivs)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
|
|
15
media.go
15
media.go
|
@ -10,7 +10,6 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/anon55555/mt/rudp"
|
||||
)
|
||||
|
@ -362,8 +361,6 @@ func loadMedia(servers map[string]struct{}) {
|
|||
|
||||
loadMediaCache()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for server := range servers {
|
||||
straddr := ConfKey("servers:" + server + ":address")
|
||||
|
||||
|
@ -383,23 +380,15 @@ func loadMedia(servers map[string]struct{}) {
|
|||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
clt := &Conn{username: "media"}
|
||||
|
||||
fin := make(chan *Conn) // close-only
|
||||
go Init(clt, srv, false, true, fin)
|
||||
<-fin
|
||||
|
||||
go func() {
|
||||
<-fin
|
||||
|
||||
srv.fetchMedia()
|
||||
wg.Done()
|
||||
}()
|
||||
srv.fetchMedia()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if err := mergeNodedefs(nodedefs); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
35
redirect.go
35
redirect.go
|
@ -20,8 +20,8 @@ func RegisterOnRedirectDone(function func(*Conn, string, bool)) {
|
|||
onRedirectDone = append(onRedirectDone, function)
|
||||
}
|
||||
|
||||
func processRedirectDone(c *Conn, newsrv string) {
|
||||
success := c.ServerName() == newsrv
|
||||
func processRedirectDone(c *Conn, newsrv *string) {
|
||||
success := c.ServerName() == *newsrv
|
||||
|
||||
successstr := "false"
|
||||
if success {
|
||||
|
@ -30,12 +30,12 @@ func processRedirectDone(c *Conn, newsrv string) {
|
|||
|
||||
rpcSrvMu.Lock()
|
||||
for srv := range rpcSrvs {
|
||||
srv.doRpc("->REDIRECTED "+c.Username()+" "+newsrv+" "+successstr, "--")
|
||||
srv.doRpc("->REDIRECTED "+c.Username()+" "+*newsrv+" "+successstr, "--")
|
||||
}
|
||||
rpcSrvMu.Unlock()
|
||||
|
||||
for i := range onRedirectDone {
|
||||
onRedirectDone[i](c, newsrv, success)
|
||||
onRedirectDone[i](c, *newsrv, success)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,11 +44,32 @@ func (c *Conn) Redirect(newsrv string) error {
|
|||
c.redirectMu.Lock()
|
||||
defer c.redirectMu.Unlock()
|
||||
|
||||
defer processRedirectDone(c, newsrv)
|
||||
defer processRedirectDone(c, &newsrv)
|
||||
|
||||
straddr, ok := ConfKey("servers:" + newsrv + ":address").(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("server %s does not exist", newsrv)
|
||||
grp, ok := ConfKey("groups:" + newsrv).([]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("server or group %s does not exist", newsrv)
|
||||
}
|
||||
|
||||
smallestCnt := int(^uint(0) >> 1)
|
||||
for _, srv := range grp {
|
||||
cnt := len(ConnsServer(srv.(string)))
|
||||
if cnt < smallestCnt {
|
||||
if c.ServerName() == srv.(string) {
|
||||
return fmt.Errorf("already connected to server %s", srv.(string))
|
||||
}
|
||||
|
||||
smallestCnt = cnt
|
||||
newsrv = srv.(string)
|
||||
}
|
||||
}
|
||||
|
||||
straddr, ok = ConfKey("servers:" + newsrv + ":address").(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("server %s does not exist", newsrv)
|
||||
}
|
||||
}
|
||||
|
||||
if c.ServerName() == newsrv {
|
||||
|
@ -70,7 +91,7 @@ func (c *Conn) Redirect(newsrv string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fin := make(chan *Conn) // close-only
|
||||
fin := make(chan *Conn)
|
||||
go Init(c, srv, true, false, fin)
|
||||
initOk := <-fin
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ func initStorageDB() (*sql.DB, error) {
|
|||
}
|
||||
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS storage (
|
||||
key VARCHAR(512) NOT NULL,
|
||||
key VARCHAR(512) PRIMARY KEY NOT NULL,
|
||||
value VARCHAR(512) NOT NULL
|
||||
);`); err != nil {
|
||||
db.Close()
|
||||
|
|
Loading…
Reference in New Issue