跳到主要内容

常见问题

注意事项

  1. 动态类配置不需要配置 void 的方法,因为没有返回结果,Mock 了也没意义。
  2. 动态类如果请求参数一样,只会录制一次,这种做法主要是为了去重,能够减少录制的数据量,提高录制效率。
  3. 如果在回放期间 Apollo 配置被 Mock了,那当前时间内这个机器的内存里就是 Mock 后的配置,需要注意回放期间不允许其他外部请求访问,否则还是会返回 Mock 的配置。
  4. 不建议在生产环境回放,一般来说生产环境只录制流量,回放在测试环境或本地操作。

登录失败问题

登陆时邮箱接收不到验证码

请确保部署 AREX 服务的服务器可以正常对外发送请求,因为发邮件需要走外部的邮件服务器。

如果无法访问外部网络,点击发送验证码后,可以自行在 arex_storage_db 数据库 user 表中的 verificationCode 字段查找验证码:

常规接口测试问题

无法发送请求,响应框一直显示进程中

由于 AREX 是通过浏览器发送请求,因此在发送请求前需要安装 Chrome 插件,解除浏览器跨域限制。

出现这种情况请先检查是否安装插件。

如已安装插件,有可能是因为插件版本太旧,需要前往 Release 下载最新版本。

版本更新后,如果点击发送后依然无法成功,可前往 Chrome Extensions 搜索 AREX,点击 Service Worker 后再点击发送请求,检查发送的真实请求,以便确定是否存在请求发送失败或其他问题。

录制问题

提示

如果是 servlet 项目,以下几种类型的请求不会录制:

  1. Request Header content-type 包含:javascript、image、font、pdf、css
  2. Url 后缀为:.js、.css、.png、.woff、.pdf、.map、.ico
  3. HttpMethod 为:HEAD、OPTIONS
启动时出现报错:[AREX] Agent would not install due to ip (not recording)

这种情况通常表示 Agent 未能成功启动。可能的原因是之前已经启动过 Agent,并且已经在 AREX 中注册过。AREX 默认设置是同一个 service name 只允许启动一个应用的 Agent。正常情况下,当应用停止时,Agent 能够感知到这一状态,并通过 shutdown hook 机制通知 AREX 一个停止事件。然而,如果使用了强制关机的方式,比如执行 kill -9 命令,Agent 就无法感知到 shutdown 事件。

要取消同一个 service name 只允许启动一个应用的 Agent 的限制,可以通过修改 AREX 配置页面中的“Record” -> “Record Machine Count” 来实现。这样可以允许同一 service name 下启动多个应用的 Agent。修改配置时,应确保理解可能带来的影响,比如资源使用和数据管理的复杂性。

AREX Agent 录制时对应用的影响有哪些?

录制时,AREX Agent 主要影响应用的元空间(Metaspace),占用大约5-15MB的空间,具体取决于录制结果的大小。另外,Agent 启动时需要重新转换(retransform)字节码,触发 JVM 重新编译,这可能会使启动时间增加大约 1 到 2 秒。

Agent 启动失败

如果出现如上所示错误提示:Unsupported major.minor version 52.0,请通过以下命令确认当前系统的 JDK 版本是否大于 1.8.0_25。如不是,请升级 JDK 版本 > 1.8.0_25。

java -version
修改录制用例保存期限

目前数据库中默认只保存 4 天内的录制用例,超期后用例会被自动删除。如果需要长时间保留,可以在 docker-compose.yml 文件的 arex-storage-service 配置项中增加一条:

arex-storage-service:
...
environment:
- TZ=Asia/Shanghai
- JAVA_OPTS=-Darex.storage.mongo.host=mongodb://arex:iLoveArex@mongodb:27017/arex_storage_db
-Darex.storage.cache.url=redis://redis:6379/
-Darex.report.service.api=http://arex-report-service:8080
-Darex.storage.defaultExpirationDuration=1000000000
...

仅对修改配置并重启 AREX 之后录制的用例生效。

如何查看录制到的用例

正常情况下,可以在前端页面查看某应用近 4 天的录制详情。

