Flamingo
A go framework for handling many (like millions, hopefully) of concurrent, long-held connections and
interacting with them in a pipeline-style manner.
Usage
Here's an example echo server written using flamingo:
package main
import (
"fmt"
"runtime"
"os"
"strconv"
"time"
"flamingo"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
args := os.Args
if len(args) < 2 { panic("Need to supply port number") }
portStr := args[1]
port,_ := strconv.Atoi(portStr)
flamingo := flamingo.New(flamingo.Opts{
Port: port,
ActivityTimeout: 5 * time.Second,
BufferSize: 1024,
BufferTillDelim: true,
Delim: '\n',
})
fmt.Printf("Port created\n")
go func() {
for {
id,conn := flamingo.RecvOpen()
fmt.Printf("Got open for %d: %v\n",id,conn)
}
}()
for i:=0;i<10;i++ {
go func() {
for {
id,msg := flamingo.RecvData()
flamingo.SendData(id,msg)
}
}()
}
go func() {
for {
id := flamingo.RecvClose()
fmt.Printf("Got close for %d\n",id)
}
}()
select {}
}
What/How/Why?
One of problems with highly concurrent systems is that of routing. For example, in a pub/sub server,
when a publish happens the server must get the list of connections from some datastore (or memory)
and loop through them. But what is that list? If the datastore is external to the program it's
probably a list of strings or integers. How to map those identifiers to socket descriptors? Flamingo
takes care of that. All sockets are identified by a single, serializable identifier, and flamingo
deals with the job of routing to an actual socket descriptor.
Limitations
Currently the most obvious limitation of flamingo is in socket data buffering. If the messages you're
going to be receiving on your sockets are anything more complicated then data ending in a specific
delimiter you're going to have a difficult time. I'm still trying to think of the best solution for
this, and will absolutely take suggestions if anyone has any.
Todo
Flamingo is still in development and is far from being stable or production ready. Things to-do:
- Make it possible to set socket options on the listen socket
- Make workers have the ability to buffer data until they find some delimiter, because with the current
setup that's really difficult for the application to do.
- Make it possible to get status information out (number of connections, etc...)
- Make some real documentation
- Load test this thing, haven't done so since the first iteration, of which only the core code is left
- Method for serializing the id