嗨,我叫Ivan,我正在Tarantool上开发高负载解决方案。我将告诉您如何以及为什么选择Pandora在Tarantool上对应用程序进行负载测试,并显示如何使用它的示例。
被测应用程序的描述
让我们测试分片队列分布式队列模块,以了解如何快速插入和检索队列任务。应用程序API基于二进制协议,该协议使您可以对数据执行基本操作,调用函数(RPC)并执行自定义lua代码。在我们的示例中,这是两个函数:queue.tube_name:put
和queue.tube_name:take
。
选择测试工具
有很多测试工具,但是我们需要在其中选择正确的工具。我们将根据以下条件进行选择:
- 您需要遵循二进制协议。因此,您将必须使用与Tarantool连接的编程语言编写代码。Jmeter,bfg,Pandora和Gatling可以做到这一点。
- . Phantom, wrk, Jmeter, Pandora Gatling.
- . , , . bfg, Pandora Gatling.
-
. . influxdb, , Jmeter Gatling. Taurus ( ). . Jmeter, Pandora, bfg Phantom. - . , — .
, : . Jmeter Pandora, Taurus Jmeter Gatling.
Jmeter Gatlling?
Java-, Java, Groovy Scala . , , , Go.
Pandora — , Go ..
Go — ?
Pandora — ?
Go.
. — ?
, , c , , , .
as code
, , .
?
, .
go get github.com/tarantool/go-tarantool \
github.com/spf13/afero \
github.com/yandex/pandora
: , .
:
type Ammo struct { Method string TubeName string Params map[string] interface {} }
. , .
: .
tnt_queue_ammo.json
:
{"Method": "put", "TubeName": "test-tube", "Params": {"data": "task"}} {"Method": "take", "TubeName": "test-tube"}
TubeName
— sharded-queue.
:
type GunConfig struct { Target []string `validate:"required"` User string `validate:"required"` Pass string `validate:"required"` }
yaml
- Pandoragun
:
gun: type: tnt_queue_gun target: - localhost:3301 - localhost:3302 user: admin pass: queue-app-cluster-cookie
.
type
.
:
type Gun struct { conn *tarantool.Connection conf GunConfig aggr core.Aggregator }
, ( Tarantool).
Bind
. . .
func (g *Gun) Bind(aggr core.Aggregator, deps core.GunDeps) error { conn, err := tarantool.Connect( g.conf.Target[rand.Intn(len(g.conf.Target))], tarantool.Opts{ User: g.conf.User, Pass: g.conf.Pass, }, ) if err != nil { log.Fatalf("Error: %s", err) } g.conn = conn g.aggr = aggr return nil }
Shoot
. . , , , .
queueCall
Tarantool go-tarantool:
func (g *Gun) Shoot(coreAmmo core.Ammo) { ammo := coreAmmo.(*Ammo) sample := netsample.Acquire(ammo.Method) code := 200 var err error startTime := time.Now() switch ammo.Method { case "put": _, err = g.queueCall(ammo.TubeName, "put", ammo.Params["data"]) case "take": _, err = g.queueCall(ammo.TubeName, "take") } sample.SetLatency(time.Since(startTime)) if err != nil { log.Printf("Error %s task: %s", ammo.Method, err) code = 500 } defer func() { sample.SetProtoCode(code) sample.AddTag(ammo.TubeName) g.aggr.Report(sample) }() }
:
- .
- ( HTTP).
- , .
: 20 . 25 . 60 . ( ) 1 .
rps:
duration: 60s
type: line
from: 20000
to: 25000
startup:
type: once
times: 1000
:
pandora:
enabled: true
package: yandextank.plugins.Pandora
pandora_cmd: ./tnt_queue_gun
config_file: ./tnt_queue_load.yaml
:
docker run -v $(pwd):/var/loadtest \
-v $SSH_AUTH_SOCK:/ssh-agent \
-e SSH_AUTH_SOCK=/ssh-agent \
--net host \
-it direvius/yandex-tank
:
Go- Tarantool, .
, queue.tube_name:ack
, ID . , InfluxDB Grafana- Overload.
有关Pandora的体系结构和功能的更多信息,您可以在Heisenbug会议上参考其创建者的报告。