流量录制详情

或者可以在数据库的 RollingServletMocker 表中查看是否有录制到数据。

应用搭载 Agent 后,没有展示在应用列表中

可以从以下几点进行排查:

  1. 检查 Agent 启动参数是否正确

先检查应用启动参数,确认地址是否配置正确,如下:

environment:
- JAVA_TOOL_OPTIONS='-javaagent:/usr/local/tomcat/arex-agent.jar' -Darex.service.name=community-test-0905 -Darex.storage.service.host=10.5.153.151
-Darex.enable.debug=true -Dspring.datasource.url=jdbc:mysql://cmysql:3306/community?useUnicode=true&characterEncoding=utf-8 -Dspring.datasource.username=arex_admin
-Dspring.datasource.password=arex_admin_password -Dspring.redis.host=credis -Dspring.redis.port=6379
  • 检查 AREX Jar 包位置是否正确
  • 检查服务名是否正确
  • 检查 Storage 服务的地址和端口是否正确
  1. 检查 Agent 启动时控制台输出信息是否正确

检查 Agent 启动时控制台输出信息是否正确,如下所示(arex-commnity-test 为应用名):

arex-commnity-test     | [main] INFO io.arex.foundation.services.ConfigService - [AREX] Load agent config
arex-commnity-test | request: "recordVersion":"0.3.8","host":"172.29.0.4","agentStatus":"START","systemProperties":{"awt.toolkit":"sun.awt.X11.XToolkit","file.encoding.pkg":"sun.io","java.specification.version":"1.8","spring.redis.host":"credis","sun.cpu.isalist":"","sun.jnu.encoding":"UTF-8","java.class.path":"/usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar:/usr/local/tomcat/arex-agent.jar","arex.service.name":"community-test-0905","java.vm.vendor":"Oracle Corporation","sun.arch.data.model":"64","java.vendor.url":"http://java.oracle.com/","user.timezone":"Etc/UTC","os.name":"Linux","java.vm.specification.version":"1.8","sun.java.launcher":"SUN_STANDARD","sun.boot.library.path":"/usr/local/openjdk-8/jre/lib/amd64","sun.java.command":"org.apache.catalina.startup.Bootstrap start","arex.agent.version":"0.3.8","sun.cpu.endian":"little","user.home":"/root","user.language":"en","spring.redis.port":"6379","java.specification.vendor":"Oracle Corporation","java.home":"/usr/local/openjdk-8/jre","ignore.endorsed.dirs":"","arex.rate.limit":"1","spring.datasource.password":"arex_admin_password","file.separator":"/","arex.agent.jar.file.path":"/usr/local/tomcat/arex-agent.jar","line.separator":"\n","java.vm.specification.vendor":"Oracle Corporation","java.specification.name":"Java Platform API Specification","spring.datasource.url":"jdbc:mysql://cmysql:3306/community?useUnicode=true&characterEncoding=utf-8","java.awt.graphicsenv":"sun.awt.X11GraphicsEnvironment","arex.storage.service.host":"10.5.153.151","sun.boot.class.path":"/usr/local/openjdk-8/jre/lib/resources.jar:/usr/local/openjdk-8/jre/lib/rt.jar:/usr/local/openjdk-8/jre/lib/sunrsasign.jar:/usr/local/openjdk-8/jre/lib/jsse.jar:/usr/local/openjdk-8/jre/lib/jce.jar:/usr/local/openjdk-8/jre/lib/charsets.jar:/usr/local/openjdk-8/jre/lib/jfr.jar:/usr/local/openjdk-8/jre/classes","jdk.tls.ephemeralDHKeySize":"2048","java.util.logging.config.file":"/usr/local/tomcat/conf/logging.properties","java.protocol.handler.pkgs":"org.apache.catalina.webresources","sun.management.compiler":"HotSpot 64-Bit Tiered Compilers","arex.allow.time.to":"23:59","java.runtime.version":"1.8.0_342-b07","user.name":"root","path.separator":":","arex.dynamic.result.size.limit":"1000","os.version":"3.10.0-693.21.1.el7.x86_64","java.endorsed.dirs":"/usr/local/openjdk-8/jre/lib/endorsed","java.runtime.name":"OpenJDK Runtime Environment","file.encoding":"UTF-8","java.vm.name":"OpenJDK 64-Bit Server VM","arex.enable.report.status":"true","org.apache.catalina.security.SecurityListener.UMASK":"0027","java.vendor.url.bug":"http://bugreport.sun.com/bugreport/","java.io.tmpdir":"/usr/local/tomcat/temp","catalina.home":"/usr/local/tomcat","java.version":"1.8.0_342","user.dir":"/usr/local/tomcat","os.arch":"amd64","java.vm.specification.name":"Java Virtual Machine Specification","java.awt.printerjob":"sun.print.PSPrinterJob","sun.os.patch.level":"unknown","catalina.base":"/usr/local/tomcat","java.util.logging.manager":"org.apache.juli.ClassLoaderLogManager","spring.datasource.username":"arex_admin","arex.allow.time.from":"00:01","java.library.path":"/usr/local/tomcat/native-jni-lib:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib","java.vendor":"Oracle Corporation","java.vm.info":"mixed mode","java.vm.version":"25.342-b07","sun.io.unicode.encoding":"UnicodeLittle","java.ext.dirs":"/usr/local/openjdk-8/jre/lib/ext:/usr/java/packages/lib/ext","arex.enable.debug":"true","java.class.version":"52.0"},"systemEnv":{"PATH":"/usr/local/tomcat/bin:/usr/local/openjdk-8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","JAVA_HOME":"/usr/local/openjdk-8","CATALINA_HOME":"/usr/local/tomcat","JDK_JAVA_OPTIONS":" --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED","LANG":"C.UTF-8","TOMCAT_MAJOR":"9","TOMCAT_VERSION":"9.0.65","HOSTNAME":"403f7af2398e","LD_LIBRARY_PATH":"/usr/local/tomcat/native-jni-lib","JAVA_TOOL_OPTIONS":"'-javaagent:/usr/local/tomcat/arex-agent.jar' -Darex.service.name=community-test-0905 -Darex.storage.service.host=10.5.153.151 -Darex.enable.debug=true -Dspring.datasource.url=jdbc:mysql://cmysql:3306/community?useUnicode=true&characterEncoding=utf-8 -Dspring.datasource.username=arex_admin -Dspring.datasource.password=arex_admin_password -Dspring.redis.host=credis -Dspring.redis.port=6379","TOMCAT_SHA512":"2ae846848b8436856be11cfa18d9c62caa06ca7d3134012b2e10cbf6078753c4af20cc5d37f7dc75f1779f5c59d7c033850b8626534c3ce7e389641a67963cf6","TOMCAT_NATIVE_LIBDIR":"/usr/local/tomcat/native-jni-lib","JAVA_VERSION":"8u342","PWD":"/usr/local/tomcat","SHLVL":"0","HOME":"/root","GPG_KEYS":"48F8E69F6390C9F25CFEDCD268248959359E722B A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 DCFD35E0BF8CA7344752DE8B6FB21E8933C60243"}}
arex-commnity-test | response: {"responseStatusType":{"responseCode":0,"responseDesc":"success","timestamp":1693902650048},"body":{"serviceCollectConfiguration":{"status":null,"modifiedTime":1693901294108,"appId":"community-test-0905","sampleRate":1,"allowDayOfWeeks":127,"timeMock":true,"allowTimeOfDayFrom":"00:01","allowTimeOfDayTo":"23:59","excludeServiceOperationSet":null,"recordMachineCountLimit":1,"extendField":null},"dynamicClassConfigurationList":null,"status":3,"targetAddress":"172.29.0.4"}}
  • [main] INFO io.arex.foundation.services.ConfigService - [AREX] Load agent config 是 AREX Agent 打印的日志,表示正在加载配置。
  • request: 是 AREX 向 Storage 发出的请求信息,可以看到版本,注册状态等信息。
  • response:是 Storage 返回的信息,其中包含了配置信息、Agent 记录信息等。

