转转QA 线下环境动态调用 RPC 服务实践

笑哼 for 转转QA · 2018年09月21日 · 83 次阅读

作者 | 申言方
一、背景
随着业务的增长,作为 QA 的我们开发了一系列的测试工具,随着代码量的增加和工具的增多,商业测试平台应运而生。平台的愿景是在平时的工作中提高 QA 测试效率,帮助 RD 实现自测,但是在实际的使用发现了一些问题:
1.测试平台只能加载一个 rpc 服务的配置文件;
2.测试平台加载的 rpc 服务配置文件无法实时变更,做到因人而异;
3.测试平台不能够并发调用不同机器上的 rpc 服务,“各用个的” 互不影响。
以上 3 个问题,究其根本原因就是作为测试平台的 WF 站点,不能根据需要调用指定机器上的 RPC 服务,即 rpcclient 在线下环境不能够动态的调用不同机器上的 RPC 服务。

释疑:转转有完整的测试环境网络隔离,所有测试用机器统一在环境管理平台上管理,大致分为测试环境、稳定环境、沙箱环境等,而这些环境中的 RPC 服务,无法注册并使用线上的服务管理平台。关于环境平台详见转转 QA 公众号前述分享:转转测试环境平台解决方案https://mp.weixin.qq.com/s/iFeKq2ozW3G3m8pe0wt45A

二、用到的知识点
1.JAVA 类加载机制
主要有 父类优先策略 和 子类优先策略,顾名思义父类优先策略,当前 classloader 加载类时,先委托父类去加载,形成一个类加载的链路。子类优先策略,则是首先当前 classloader 在自己的 classpath 中寻找 class 文件。
2.类加载同名类的处理
在同一个 cloassloader 中,加载 classpath 中靠前的类。
3.JAVA 动态代理
java.lang.reflect.* 系列提供的功能
4.ThreadLocal
java.lang.ThreadLocal

三、测试平台
先来看一下商业测试平台目前的实现方式,以创建商品并投放为例,在提交之前,需要手动选择一下需要调用的 rpc 服务所在机器的 ip,这个下拉列表是调用环境平台的 api,获取当前用户拥有操作权限的所有机器,再加上默认的测试稳定环境、沙箱稳定环境。

在加上其他必填的参数后,点击提交,页面上就会展示本次请求的执行结果

wf 站点的日志中可以看到本次请求所调用到的 rpc 服务所在的 ip

针对背景中提到的 3 个问题,测试平台通过接入公司内网 sso,调用环境平台对应 api,实时获取 ip 列表,并动态生成 rpc 服务配置文件来解决问题 2;问题 1、3 需要修改 rpcclient 来实现。

四、rpcclient 动态调用 RPC 服务
为了实现 “rpcclient 动态调用 RPC 服务” 这一功能,rpcclient 需要实现加载多个 rpc.config,我用两种方式分别针对不同的 rpcclient 版本,实现了这一功能

方案 1
低版本的 rpcclient 调用逻辑见下图,保密性原因省去具体类名称,主要就是使用了 java 的动态代理机制,来反射生成需要调用的 rpc 服务,通过解析默认位置的 rpc 服务配置文件,来确定 rpc 服务所在的机器及端口,通过序列化和反序列化来传递调用参数和返回结果。

需要做的改动
1.配置文件的生成
单独的 api 提供,在测试平台上选择需要更新的 rpc 服务所在的 ip,点击更新后,根据环境平台 api 返回的该 ip 上所有已部署的集群,生成新的配置文件,该操作会会覆盖已有的对应的配置文件。文件名称会以 ip 作为前缀,例如,192.168.187.208_rpc.config
2.配置文件的加载
从 Class1 的 create 方法增加一个入参 ---- 需要调用的 rpc 服务所在机器的 ip,然后一直传递到 Class5 的 get() 方法,get() 通过 ip 来解析对应 rpc 服务配置文件,返回响应的 rpc 服务 ip 和端口等信息。
3.新建工程,把修改后的代码打包成 1.dynamic.client.jar,这样 classloader 在加载时,会优先加载 1.dynamic.client.jar 中的类,就不会再加载 rpcclient.jar 中重名的类。虽然 java 加载 jar 的先后顺序是由操作系统决定,但是在 linux 上每次都全量更新 lib 下的所有 jar 包,目前还没有出现先加载 rpcclient.jar 的情况出现。
这个方案有一些缺点,1.已有代码需要有很大的改动;2.代码依赖比较严重,如果不想使用 rpcclient 动态加载 rpc 服务这一功能,需要再改回原来的代码。3.每个 create 相关的调用都需要改,工作量有些大。

方案 2
新版的 rpcclient 改变了 client 类之间的调用环节,但是最后还是需要 getConfig() 方法来加载和解析 rpc.config,为了一并解决方案 1 中的缺点,本方案使用了 ThreadLocal 来实现,调用过程简略示意图如下

使用该方案,原来的代码不用做太大的改动,直接在拦截器中添加相应的代码就可以,解决了方案 1 的缺陷,并保证了功能的实现。

五、优点
1.实现动态修改 rpc.config,不需要在重启 wf 站点就可以生效
2.每个用户使用自己的 rpc.config,多个用户之间互不干扰
3.不需要在修改本机的 host,解决了平台型工具需要多个机器部署的尴尬,不需要在被测服务的机器上再启动一个测试平台
4.请求用到的 server 的信息可追踪
5.为 RD 自测时,使用 QA 提供的测试代码提供可能
6.为后续的 RPC 服务 diff 提供了可能
7.如有必要 RPC mock 也可以实现

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册