I'm working on a api written with Go, that has a main goal that it should answer the request as fast as possible. I came up with using goroutines.
I test it with wrk with this command:
$ wrk -t1 -c200 -d1s http://127.0.0.1:8080
// this passes
...
21efef3
21efef3
21efef3
21efef3
21efef3
21efef3
21efef3
...
$ wrk -t1 -c400 -d1s http://127.0.0.1:8080
// this test fails with this error returned in go terminal
...
21efef3
21efef3
21efef3
21efef3
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x6ada46]
goroutine 2325 [running]:
github.com/gocql/gocql.(*Session).Close(0x0)
/home/mda/.local/go/src/github.com/gocql/gocql/session.go:336 +0x26
panic(0x707f40, 0x8ed650)
/usr/lib/go-1.8/src/runtime/panic.go:489 +0x2cf
github.com/gocql/gocql.(*Session).Query(0x0, 0x777d4c, 0x34, 0xc428cfd190, 0x1, 0x1, 0x0)
/home/mda/.local/go/src/github.com/gocql/gocql/session.go:294 +0x26
main.getData()
/home/mda/code/api-go/main2.go:45 +0x1f6
created by main.main.func1
/home/mda/code/api-go/main2.go:18 +0x39
exit status 2
Process finished with exit code 1
Cassandra seems to work fine
$ cassandra-stress read n=200000 -pop seq=1..200000 -rate threads=200 -node 127.0.0.1
Results:
Op rate : 14,090 op/s [READ: 14,090 op/s]
Partition rate : 14,090 pk/s [READ: 14,090 pk/s]
Row rate : 14,090 row/s [READ: 14,090 row/s]
Latency mean : 14.1 ms [READ: 14.1 ms]
Latency median : 9.7 ms [READ: 9.7 ms]
Latency 95th percentile : 39.4 ms [READ: 39.4 ms]
Latency 99th percentile : 72.1 ms [READ: 72.1 ms]
Latency 99.9th percentile : 218.1 ms [READ: 218.1 ms]
Latency max : 346.8 ms [READ: 346.8 ms]
Total partitions : 200,000 [READ: 200,000]
Total errors : 0 [READ: 0]
Total GC count : 14
Total GC memory : 4.346 GiB
Total GC time : 0.4 seconds
Avg GC time : 31.9 ms
StdDev GC time : 9.4 ms
Total operation time : 00:00:14
This is a simplified version of my Go code:
package main
import (
"fmt"
"log"
"github.com/buaazp/fasthttprouter"
"github.com/valyala/fasthttp"
"github.com/valyala/fasthttp/reuseport"
"github.com/gocql/gocql"
)
var cluster *gocql.ClusterConfig
func main() {
router := fasthttprouter.New()
router.GET("/", func(ctx *fasthttp.RequestCtx) {
// We need this goroutine
go getData()
fmt.Fprint(ctx, "Welcome to home!")
ctx.Response.Header.ConnectionClose()
})
ln, err := reuseport.Listen("tcp4", ":8080")
if err != nil {
log.Fatalf("error in reuseport listener: %s", err)
}
if err = fasthttp.Serve(ln, router.Handler); err != nil {
log.Fatalf("error in fasthttp Server: %s", err)
}
}
func setup_cluster() {
cluster = gocql.NewCluster("127.0.0.1:9042")
cluster.Keyspace = "myKeySpace"
cluster.Consistency = gocql.One
}
func getData() {
if cluster == nil {
setup_cluster()
}
session, _ := cluster.CreateSession()
defer session.Close()
var id string
var value string
if err := session.Query(`SELECT id, ads FROM product_ads
WHERE id = ? LIMIT 1`,
"213").Consistency(gocql.One).Scan(&id, &value); err != nil {
log.Fatal(err)
}
// ... do some stuff with id & value
fmt.Println(value)
}
here is the process limits of my go code and cassandra, they have the same values set for different users:
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 32768 32768 processes
Max open files 1000000 1000000 files
Max locked memory unlimited unlimited bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 31265 31265 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
what do you suggest? why Go fails to create new session?