zoukankan      html  css  js  c++  java
  • Gatling-插件开发


    源码

    参考:
    How to Write a Custom Protocol for Gatling?
    Creating a custom Gatling prococol for AWS Lambda

    插件开发

    Action

    package io.gatling.ext.redis.action
    
    import java.util.concurrent.Executors
    
    import com.typesafe.scalalogging.StrictLogging
    import io.gatling.commons.stats.{KO, OK}
    import io.gatling.commons.util.Clock
    import io.gatling.core.CoreComponents
    import io.gatling.core.action.{Action, ExitableAction}
    import io.gatling.core.session.{Expression, Session}
    import io.gatling.core.stats.StatsEngine
    import io.gatling.core.util.NameGen
    import io.gatling.ext.redis.protocol.RedisComponents
    import redis.clients.jedis.Jedis
    
    import scala.concurrent._
    import scala.util.{Failure, Success}
    
    
    class RedisGetAction(
                          key: Expression[String],
                          coreComponents: CoreComponents,
                          val redisComponents: RedisComponents,
                          throttled: Boolean,
                          val next: Action
                        ) extends ExitableAction with NameGen with StrictLogging {
    
      // 可以自定义也可以引入默认的执行器
      // import scala.concurrent.ExecutionContext.Implicits.global
      implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(50))
    
      override def statsEngine: StatsEngine = coreComponents.statsEngine
    
      override def clock: Clock = coreComponents.clock
    
      override def name: String = genName("redis-get-action")
    
      override def execute(session: Session): Unit = {
    
        key(session) map {
    
          keyS => {
    
            val requestStartDate = clock.nowMillis
    
            val jedis: Jedis = redisComponents.jedisMap(session.userId)
    
            val future: Future[String] = Future[String] {
              jedis.get(keyS)
            }
    
            future onComplete {
              case Success(value) => statsEngine.logResponse(
                session,
                keyS,
                requestStartDate,
                clock.nowMillis,
                OK,
                Some(value),
                Some(value)
              )
              case Failure(exception) => {
                logger.error(exception.toString)
                statsEngine.logResponse(
                  session,
                  keyS,
                  requestStartDate,
                  clock.nowMillis,
                  KO,
                  Some(exception.getMessage),
                  Some(exception.getMessage)
                )
              }
            }
    
            if (throttled) {
              coreComponents.throttler.throttle(session.scenario, () => next ! session)
            } else {
              next ! session
            }
          }
        }
      }
    }
    

    ActionBuilder

    package io.gatling.ext.redis.builder
    
    import com.typesafe.scalalogging.StrictLogging
    import io.gatling.core.action.Action
    import io.gatling.core.action.builder.ActionBuilder
    import io.gatling.core.session.Expression
    import io.gatling.core.structure.ScenarioContext
    import io.gatling.ext.redis.action.RedisGetAction
    import io.gatling.ext.redis.protocol.RedisProtocol
    
    class RedisActionBuilder(key: Expression[String]) extends ActionBuilder with StrictLogging {
    
      override def build(ctx: ScenarioContext, next: Action): Action = {
    
        import ctx._
        new RedisGetAction(
          key,
          coreComponents,
          protocolComponentsRegistry.components(RedisProtocol.redisProtocolKey),
          throttled,
          next
        )
      }
    }
    

    Protocol & Components & Components

    package io.gatling.ext.redis.protocol
    
    import io.gatling.core.config.GatlingConfiguration
    import io.gatling.core.protocol.{Protocol, ProtocolComponents, ProtocolKey}
    import io.gatling.core.session.Session
    import io.gatling.core.{CoreComponents, protocol}
    import redis.clients.jedis.Jedis
    
    case class RedisProtocol(host: String, port: Int, password: Option[String]) extends Protocol {
      type Components = RedisComponents
    }
    
    object RedisProtocol {
    
      def apply(host: String, port: Int, password: Option[String] = None): RedisProtocol = new RedisProtocol(host, port, password)
    
      val redisProtocolKey: ProtocolKey[RedisProtocol, RedisComponents] = new ProtocolKey[RedisProtocol, RedisComponents] {
    
        override def protocolClass: Class[protocol.Protocol] = classOf[RedisProtocol].asInstanceOf[Class[io.gatling.core.protocol.Protocol]]
    
        override def defaultProtocolValue(configuration: GatlingConfiguration): RedisProtocol = RedisProtocol("127.0.0.1", 6379)
    
        override def newComponents(coreComponents: CoreComponents): RedisProtocol => RedisComponents = {
          redisProtocol => RedisComponents(redisProtocol)
        }
      }
    }
    
    case class RedisComponents(redisProtocol: RedisProtocol) extends ProtocolComponents {
    
      val jedisMap: scala.collection.mutable.Map[Long, Jedis] = scala.collection.mutable.HashMap()
    
      override def onStart: Session => Session = {
        session => {
          println("RedisComponents start: " + session)
          val jedis: Jedis = new Jedis(redisProtocol.host, redisProtocol.port)
    
          redisProtocol.password match {
            case Some(value) => jedis.auth(value)
            case None =>
          }
    
          jedis.set(String.valueOf(session.userId), session.toString)
    
          jedisMap(session.userId) = jedis
    
          session
        }
      }
    
      override def onExit: Session => Unit = {
        session => {
          println("RedisComponents exit: " + session)
        }
      }
    }
    
    case class RedisProtocolBuilder(host: String, port: Int, password: Option[String]) {
      def build: RedisProtocol = RedisProtocol(host, port, password)
    }
    
    object RedisProtocolBuilder {
      implicit def toRedisProtocol(builder: RedisProtocolBuilder): RedisProtocol = builder.build
    }
    

    Predef

    package io.gatling.ext.redis
    
    import io.gatling.core.session.Expression
    import io.gatling.ext.redis.builder.RedisActionBuilder
    import io.gatling.ext.redis.protocol.RedisProtocolBuilder
    
    object Predef {
    
      implicit def string2Option(string: String): Option[String] = Some(string)
      
      def redis(
                 host: String,
                 port: Int,
                 password: Option[String] = None
               ): RedisProtocolBuilder = RedisProtocolBuilder(host, port, password)
    
      def redis(key: Expression[String]): RedisActionBuilder = new RedisActionBuilder(key)
    }
    

    使用中遇到的问题

    如果要在DSL中使用hours、minutes等,需要导包:scala.concurrent.duration._
    Expression的本质是一个函数:session => type Expression[T] = Session => Validation[T]
    Validation中常用的两个函数:
    1. def map[A](f: T => A): Validation[A]
    2. def flatMap[A](f: T => Validation[A]): Validation[A]
  • 相关阅读:
    【数据结构】算法 Invert Binary Tree 翻转二叉树
    雪碧图
    闭包
    正则那些事
    JS添加,删除表格中的行那些事
    三目运算
    10个不能重复的随机数要求为55-109的整数, 要将10个随机数打印出来,并且将10个随机数里面能够被5整除的数打印出来,最后将能够被5整除的数叠加的结果打印出来
    输出从小到大排序好的五个不重复的随机整数,范围[10-23)。努力的人全世界都为你让路!你的努力终将美好!
    随机取10个在55-80之间的数,按照从小到大排序输出,冒泡排序
    求10个随机数,随机数要求为25-99的整数.能够被3整除的数
  • 原文地址:https://www.cnblogs.com/CSunShine/p/12737746.html
Copyright © 2011-2022 走看看