检查 Agent 的配置输出,再次确认配置:

arex-commnity-test     | 05-Sep-2023 08:44:14.019 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/9.0.65
arex-commnity-test | 05-Sep-2023 08:44:14.023 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Jul 14 2022 12:28:53 UTC
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 9.0.65.0
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 3.10.0-693.21.1.el7.x86_64
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/local/openjdk-8/jre
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.8.0_342-b07
arex-commnity-test | 05-Sep-2023 08:44:14.024 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation
arex-commnity-test | 05-Sep-2023 08:44:14.025 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat
arex-commnity-test | 05-Sep-2023 08:44:14.025 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -javaagent:/usr/local/tomcat/arex-agent.jar
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Darex.service.name=community-test-0905
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Darex.storage.service.host=10.5.153.151
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Darex.enable.debug=true
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dspring.datasource.url=jdbc:mysql://cmysql:3306/community?useUnicode=true&characterEncoding=utf-8
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dspring.datasource.username=arex_admin
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dspring.datasource.password=arex_admin_password
arex-commnity-test | 05-Sep-2023 08:44:14.033 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dspring.redis.host=credis
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dspring.redis.port=6379
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs=
arex-commnity-test | 05-Sep-2023 08:44:14.034 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat
arex-commnity-test | 05-Sep-2023 08:44:14.035 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat
arex-commnity-test | 05-Sep-2023 08:44:14.035 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp

