Skip to content

Commit

Permalink
[bench] 人気者出品の前に別goroutineでbuyerのセッションを用意しておく
Browse files Browse the repository at this point in the history
  • Loading branch information
catatsuy committed Aug 29, 2019
1 parent 3f1a5c3 commit acd4e62
Showing 1 changed file with 60 additions and 41 deletions.
101 changes: 60 additions & 41 deletions bench/scenario/campaign.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package scenario

import (
"context"
"log"
"sync"
"time"

Expand All @@ -16,12 +17,52 @@ func Campaign(ctx context.Context, critical *fails.Critical) {
var wg sync.WaitGroup
closed := make(chan struct{})

// buyer用のセッションを増やしておく
// 500ユーザーを追加したら止まる
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()

L:
for j := 0; j < 50; j++ {
ch := time.After(200 * time.Millisecond)

user1 := asset.GetRandomBuyer()
s, err := loginedSession(ctx, user1)
if err != nil {
// ログインに失敗しまくるとプールに溜まらないので一気に購入できなくなる
// その場合は失敗件数が多いという理由で失格にする
critical.Add(err)
goto Final
}
BuyerPool.Enqueue(s)

Final:
select {
case <-ch:
case <-ctx.Done():
break L
}
}
}()
}

wg.Add(1)
go func() {
defer wg.Done()
<-time.After(7 * time.Second)

L:
for j := 0; j < ExecutionSeconds/10; j++ {
ch := time.After(10 * time.Second)

popularListing(ctx, critical)
isIncrease := popularListing(ctx, critical, 80)

if isIncrease {
// goroutineを増やす
log.Print("increase")
}

select {
case <-ch:
Expand All @@ -44,36 +85,12 @@ func Campaign(ctx context.Context, critical *fails.Critical) {

// popularListing is 人気者出品
// 人気者が高額の出品を行う。高額だが出品した瞬間に大量の人が購入しようとしてくる。もちろん購入できるのは一人だけ。
func popularListing(ctx context.Context, critical *fails.Critical) {
// buyerが足りない分を準備しておく
if l := BuyerPool.Len(); l < 50 {
count := 60 - l

var wg sync.WaitGroup

for i := 0; i < count/5; i++ {
for j := 0; j < 5; j++ {
wg.Add(1)

go func() {
defer wg.Done()

user1 := asset.GetRandomBuyer()
s, err := loginedSession(ctx, user1)
if err != nil {
// ログインに失敗しまくるとプールに溜まらないので一気に購入できなくなる
// その場合は失敗件数が多いという理由で失格にする
critical.Add(err)
return
}
BuyerPool.Enqueue(s)
}()
}
// 一気にログインするとアプリケーションがしんどいのでほどほどにする
<-time.After(100 * time.Millisecond)
}

wg.Wait()
func popularListing(ctx context.Context, critical *fails.Critical, num int) (isIncrease bool) {
// buyerが足りない場合はログインを意図的に遅くしている可能性があるのでペナルティとして実行しない
l := BuyerPool.Len()
if l < num+10 {
log.Printf("login user insufficient (count: %d)", l)
return false
}

// 真のbuyerが入るチャネル。複数来たらエラーにする
Expand All @@ -82,20 +99,20 @@ func popularListing(ctx context.Context, critical *fails.Critical) {
popular, err := buyerSession(ctx)
if err != nil {
critical.Add(err)
return
return false
}

price := 1000

targetItemID, err := sell(ctx, popular, price)
if err != nil {
critical.Add(err)
return
return false
}

var wg sync.WaitGroup

for i := 0; i < 50; i++ {
for i := 0; i < num; i++ {
wg.Add(1)
go func() {
defer wg.Done()
Expand Down Expand Up @@ -137,7 +154,7 @@ func popularListing(ctx context.Context, critical *fails.Critical) {
case <-closed:
// 全goroutineが終了したのにbuyerがいない場合は全員が購入に失敗している
critical.Add(failure.New(fails.ErrApplication, failure.Messagef("商品 (item_id: %d) に対して全ユーザーが購入に失敗しました", targetItemID)))
return
return false
}

defer func() {
Expand All @@ -161,36 +178,38 @@ func popularListing(ctx context.Context, critical *fails.Critical) {
reserveID, apath, err := popular.Ship(ctx, targetItemID)
if err != nil {
critical.Add(err)
return
return false
}

md5Str, err := popular.DownloadQRURL(ctx, apath)
if err != nil {
critical.Add(err)
return
return false
}

sShipment.ForceSetStatus(reserveID, server.StatusShipping)
if !sShipment.CheckQRMD5(reserveID, md5Str) {
critical.Add(failure.New(fails.ErrApplication, failure.Messagef("QRコードの画像に誤りがあります (item_id: %d, reserve_id: %s)", targetItemID, reserveID)))
return
return false
}

err = popular.ShipDone(ctx, targetItemID)
if err != nil {
critical.Add(err)
return
return false
}

ok := sShipment.ForceSetStatus(reserveID, server.StatusDone)
if !ok {
critical.Add(failure.New(fails.ErrApplication, failure.Messagef("配送予約IDに誤りがあります (item_id: %d, reserve_id: %s)", targetItemID, reserveID)))
return
return false
}

err = buyer.Complete(ctx, targetItemID)
if err != nil {
critical.Add(err)
return
return false
}

return true
}

0 comments on commit acd4e62

Please sign in to comment.