Gatling中gRPC请求失败时如何强制虚拟用户退出场景?
问题
我配置了如下的双向流(bidiStream):
.exec( bidiStream_conf .start("#{payload}") .header(metadataObject.Authorization)(s"Bearer ${Key}") .extract(_.pk.some)(_ saveAs "var") .sessionCombiner(SessionCombiner.pick("var")) .endCheck(statusCode is Status.Code.OK) ) .exitHereIfFailed .exec(REST_req) .exec(bidiStream_conf.complete) .exec(bidiStream_conf.reconciliate(waitFor = NextMessage))
我希望当流失败时强制虚拟用户(V.User)退出,因此传入了无效密钥,运行后得到如下日志:
gRPC stream completion: status= PERMISSION_DENIED, description: code = E3014, message = Token is invalid! trailers= content-type: application/grpc <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 15:45:32.700 [DEBUG] c.g.p.g.g.s.BidiStreamCall - Client issued message but stream bidiStream_conf already completed ================================================================================ 2023-11-30 15:45:34 5s elapsed ---- Requests ------------------------------------------------------------------ > Global (OK=2 KO=1 ) > bidiStream_Req (OK=0 KO=1 ) > REST_Req (OK=1 KO=0 ) ---- Errors -------------------------------------------------------------------- > grpcStatusCode.find.is(OK), but actually found PERMISSION_DENI 1 (100.0%) ED
可见后续REST API仍被执行,我认为使用exitHereIfFailed的方式有误,请问如何正确操作才能强制虚拟用户完全停止整个场景?
解决方案
问题的核心是gRPC双向流的失败为异步触发,exitHereIfFailed仅同步判断当前步骤状态,无法捕获后续流回调中出现的错误,导致后续REST请求仍会执行。以下是几种可行的解决方式:
同步等待流完成
在双向流配置中添加.await,确保虚拟用户等待流完成后再执行后续步骤,让流的失败状态同步到当前步骤,此时exitHereIfFailed即可生效:.exec( bidiStream_conf .start("#{payload}") .header(metadataObject.Authorization)(s"Bearer ${Key}") .extract(_.pk.some)(_ saveAs "var") .sessionCombiner(SessionCombiner.pick("var")) .endCheck(statusCode is Status.Code.OK) .await // 等待流完成,同步错误状态到当前步骤 ) .exitHereIfFailed .exec(REST_req) .exec(bidiStream_conf.complete) .exec(bidiStream_conf.reconciliate(waitFor = NextMessage))异步错误触发立即终止
如果不需要等待流完成,希望流一失败就立刻终止虚拟用户,可在流的onFailure回调中直接调用exitNow:.exec( bidiStream_conf .start("#{payload}") .header(metadataObject.Authorization)(s"Bearer ${Key}") .extract(_.pk.some)(_ saveAs "var") .sessionCombiner(SessionCombiner.pick("var")) .endCheck(statusCode is Status.Code.OK) .onFailure { session => session.markAsFailed("gRPC流权限验证失败") exitNow // 立即终止虚拟用户,不再执行后续操作 } ) .exec(REST_req) .exec(bidiStream_conf.complete) .exec(bidiStream_conf.reconciliate(waitFor = NextMessage))仅在流成功时执行后续操作
使用doIfSucceeded包裹所有后续操作,确保只有当双向流成功时才执行REST请求等步骤:.exec( bidiStream_conf .start("#{payload}") .header(metadataObject.Authorization)(s"Bearer ${Key}") .extract(_.pk.some)(_ saveAs "var") .sessionCombiner(SessionCombiner.pick("var")) .endCheck(statusCode is Status.Code.OK) ) .doIfSucceeded { _.exec(REST_req) .exec(bidiStream_conf.complete) .exec(bidiStream_conf.reconciliate(waitFor = NextMessage)) }
以上三种方式都能确保当gRPC双向流因无效密钥失败时,虚拟用户会停止执行后续操作。
内容的提问来源于stack exchange,提问作者TriNguyen
相关产品推荐
相关产品推荐