再往后,可以看到 Agent 开始进行注入的日志,到这一步,基本上插桩成功了,没有这段,表示注入失败(一般不会出现这个问题的)

...
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: internal-executors
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: class-loader
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: filter-v3
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: filter-v5
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: httpservlet-v3
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: httpservlet-v5
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: apache-httpclient-v4
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: hibernate-v5
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: mybatis-v3
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: mongo
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: jedis-v4
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.InstrumentationInstaller - [arex] installed instrumentation module: lettuce-v5
...
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.CompletableFuture$Signaller loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.FutureTask loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.Executors$FinalizableDelegatedExecutorService loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.Executors$DelegatedExecutorService loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.ThreadPoolExecutor loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.CompletableFuture$Completion loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.ForkJoinTask loaded: true from classLoader null
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: java.util.concurrent.AbstractExecutorService loaded: true from classLoader null
...
arex-commnity-test | [main] INFO io.arex.agent.instrumentation.TransformListener - [arex] onTransformation: org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter loaded: false from classLoader ParallelWebappClassLoader
arex-commnity-test | context: ROOT
arex-commnity-test | delegate: false
arex-commnity-test | ----------> Parent Classloader:
arex-commnity-test | java.net.URLClassLoader@629b780f

最后出现 Report agent status 日志,表明启动成功,Agent 跟 Storage 反馈 Agent 启动状态:

arex-commnity-test     | [arex-timer-service-3-thread-1] INFO io.arex.foundation.services.ConfigService - [AREX] Report agent status, previous lastModified: Tue, 05 Sep 2023 08:08:14 GMT, lastModified: Tue, 05 Sep 2023 08:08:14 GMT. request: {"appId":"community-test-0905","host":"172.29.0.4","agentStatus":"WORKING","currentRate":"1","decelerateCode":0}
Agent 启动成功,应用列表中还是没有显示

直接访问数据库,检查数据库是否有数据。

  1. 查看 MongoDB 的镜像:

  1. 登陆镜像并访问数据库:
# 登陆镜像
docker exec -it 1e84d2ee1f08 bash

# 链接数据库
mongo mongodb://arex:iLoveArex@mongodb:27017/arex_storage_db

# 查看 Mongo 的命令
help

