Gatling如何实现每个虚拟用户单独执行一次JWT生成及ConnectToken请求
问题根因
你当前代码的问题出在Scala对象的初始化逻辑上:GetTokenRequest是单例对象,对象内的get_token是val类型,会在对象首次加载时一次性执行完成所有逻辑,makeJwt(props)只会调用一次生成全局固定的JWT值,后续所有虚拟用户发起请求时,client_assertion参数绑定的都是这个提前生成好的固定值,自然不会每个用户单独生成。
改造方案
我们可以把固定配置提前初始化避免重复计算,再通过Gatling的会话函数实现每个用户执行时动态生成JWT:
- 将固定的属性配置、文件路径等内容提前初始化,不需要每个用户重复创建
- 新增会话处理步骤,在用户发起获取token请求前,为当前用户单独生成JWT并存入用户私有会话
- 调整
client_assertion参数的取值逻辑,从当前用户的会话中读取独有的JWT值
改造后代码
import java.io.File import java.util.Properties import io.gatling.core.Predef._ import io.gatling.http.Predef._ import config.Config._ import util._ import headers.Headers._ object GetTokenRequest extends JwtGeneratorRSA{ // 提前初始化固定配置,避免每个用户重复创建,节省性能 private val props = new Properties // 路径和固定参数只初始化一次 private val current = new File(".").getCanonicalPath props.put("issuer","cfa9c8fb-8dd6-4d7c-b142-786c3d774f64"); props.put("audience",app_url+"/connect/token"); props.put("resource","testRes"); props.put("consumer_org","testOrg"); props.put("scope","openid profile helseid://scopes/identity/pid"); props.put("token.endpoint",app_url + "/connect/token"); props.put("keystore.file",current+"/src/test/resources/data/cfa9c8fb-8dd6-4d7c-b142-786c3d774f64.p12"); props.put("keystore.password","AYiPf1mZYOY60XV0tCuPIFk9UaGiOg1K"); props.put("keystore.alias",""); props.put("keystore.alias.password",""); // 每个用户独立执行的逻辑 val get_token = exec( // 会话处理函数:每个用户执行到这一步都会单独生成JWT存入自己的会话 session => { val jwt = makeJwt(props) // 将生成的JWT存入当前用户私有会话 session.set("client_jwt", jwt) } ).exec( http("ConnectToken") .post(app_url + "/connect/token") .headers(headers_0) .formParam("grant_type", "${grant_type}") // 从当前用户会话中读取独有的JWT .formParam("client_assertion", "${client_jwt}") .formParam("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") .formParam("client_id", "${client_id}") .formParam("scope", "${scope}") .check(regex("access_token\":\"(.*?)\"").saveAs("access_token")) ) // 若需要打印每个用户的JWT,可调整会话函数为如下写法: // session => { // val jwt = makeJwt(props) // println(s"用户${session.userId}的JWT: $jwt") // session.set("client_jwt", jwt) // } }
调用方式保持原有写法即可,注意feeder的位置:
// feeder要放在exec前面,保证参数能正确读取到会话中 .feed(csv("data/TestDataTest.csv")) .exec(GetTokenRequest.get_token)
内容的提问来源于stack exchange,提问作者Magnus Jensen
相关产品推荐
相关产品推荐

