Add basic load balancing (server groups)

master
HimbeerserverDE 2021-04-02 16:36:03 +02:00
parent 8da8634c3d
commit 29e68f0200
No known key found for this signature in database
GPG Key ID: 1A651504791E6A8B
6 changed files with 77 additions and 22 deletions

View File

@ -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
View File

@ -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
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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

View File

@ -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()