# 查看实例
db.Instances.find()
# 看到这个,就说明有应用注册进来了
{ "_id" : ObjectId("64f6e73a8af8432a9b10e369"), "appId" : "community-test-0905", "host" : "172.29.0.4", "agentStatus" : "WORKING", "dataChangeCreateTime" : NumberLong("1693902650044"), "dataChangeUpdateTime" : NumberLong("1693904387816"), "dataUpdateTime" : ISODate("2023-09-05T08:59:47.816Z"), "recordVersion" : "0.3.8", "systemEnv"

# 检查 Servlet 有没有用例
db.RollingServletMocker.find()
# 显示这个,就说明用例已经录制下来了
{ "_id" : "AREX-172-28-0-4-1014277717960", "appId" : "community-test-0905", "creationTime" : ISODate("2023-09-05T08:10:16.724Z"), "expirationTime" : ISODate("2023-09-09T08:10:17.325Z"), "operationName" : "/redisTest/jedis/copy", "recordEnvironment" : 1, "recordVersion" : "0.3.8", "targetRequest" : "KLUv/QBYpQ0ApmBkJvBynQMoTUS67OXqvb58b+tYIkOYQOB9LFTc5/f/JJYJDovD4hQPWABWAF0AzkQSSaTHU7bUfnQ1OqvX3aPqwxEw0GCjACLhVR+O8uO5spcKXev1xVIuxtMyw909riqbbE6c0XTGFdmcGGseX/VKdMaXDZ44SHzGfZEm1r13f7zHVKWDBI+3Kta0yseVXHl3WrOMhtbZK6d1Xft4vjz6NeVmjmntu5gtj6d1tmRKq7w7jGDkRAdymAdyGIiBzuM7q9XdI0nEkZzJ81BQegQDUPQk0kbeQzDwPMkTC40t02rugVLB4ADQJA8zeaCmp4PEFmxd10ELmGBADgZ02kWjiGhyKc3ipg2toMpq0ymXAtAgAzVrWfOjUh7flCv7MM4udxdoBB7fa1E8NXfNj8rjK3ROVVJ2f5UGIZZ1oXIiPZGVGHqiR1HRvgfCyINk5HlyIqkIJPfxFaKSvQiVSVUoLDx+qlUz5epmuAs5X7B+/IRVydhjiVXqdTC2d5/YUkvRIAMZyEgcp2GNilUJLaBaJAcKAFU7AJy48CVrFIJVGS26RdZQE5t3uz0njuXeoK0yAw==", "targetResponse" : "KLUv/QBYzQsABhtSJRCtVgcOfg1BwoTsJcel1KrVeuNigsRwzCD+16m/hwEERAAAAIBGAEkARwCLoc3epIghlhlp16amBgRBT+NxHgAP6GFvkXRdV8Z+U2+17nuY+sbeXl0D5bC3hQxhbxtJk4pp15Ktk6O69K3i7BLkyisCDnJ1B3o4HofDwWg8zrMay1kBjMVwPIsScSA4O4wLUn5LV2apu/rDQsTg7HVy7IhhrXT0YFHoQrcJr2Cv25hKpN3u6tO0LVXeVEwblkRCcc5el8YoE7m6kxZHG64OARFn5RlJk9VzKVffdjBeHMXS1RUjF8oZWItbGScXail3XTwXaiOee4vn2S9MezJkbcQL0yXIBVLEkK47qRGuQlMjXIlG6thzm55rcQ4v0p2L0DSXhSybyVLya7puZ5a6RvI7+0ZSX03TJx5fKgMLWS4EnrNPjv22AxAACkGjCBdoveXYtdmbj/BcMpG4ChjGqhgbBhCazEUMagxqOCtkfLfNLbPGJAM=", "updateTime" : ISODate("1970-01-01T00:00:00Z") }
如何为部署在多台机器上的某项服务配置 AREX Agent

如果某服务部署在多台机器上,给该服务配置 AREX Agent 时,需要对这几台机器同时挂载 Agent 且同一个服务需要保证相同的服务名。

这种情况下,需要对多台机器进行录制,前往 Setting > Record > Running Status,调整 Record Machine Count,控制录制的机器数量为相应的机器数量即可。

应用没有录制到流量

可以从以下几点进行排查:

  1. 点击应用右上角设置按钮,查看 Agent 工作状态,确保 Agent 处于正常工作状态。

录制设置

录制设置

  1. 如果 Agent 启动正常,还是无法正常录制,那么可以考虑之前是否有过手动删除 MongoDB 的数据的操作,且在删除数据时,没有将 Redis 中数据删除干净。这是由于删除操作导致数据库中的数据和配置都被删除了,但是 Redis 中的缓存没有被删除。AREX 工作时有一个查询操作直接读取了数据库,因此没有找到相应的配置,导致录制失败。通过清除 Redis 缓存,问题应该可以得到解决。

    如下所示,下载一个 Redis 的链接工具,然后填写 Redis 服务器的 IP 地址和端口号进行连接。连接成功后,清除所有的 service_mapping 开头的缓存键(key),即可解决问题。

  2. 某些组件可能尚未被 AREX Java Agent 支持录制回放。请参考 框架支持 列表查看 AREX 目前支持的框架和组件。

回放失败问题

本地安装 AREX 录制本地被测应用, 回放任务总是中断

这个场景下, 回放的时候目标回放地址(Target Host)中不能使用 localhost 或者 127.0.0.1 访问。

Docker Compose 中的网络模式有以下几种:

  1. bridge:默认模式,每个容器都会有一个唯一的IP地址,可以通过容器名称或 IP 地址相互访问。
  2. host:容器共享主机的网络命名空间,可以访问主机的所有网络接口,包括本地的 127.0.0.1
  3. none:容器不会加入到任何网络中,只能通过容器 ID 进行访问。
  4. container:容器共享另一个容器的网络命名空间,可以通过容器名称或 IP 地址相互访问。

AREX 目前缺省的 Docker-Compose.yaml 中网络的是 bridge 模式,此模式下 Schedule 服务无法访问 127.0.0.1,导致回放失败。

如果遇到这种情况,需要将目标回放环境中的 IP 由 127.0.0.1 更改为本地的 IP 地址即可。

点击开启回放,回放状态显示异常终止

如果遇到这种情况,请先确认目标回放环境是否填写正确,完整的目标回放环境应该是协议+域名+端口号,如下所示:

如果正确,将光标移动至异常终止上,查看具体终止原因,进行问题排查。

或点击无效用例,跳到至对应的用例详情,查看报错信息。

如果还是无法定位问题,请在浏览器中前往 前端/logs 路径(如:http://0.0.0.0:8088/logs)查看报错日志:

录制的接口有 token、session 等带有时效性的状态信息

如果录制的接口有 token、session 等带有时效性的状态信息,后期进行回放时会因为 token、session 已经失效而导致失败。

1)如果登录过期方法逻辑使用的是 Calendar、LocalDateTime、Date 等时间类,则不需要额外操作,AREX 已默认支持这类时间类的 Mock,不会判定 token 过期。

如下的 token 校验逻辑,录制的 token 里面带有时间,回放的时候,校验逻辑里面会取一个 Date.now 来进行判定,AREX Time Mock 会 mock 该 Date.now 返回值,使其与录制用例中的时间信息相同,那么回放时校验逻辑中使用的时间与 token 中的时间信息相同,就不会判定 token 过期,回放也可以通过。

function verifyToken(token) {
try {
const decoded = jwt.verify(token, secret);
const currentTime = Math.floor(Date.now() / 1000);
if (decoded.exp < currentTime) {
return false;
}
return true;
} catch (error) {
return false;
}
}

2)如果是 System.currentTimeMillis 时间类,则需要额外配置动态类

