注意:此文档描述的内容正在建设中或处于功能早期阶段,请持续关注文档更新!
Mock 功能是设计用来提升微服务研发与测试效率的,它可以短路 Consumer 侧发起的远程调用,提前返回预先设定好的 Mock 值,这样即使在没有 Provider 可用的情况下,消费端也能正常的推进开发、测试进程。除此之外,mock 也可用于快速模拟负责返回值的测试数据、模拟服务端异常等场景
需要注意的是,Mock 能力仅限用于测试环境,应避免将其用于生产环境。
在跨团队或是多应用开发时,在前期开发中往往会出现依赖的服务还未开发完成的情况,这样就会导致流程的阻塞,影响研发效率。基于这种情况,Dubbo Admin 提供了 mock 能力来解耦 Consumer 与 Provider 之间的依赖,以确保在 Provider 未就绪的情况下 Consumer 仍能正常开展测试,提高研发效率。
Dubbo 框架本身设计有服务降级(有时也称为 mock)能力,通过配置 org.apache.dubbo.config.ReferenceConfig
的 mock 字段(可设置为true或是对应接口的Mock实现)或动态配置规则,此时就可以启动服务降级能力。这种服务降级能力是为生产环境的限流降级准备的,虽然也可以用于本地开发测试场景,但灵活度并不高,基于提升开发效率的根本诉求,我们设计了基于 Admin 的服务降级能力。
Dubbo Admin 服务 mock 是一种更为轻量和便捷实现方式,主要用于开发测试阶段的,目标是提升微服务场景下的整体研发效率。需求详见:Dubbo Admin Mock需求。
实现 Mock 能力,Dubbo 框架与 Admin 侧要支持的能力
Mock 请求原理时序图
在 Consumer 应用中添加依赖
开启 Mock 前,请确保在消费端应用中引入以下依赖:
<dependency>
<groupId>org.apache.dubbo.extensions</groupId>
<artifactId>dubbo-mock-admin</artifactId>
<version>${version}</version>
</dependency>
配置 -Denable.dubbo.admin.mock=true
参数开启 Mock 并重启进程
打开 Admin 配置 Mock 规则
用户可以通过在控制台上指定需要被 mock 的消费端IP、服务名和方法和具体的 mock 行为,实现对调用结果的 mock。
一些支持的规则类型与示例
数字类型:123
字符串:"hello, world!"
数组、列表:[1, 2, 3]
枚举:"ENUM_TYPE"
Map、对象:
{
"prop1": "value1",
"prop2": ["a", "b", "c"]
}
null: null
此时,消费端再次发起远程调用,就会得到预期 Mock 返回值。
注意事项
- Mock 仅限用于测试开发环境,因此为了确保核心依赖的稳定性,社区没有将 mock 组件打包在核心框架包中,用户可以自行决策是否将其作为应用的默认依赖在公司内推广
- 即使添加了 mock 二进制依赖,mock 功能也不会默认开启,需要设置
-Denable.dubbo.admin.mock=true
后才能开启。
Consumer 调用发起的调用会被本地的 MockServiceFilter 拦截,如果 mock 开关开启,则 MockServiceFilter 将请求转发到 MockService (由 Dubbo Admin 发布的服务),MockService 根据请求的服务、方法等查询用户预先配置的 mock 规则,如果查询到则返回规则中的 mock 值,Consumer 收到 mock 值后调用成功返回。
当前 Admin 支持录入 JSON 或者基本类型数据,如:
123
"hello, world!"
{
"prop1": "value1",
"prop2": ["a", "b", "c"]
}
[1, 2, 3]
dubbo-mock-admin
将为消费端引入 MockServiceFilter 请求拦截器,如果用户打开 mock 开关,那么 Filter 会将请求转发到 Admin MockService 服务。
MockService 支持返回标准 JSON 格式或者基本类型数据,消费端会基于 Dubbo 内置类型转换器将 JSON 等值转为原始对象类型。
Admin 依赖 Mysql 数据库存储用户配置的 mock 规则,具体的表结构设计如下。
CREATE TABLE `mock_rule` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`service_name` varchar(255) DEFAULT NULL COMMENT '服务名',
`method_name` varchar(255) DEFAULT NULL COMMENT '方法名',
`rule` text NULL DEFAULT COMMENT '规则',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='服务mock方法表';
CREATE TABLE `mock_log` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`method_id` int(11) DEFAULT NULL COMMENT '规则id',
`request` text COMMENT '请求数据',
`response` text COMMENT '返回值',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='mock请求记录表';