Go プロジェクトのステップ記録を記録する

間違った説明

  • goプロジェクトでスクリプトを作成し、main関数を書きました
  • モデルを使用するものgithub.com/link1st/go-stress-testing/stress
import (
    "fmt"
    // "github.com/dji/go-stress-testing/stress"
	"github.com/link1st/go-stress-testing/stress"
    "net/http"
    "time"
)
  • を実行するとgo run xxx.goエラーが報告されます
queries.go:6:2: no required module provides package github.com/link1st/go-stress-testing/stress; to add it:
        go get github.com/link1st/go-stress-testing/stress
  • go get github.com/link1st/go-stress-testing/stress不足しているモジュールをダウンロードするためのコマンドの使用を求めるプロンプト
  • 案の定、実行後もエラーが報告されます
go: github.com/link1st/go-stress-testing/stress: no matching versions for query "upgrade"
  • モジュールに利用可能な新しいバージョンがないことを示します
  • 指定されたバージョン:go get github.com/link1st/go-stress-testing/stress@latest
  • まだターゲットバージョンを取得できないというエラーが表示されます

github でモジュールのバージョン情報を検索する

  • 検索テクニックはlanguage:go model_name次のとおりです
    • 画像.png
  • モジュールのバージョン情報を表示する
  • 画像.png

インストールするバージョンを指定する

go get github.com/link1st/go-stress-testing/stress@v1.0.5
  • 物事が常にうまくいくとは限らず、それでもエラーが報告される
    • go: github.com/link1st/go-stress-testing/[email protected]: invalid version: unknown revision stress/v1.0.5

手動ビルド

  • 情報を参照した後、Maven プロジェクトのセカンドパーティ ライブラリと同様に、プロジェクトを手動でビルドしてモジュールをインストールできます。

  1. まず、go プロジェクトの依存モジュールがどこにインストールされているかを確認します。
    1. $GOPATH/pkg/mod/ディレクトリの下にある
    2. Maven のローカル リポジトリの .m2 ディレクトリに似ています。モジュールのストレージ構造も同様です
  2. 次に、github.com/link1st/go-stress-testing/stressプロジェクトのソースコードを ダウンロードします。
    1. クローンされたコードはデフォルトで master ブランチに設定されます
    2. git checkout v1.0.5
  3. go build
    • -o: 出力ファイルの名前とパスを指定します。
    • -v: コンパイルされた Go パッケージの名前を出力します。
    • -a: キャッシュされた結果を使用せずにすべてのパッケージを強制的に再コンパイルします。
    • -race: データ競合検出機能が Go プログラム内のデータ競合を識別して報告できるようにします。
    • -tags: 使用するビルド タグを指定します。
  4. 完全なコマンドgo build -o /Users/duzhihao/go/pkg/mod/github.com/link1st/go-stress-testing/[email protected] main.go
    1. でもまだうまくいかない

問題の根本

  1. 必要なパッケージは、github.com/link1st/go-stress-testing/stress
  2. このパッケージをどのように解釈するかを明確にしてください
    1. github.com: モジュールは github から取得されます
    2. link1st: 著者はlink1stです
    3. go-stress-testing: go-stress-testingプロジェクト所属
    4. stress: プロジェクトの下のストレスモジュール
  3. このモジュールを見つけるには github プロジェクトに移動してください
  4. 画像.png
  5. いいやつです、ストレスモジュールはまったくありません。

最終的解決

別の方法でストレスモジュールの下にソースコードを見つけました。ファイルは合計 4 つあります。

task.go

package stress

import (
    "context"
    "errors"
)

// Task represents a stress testing task, which consists of a name, a RunFunc function and optional StopFunc function
type Task struct {
    
    
    Name      string
    RunFunc   func() error
    StopFunc  func() error
    Context   context.Context
    Cancel    context.CancelFunc
}

// Run runs the Task and returns a TestResult
func (t *Task) Run() *TestResult {
    
    
    var requests uint64
    var errors uint64

    for {
    
    
        select {
    
    
        case <-t.Context.Done():
            return &TestResult{
    
    
                Requests: requests,
                Errors:   errors,
            }
        default:
            if err := t.RunFunc(); err != nil {
    
    
                errors++
            }
            requests++
        }
    }
}