在录制设置中将 token 的检查函数添加为动态类,这样录制的时候,AREX 会记录下 token 检查函数的返回值,通常应该是 true,表示 token 检查通过。在回放时,通过 Mock掉 token 的检查函数,使其返回 true,从而模拟录制时的情况。这样就可以保证回放的一致性,理论上回放就可以通过。

如代码中使用 java.lang.System#currentTimeMillis

package com.your.service;
public class TestService {
public void testDemo(String s) {
...
long l = System.currentTimeMillis();
if (l > s) {
...
}
...
}
}
FullClassNameMethodNameParameterTypeskeyFormula
com.your.service.TestServicetestDemojava.lang.Stringjava.lang.System.currentTimeMillis
在分析比对差异时,明明代码无差异,还是出现新增调用(new call)

在 AREX 中,一个用例通常由多个步骤组成,每个步骤包含了一个请求和一个响应。请求可以是主入口,也可以是外部调用(包括 DB、Redis 等)。在每个步骤中,都会记录请求的参数和响应结果等信息,用于后续的对比。如果录制与回放时的主入口响应,以及外部依赖的请求均无差异,则视为该用例回放通过。

主入口和外部调用的差异类型主要分为以下三种:

  • new call:这种差异类型表示该主入口或外部调用的 Mock 在录制时不存在,但在回放时存在,即新增了调用,通常是因为有新功能的迭代。
  • call missing:表示在录制时存在,但在回放时缺失了调用,通常是因为项目进行了优化,移除了某些不必要的调用关系。
  • value diff:表示在录制和回放时都存在,但在对比过程中某些节点有差异。

