YOU ARE DOWNLOADING DOCUMENT

Please tick the box to continue:

Transcript
Page 1: Scaling FastAGI Applications with Go

Scaling FastAGI Applications with Go

Lefteris Zafiris NTA LtdAstricon 2014 Las Vegas

Page 3: Scaling FastAGI Applications with Go

Who we are

NTA Ltd - nta.co.uk

- UK based VoIP provider since 2001- Hosted PBX services- SIP- FOSS- Kamailio / Asterisk- Perl

Page 4: Scaling FastAGI Applications with Go

Perl stack

- FastAGI server

- Net::Server

- fork / prefork

- Memory

- Capacity - calls / server

Page 5: Scaling FastAGI Applications with Go

Enter Go

2007 Google

Rob Pike, Ken Thompson, Robert Griesemer

- Statically typed- Garbage-collected- Natively compiled- Concurrency- C family- Pragmatic, minimalistic

Page 6: Scaling FastAGI Applications with Go

Enter Go

Do not communicate by sharing memory.

Share memory by communicating.

- Goroutines

lightweight threads

cheap

multiplexed in OS threads

- Channels

communication

synchronization

Page 7: Scaling FastAGI Applications with Go

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

Page 8: Scaling FastAGI Applications with Go

Go toolset

- go command

testfmtbuildinstall

- Debugging

gdb- Package management

go get

Page 9: Scaling FastAGI Applications with Go

AGI Package

- AGI and FastAGI support

- Simple familiar interface

- BSD Licence

- Install:

go get github.com/zaf/agi

Page 10: Scaling FastAGI Applications with Go

AGI Package

- Session structure

AGI environment variables

Env map[string]string

- Reply structure

Numeric result of the AGI command

Res intAdditional returned data

Dat string

Page 11: Scaling FastAGI Applications with Go

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)

Page 12: Scaling FastAGI Applications with Go

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", "#")

Page 13: Scaling FastAGI Applications with Go

AGI examplepackage 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: %v\n", err) } // Print a message on the asterisk console using Verbose. _, err := myAgi.Verbose("Hello World") if err != nil { log.Fatalf("AGI reply error: %v\n", err) }}

Page 14: Scaling FastAGI Applications with Go

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

Page 15: Scaling FastAGI Applications with Go

FastAGI Examplefunc connHandle(c net.Conn) { defer c.Close() myAgi := agi.New() // Create I/O buffers rw := bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c)) err := myAgi.Init(rw) if err != nil { log.Println(err) return } rep, err := myAgi.StreamFile("hello", "1234567890#*") if err != nil { log.Println(err) return }

// Check AGI command return value if rep.Res == -1 { log.Println("Failed to playback file") }}

Page 16: Scaling FastAGI Applications with Go

Error Handlingfunc connHandle(c net.Conn) { defer func() { c.Close() if err := recover(); err != nil { log.Println("Session terminated:", err) } }() myAgi := agi.New() rw := bufio.NewReadWriter(bufio.NewReader(c), bufio.NewWriter(c)) err := myAgi.Init(rw) checkErr(err) _, err := myAgi.Verbose("Hello World") checkErr(err)}//Check for AGI Protocol errors or hangupsfunc checkErr(e error) { if e != nil { panic(e) }}

Page 17: Scaling FastAGI Applications with Go

AGI Debug

- Error testing- Performance testing- Security testing

Eliminate the use of Asterisk

Custom AGI Payloads

Page 18: Scaling FastAGI Applications with Go

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

Page 19: Scaling FastAGI Applications with Go

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

Page 20: Scaling FastAGI Applications with Go

Agistress

Config file:

- JSON format

- Environment variables

- AGI Command replies

- Reply delay

Page 21: Scaling FastAGI Applications with Go

Agistress

Config file sample:

{"AgiPayload": [

{"Msg": "200 result=0", "Delay": 10}, {"Msg": "200 result=0", "Delay": 10}, {"Msg": "200 result=1 endpos=1234", "Delay": 3000}, {"Msg": "HANGUP"}

]}

Page 22: Scaling FastAGI Applications with Go

Agistress

Sample output:Running FastAGI bench against: 192.168.1.10:4573Press Enter to stop.

A new run each: 100msSessions per run: 10Reply delay: 50ms

FastAGI SessionsActive: 20Completed: 520Duration: 206121479 ns (last 10000 sessions average)Failed: 0

Page 23: Scaling FastAGI Applications with Go

Measuring

Comparison between FastAGI implementations:

- Perl:

Asterisk::AGI

Net::Server::PreFork

- Go:

agi package

net package

Page 24: Scaling FastAGI Applications with Go

Measuring

Simple sound file Playback application:

- Start session and parse AGI Env- Parse FastAGI request URI

agi://10.11.12.13/myagi?file=echo-test

- Check channel status- Answer channel- Playback given file

Perl: 73 loc (http://goo.gl/hdsxuw)

Go: 90 loc (http://goo.gl/uxezg7)

Page 25: Scaling FastAGI Applications with Go

Benchmark

Stress test using agistress:- 1 session/sec

agistress -delay=0- 25 sessions/sec

agistress -runs=5 -sess=5 -delay=0- 50 sessions/sec

agistress -runs=10 -sess=5 -delay=0- 100 sessions/sec

agistress -runs=10 -sess=10 -delay=0- 200 and 400 sessions/sec

Page 26: Scaling FastAGI Applications with Go
Page 27: Scaling FastAGI Applications with Go

Benchmark

Memory usage:

Many active sessions

Custom AGI Payload, 5 sec playback duration

- 12 active sessions:

agistress -sess=2 -conf=sample.conf

- 24 active sessions:

agistress -sess=4 -conf=sample.conf

- 48, 96 and 192 sessions

Page 28: Scaling FastAGI Applications with Go
Page 29: Scaling FastAGI Applications with Go

Results

- Up to 3 times less CPU usage

- Up to 2.5 times shorter runtime

- Enormous memory savings

Page 30: Scaling FastAGI Applications with Go

Thank You!


Related Documents