// NewTask returns a new Task with the given name and RunFunc function
func NewTask(name string, runFunc func() error) *Task {
    
    
    ctx, cancel := context.WithCancel(context.Background())
    return &Task{
    
    
        Name:     name,
        RunFunc:  runFunc,
        Context:  ctx,
        Cancel:   cancel,
    }
}

// NewTimedTask returns a new Task with the given name, RunFunc function and duration
func NewTimedTask(name string, runFunc func() error, duration int) *Task {
    
    
    ctx, cancel := context.WithTimeout(context.Background(), Duration(duration)*time.Second)
    return &Task{
    
    
        Name:     name,
        RunFunc:  runFunc,
        StopFunc: cancel,
        Context:  ctx,
        Cancel:   cancel,
    }
}

// Stop stops the Task
func (t *Task) Stop() error {
    
    
    if t.StopFunc == nil {
    
    
        return errors.New("Stop function is not defined")
    }

    return t.StopFunc()
}

シーンゴー

package stress


import (
    "sync"
    "sync/atomic"
    "time"
)


// Scene represents a stress testing scene, which consists of multiple tasks
type Scene struct {
    
    
    Name        string
    Frequency   time.Duration
    Duration    time.Duration
    SetupFunc   func() error
    CleanupFunc func() error
    tasks       []*Task
}


// AddTask adds a new Task to the Scene
func (s *Scene) AddTask(task *Task) {
    
    
    s.tasks = append(s.tasks, task)
}


// Run runs the Scene and returns a TestResult
func (s *Scene) Run() *TestResult {
    
    
    resCh := make(chan *TestResult)
    wg := sync.WaitGroup{
    
    }


    wg.Add(len(s.tasks))


    for _, task := range s.tasks {
    
    
        go func(task *Task) {
    
    
            defer wg.Done()
            resCh <- task.Run()
        }(task)
    }


    if s.SetupFunc != nil {
    
    
        if err := s.SetupFunc(); err != nil {
    
    
            panic(err)
        }
    }


    ticker := time.NewTicker(s.Frequency)
    stop := make(chan bool)


    go func() {
    
    
        time.Sleep(s.Duration)
        close(stop)
    }()


    var requests uint64
    var errors uint64


loop:
    for {
    
    
        select {
    
    
        case <-ticker.C:
            for _, task := range s.tasks {
    
    
                for i := 0; i < requestsPerTask; i++ {
    
    
                    if err := task.RunFunc(); err != nil {
    
    
                        atomic.AddUint64(&errors, 1)
                    }
                    atomic.AddUint64(&requests, 1)
                }
            }
        case res := <-resCh:
            atomic.AddUint64(&requests, res.Requests)
            atomic.AddUint64(&errors, res.Errors)
        case <-stop:
            break loop
        }
    }


    ticker.Stop()


    if s.CleanupFunc != nil {
    
    
        if err := s.CleanupFunc(); err != nil {
    
    
            panic(err)
        }
    }


    wg.Wait()


    elapsed := time.Duration(requests) * time.Second / time.Duration(rps)
    return &TestResult{
    
    
        Requests: requests,
        Errors:   errors,
        Rps:      rps,
        Elapsed:  elapsed,
    }
}


// NewScene returns a new Scene with the given name and default settings
func NewScene(name string) *Scene {
    
    
    return &Scene{
    
    
        Name:      name,
        Frequency: time.Second,
        Duration:  10 * time.Second,
        SetupFunc: func() error {
    
    
            return nil
        },
        CleanupFunc: func() error {
    
    
            return nil
        },
    }
}

test_result.go

package stress


import "time"


// TestResult represents the result of a stress test
type TestResult struct {
    
    
    Requests uint64
    Errors   uint64
    Rps      uint64
    Elapsed  time.Duration
}

utils.go

package stress


import "time"


const (
    requestsPerTask = 100
    rps             = 100
)


// Duration is an int that can be used with the time package
type Duration int


func (d Duration) String() string {
    
    
    return time.Duration(d * time.Second).String()
}

これらの go ファイルのコードは信頼できないため、実際のアプリケーションの要件に応じてロジックの適応を実行する必要があることに注意してください。

おすすめ

転載: blog.csdn.net/GoNewWay/article/details/130997639