通常来讲,如果代码无差异,应该是不会出现新增调用的情况的。如果存在,请确认代码中是否存在本地缓存的情况。例如录制的时候,缓存里面有值,但在回放该操作时,由于缓存已经失效或者被清空了,所以需要重新访问依赖接口如数据库之类的来加载数据,从而导致出现一些新增调用的情况。

AREX 的回放匹配逻辑是什么?

在回放过程中,AREX 对主接口进行真实调用,而对外部第三方依赖(如数据库、Redis 等)不会产生真实的调用,如果子调用入参与录制子调用的入参相同,则直接返回录制的数据。

这里的回放匹配逻辑根据依赖组件类型的不同而有所差异,主要分为两种算法:

  • 对于动态类(Dynamic class)和Redis,使用精准匹配加模糊匹配的算法。
  • 对于其他类型的依赖,如数据库、HTTP、Dubbo Consumer,使用精准匹配加特征值匹配的算法。
如何处理新版本改动导致的回放失败问题?

例如:新版本改动了表结构、增加了或删减了数据库操作,从而导致回放失败

在进行回放测试时,AREX 会默认屏蔽所有的外部依赖,包括数据库。如果在用于回放的新版本中对数据库的结构或操作进行了修改,那么在回放过程中可能会出现一些预期的差异。这些差异并不代表代码本身存在错误,而是因为数据库的变动导致。特别是对于那些在之前的录制中未曾出现的新增数据库操作,如果在回放时没有相应的录制数据,这些操作将无法成功 Mock,从而导致回放失败。

针对这种情况,AREX 允许用户针对某些操作类型(如 query、update)配置忽略 Mock,回放时将对外部依赖进行真实调用,但这可能会产生脏数据。用户需要确保真实调用不会产生副作用才能安全使用此功能。

其他

为什么回放时同一个用例会发四次请求?

这是由于 AREX 在回放时的预热 + 降噪机制导致的。

  • 第一次请求:预热操作。在测试开始时,AREX 会进行一次预热操作。特别是在使用配置中心(如 Apollo)的场景中,第一次请求会通过访问缓存来获取与录制时相同的配置信息,确保测试环境与录制环境一致。

    以 Apollo 为例,其配置是加载到内存中的全局配置。回放时需要将所有配置 Mock 成录制时的设置,这个过程是异步的(Apollo 的内部机制),因此无法保证第一次就能把所有的配置文件都还原完成。为了解决这个问题,需要先进行一次预热操作。这样,后续的回放请求就会使用 Mock 过的 Apollo 配置。

  • 第二、三次请求:用于降噪。在预热之后,AREX 会对同一测试用例进行两次预回放。这两次回放的目的是通过对比它们之间的流量差异,找出并剔除其中的“噪声”点(如随机数、时间戳等)。

  • 第四次请求:正式请求。与录制时的流量进行比对,以验证测试结果是否符合预期。

通过强制录制/固化后的测试用例,在修改了其中 Mock 值后,返回的响应中依旧是未修改前的值

这是由于 AREX 对于主接口的返回值是不 Mock 的,只会对中间过程中调用的第三方依赖进行 Mock,修改才有效。