性能测试资源占用问题排查及解决

img.png

img_1.png

img_5.png

img_2.png

img_3.png

问题排查

解决问题思路及优缺点

  1. 在用例运行结束时停止plugin的操作
  2. 修改NewCaseRunner,在调用initPlugin时增加限制,一个 debugtalk 只运行一次

综合考虑考虑下,采用2方式会更加稳妥,缺点可以采用分布式压测做分流问题,分布式压测后续可以通过 k8s 部署多个工作节点

解决方案

  1. 每次运行时有个唯一值,以此来确定是否需要执行 initPlugin,好在之前的设计的 debugtalk path 是唯一值,这次不用改动到其他代码
  2. 通过单例设计模式实现,因为是多线程运行,所以需要加锁
  3. 通过 map 实现可以同时运行多个实例,主要是兼容接口测试,否则不同项目访问到的可能是同一个 plugin 实例
// Package hrp NewCaseRunner 方法下把initPlugin修改成cheetahInitPlugin
package hrp

func (r *HRPRunner) NewCaseRunner(testcase *TestCase) (*CaseRunner, error) {
   caseRunner := &CaseRunner{
      testCase:  testcase,
      hrpRunner: r,
      parser:    newParser(),
   }

   // init parser plugin
   //plugin, err := initPlugin(testcase.Config.Path, r.venv, r.pluginLogOn)
   //压测运行时会同时运行多个plugin,用单例方式控制每次压测任务只能运行一个plugin
   plugin, err := cheetahInitPlugin(testcase.Config.Path, r.venv, r.pluginLogOn)

   if err != nil {
      return nil, errors.Wrap(err, "init plugin failed")
   }
   if plugin != nil {
      caseRunner.parser.plugin = plugin
      caseRunner.rootDir = filepath.Dir(plugin.Path())
   }

   // ... 省略其他代码
}
// Package hrp 增加 cheetahInitPlugin 函数
package hrp

import (
   "github.com/httprunner/funplugin"
   "github.com/pkg/errors"
   "sync"
)

var cheetahPlugin = make(map[string]*funplugin.IPlugin)
var mutex sync.Mutex

func cheetahInitPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err error) {
   plugins := cheetahPlugin[path]
   if plugins == nil {
      mutex.Lock()
      defer mutex.Unlock()
      if plugins == nil {
         plugin, err = initPlugin(path, venv, logOn)
         if err != nil {
            return nil, errors.Wrap(err, "init plugin failed")
         }
         cheetahPlugin[path] = &plugin
         plugins = &plugin
      }
   }
   return *plugins, nil
}

解决后效果

img_6.png

往期文档


↙↙↙阅读原文可查看相关链接,并与作者交流