A presentation about combining the powers of the Go language and Asterisk in order to provide fast, reliable and hugely scalable voice applications. A brief introduction about why Go presents a big opportunity for the asterisk community, a primer into developing FastAGI applications, demonstration of the AGI package [1] and a walk through the idioms and challenges of developing in Go. The talk is focused mainly on our experience of porting existing code into Go with the aim to scale our services to larger numbers accompanied with benchmarks and an introduction to some tools [2] we developed to help us test, debug and benchmark AGI applications.
2. Who we are
VoIP engineer at NTA ltd
Voice and text toolset
- Flite Asterisk App
- eSpeak Asterisk App
- googleTTS
- speech recognition - Google speech API
- Text translation
github.com/zaf
3. Who we are
NTA Ltd - nta.co.uk
- UK based VoIP provider since 2001
- Hosted PBX services
- SIP
- FOSS
- Kamailio / Asterisk
- Perl
4. Perl stack
- FastAGI server
- Net::Server
- fork / prefork
- Memory
- Capacity - calls / server
5. Enter Go
2007 Google
Rob Pike, Ken Thompson, Robert Griesemer
- Statically typed
- Garbage-collected
- Natively compiled
- Concurrency
- C family
- Pragmatic, minimalistic
6. Enter Go
Do not communicate by sharing memory.
Share memory by communicating.
- Goroutines
lightweight threads
cheap
multiplexed in OS threads
- Channels
communication
synchronization
7. Enter Go
/*
A simple example in go
*/
package main
import "fmt"
func main() {
var msg string
msg = "Hello Astricon"
// Retroactively say hello to all Astricons!
for i := 0; i <= 10; i++ {
fmt.Println(msg, 2004+i)
}
}
8. Go toolset
- go command
test
fmt
build
install
- Debugging
gdb
- Package management
go get
9. AGI Package
- AGI and FastAGI support
- Simple familiar interface
- BSD Licence
- Install:
go get github.com/zaf/agi
10. AGI Package
- Session structure
AGI environment variables
Env map[string]string
- Reply structure
Numeric result of the AGI command
Res int
Additional returned data
Dat string
11. AGI Package
- AGI commands as methods of the Session struct
func (a *Session) Answer() (Reply, error)
func (a *Session) SendText(text string) (Reply,
error)
func (a *Session) Hangup(channel ...string)
(Reply, error)
func (a *Session) SayDigits(digit int,
escape string) (Reply, error)
12. AGI Package usage
- Create a new session:
myAgi := agi.New()
- Initialize, read and parse AGI environment:
myAgi.Init(nil)
- Execute AGI commands:
myAgi.StreamFile("hello-world", "#")
13. AGI example
package main
import (
"log"
"github.com/zaf/agi"
)
func main() {
// Create a new AGI session and Parse the AGI environment.
myAgi := agi.New()
err := myAgi.Init(nil)
if err != nil {
log.Fatalf("Error Parsing AGI environment: %vn", err)
}
// Print a message on the asterisk console using Verbose.
_, err := myAgi.Verbose("Hello World")
if err != nil {
log.Fatalf("AGI reply error: %vn", err)
}
}
14. FastAGI Example
func main() {
// Create a tcp listener on port 4573 and start a new goroutine for each connection.
ln, err := net.Listen("tcp", ":4573")
if err != nil {
log.Fatal(err)
}
defer ln.Close()
for {
conn, err := ln.Accept()
if err != nil {
log.Println(err)
continue
}
go connHandle(conn)
}
}
17. AGI Debug
- Error testing
- Performance testing
- Security testing
Eliminate the use of Asterisk
Custom AGI Payloads
18. Agistress
A client that can connect to servers using the Asterisk Gateway
Interface
- user defined payloads
- user controlled session parameters
- fast - parallel session spawning
- performance measuring
- written in Go
go get github.com/zaf/agistress
19. Agistress
Run once and display full debug output of the AGI session:
agistress -host 127.0.0.1 -single
Stress test the AGI server by spawning 10 sessions 10 times per
second and display performance details:
agistress -host 127.0.0.1 -sess 10 -runs 10
Run once using custom AGI payload from config file:
agistress -host 127.0.0.1 -single -conf payload.conf