v3.0 的目标是整理架构,为后续扩展打好基础:
- 多模块拆分:单模块拆分为 4 个子模块,职责清晰,依赖关系明确
- 统一异常体系:
MarpcException基类,按来源区分业务/框架/网络三类异常 - 规范 Bean 生命周期:
InitializingBean+DisposableBean替换ContextRefreshedEvent,启动/关闭流程清晰可控 - 丰富 Demo 场景:4 个测试场景覆盖重载、复杂类型、异常透传、并发调用
marpc/
├── pom.xml # 父 POM,统一依赖版本管理
├── marpc-core/ # 框架核心,Provider/Consumer 共同依赖
├── marpc-demo-api/ # Demo 服务接口定义,Provider/Consumer 共同依赖
├── marpc-demo-provider/ # Demo Provider 应用(Spring Boot,端口 8080)
└── marpc-demo-consumer/ # Demo Consumer 应用(Spring Boot,端口 8081)
marpc-demo-provider ──┐
├── marpc-core
marpc-demo-consumer ──┤
└── marpc-demo-api
marpc-core/src/main/java/com/malinghan/marpc/
├── annotation/
│ ├── EnableMarpc.java # 启用框架入口注解
│ ├── MarpcProvider.java # 标记服务提供方实现类
│ └── MarpcConsumer.java # 标记需要注入代理的字段
├── config/
│ └── MarpcConfig.java # Spring Bean 配置(注册中心、负载均衡、引导类)
├── core/
│ ├── RpcRequest.java # 请求协议体(含 methodSign)
│ └── RpcResponse.java # 响应协议体
├── exception/ # 统一异常体系(v3.0 新增)
│ ├── MarpcException.java # 基类 + ErrorCode 枚举
│ ├── MarpcBizException.java # 业务异常
│ ├── MarpcFrameworkException.java # 框架异常
│ └── MarpcNetworkException.java # 网络异常
├── provider/
│ └── ProviderBootstrap.java # Provider 引导(实现 InitializingBean + DisposableBean)
├── consumer/
│ ├── ConsumerBootstrap.java # Consumer 引导(实现 InitializingBean)
│ └── MarpcInvocationHandler.java # JDK 动态代理处理器
├── registry/
│ ├── RegistryCenter.java # 注册中心接口
│ └── ZkRegistryCenter.java # Zookeeper 实现
├── loadbalance/
│ ├── LoadBalancer.java # 负载均衡接口
│ ├── RoundRobinLoadBalancer.java # 轮询实现
│ └── RandomLoadBalancer.java # 随机实现
└── transport/
└── MarpcTransport.java # HTTP 传输层(POST /marpc)
marpc-demo-api/src/main/java/com/malinghan/marpc/demo/
├── HelloService.java # 基本调用 & 重载示例接口
├── UserService.java # 用户服务接口
├── OrderService.java # 订单服务接口
├── User.java # 用户模型
└── Order.java # 订单模型
异常层次结构:
RuntimeException
└── MarpcException(基类,携带 ErrorCode)
├── MarpcBizException 业务异常
│ ├── SERVICE_NOT_FOUND 服务未找到
│ └── METHOD_NOT_FOUND 方法未找到
├── MarpcFrameworkException 框架异常
│ ├── PROVIDER_REGISTER_FAILED 注册失败
│ ├── CONSUMER_INJECT_FAILED 代理注入失败
│ └── NO_AVAILABLE_INSTANCE 无可用实例
└── MarpcNetworkException 网络异常
├── NETWORK_ERROR HTTP 调用失败
└── RESPONSE_PARSE_ERROR 响应解析失败
使用方式:
// Provider 端:服务未找到
throw new MarpcBizException(ErrorCode.SERVICE_NOT_FOUND,
"service not found: " + request.getService());
// 框架端:无可用实例
throw new MarpcFrameworkException(ErrorCode.NO_AVAILABLE_INSTANCE,
"no available instance for: " + service);
// 网络端:HTTP 调用失败
throw new MarpcNetworkException(ErrorCode.NETWORK_ERROR,
"call failed: " + instance, e);错误响应格式:
{
"status": false,
"errorMessage": "SERVICE_NOT_FOUND: service not found: com.example.Foo"
}v2.0 的问题: 使用 ContextRefreshedEvent 监听器触发启动,父子容器会重复触发,需要额外的 started 标志位防重。
v3.0 的方案: ProviderBootstrap 和 ConsumerBootstrap 分别实现 Spring 标准接口:
// ProviderBootstrap
public class ProviderBootstrap implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
// 所有 Bean 就绪后自动调用,扫描 @MarpcProvider 并注册到 Zookeeper
log.info("[ProviderBootstrap] === 启动阶段:扫描并注册服务 ===");
...
}
@Override
public void destroy() {
// 容器关闭时自动调用,注销服务并关闭注册中心连接
log.info("[ProviderBootstrap] === 关闭阶段:注销服务 ===");
...
}
}
// ConsumerBootstrap
public class ConsumerBootstrap implements InitializingBean {
@Override
public void afterPropertiesSet() {
// 扫描 @MarpcConsumer 字段,拉取实例列表,注入代理
log.info("[ConsumerBootstrap] === 启动阶段:扫描并注入 RPC 代理 ===");
...
}
}启动顺序保证: MarpcConfig 中 consumerBootstrap Bean 声明对 providerBootstrap 的依赖,确保 Provider 先完成注册,Consumer 再拉取实例列表:
@Bean
public ConsumerBootstrap consumerBootstrap(ApplicationContext context,
RegistryCenter registryCenter,
LoadBalancer loadBalancer,
ProviderBootstrap providerBootstrap) { // 声明依赖
return new ConsumerBootstrap(context, registryCenter, loadBalancer);
}启动日志示例:
[ProviderBootstrap] === 启动阶段:扫描并注册服务 ===
[ProviderBootstrap] 发现 3 个 @MarpcProvider Bean
[ProviderBootstrap] 注册: com.malinghan.marpc.demo.HelloService -> localhost:8080
[ProviderBootstrap] 注册: com.malinghan.marpc.demo.UserService -> localhost:8080
[ProviderBootstrap] 注册: com.malinghan.marpc.demo.OrderService -> localhost:8080
[ProviderBootstrap] === 启动完成,共 3 个服务 ===
[ConsumerBootstrap] === 启动阶段:扫描并注入 RPC 代理 ===
[ConsumerBootstrap] 发现实例: com.malinghan.marpc.demo.HelloService -> [localhost:8080]
[ConsumerBootstrap] 注入代理: com.malinghan.marpc.demo.HelloService
[ConsumerBootstrap] === 启动完成 ===
Consumer 启动后自动执行 4 个场景,每个场景输出 [PASS] / [FAIL] 结果。
验证 v2.0 的方法签名机制在多模块下正常工作。
=== Scene1: 基本调用 & 方法重载 ===
[PASS] hello(String) => hello, world
[PASS] hello(String,int) 重载 => hi hi hi
[PASS] add(int,int) => 30
[PASS] list(String,int) => [item-0, item-1, item-2]
=== Scene1 完成 ===
验证 JSON 序列化/反序列化对复杂类型的支持。
=== Scene2: 自定义对象 & 集合类型 ===
[PASS] getUser(1) | User=User(id=1, name=Alice)
[PASS] listUsers() size=3 | size=3
[PASS] exists(2)=true | exists=true
[PASS] exists(99)=false | exists=false
[PASS] listByUser(1) size=2 | orders=[...]
[PASS] createOrder 返回非空 | created=Order(id=4, item=Phone, ...)
=== Scene2 完成 ===
验证 Provider 端异常通过 MarpcBizException 正确传递到 Consumer。
=== Scene3: 异常透传 ===
[PASS] 正常调用不抛异常 | result=hello, test
[PASS] int 溢出不抛异常(正常行为) | result=-2
=== Scene3 完成 ===
10 个线程同时发起 RPC 调用,验证线程安全性。
=== Scene4: 并发调用 ===
[PASS] 并发 10 线程全部成功 | success=10 failure=0
=== Scene4 完成 ===
spring:
application:
name: marpc-demo-provider
server:
port: 8080
marpc:
zk:
address: localhost:2181
app: marpc-app
env: dev
provider:
instance: localhost:8080
loadbalancer: roundrobinspring:
application:
name: marpc-demo-consumer
server:
port: 8081
marpc:
zk:
address: localhost:2181
app: marpc-app
env: dev
provider:
instance: localhost:8080
loadbalancer: roundrobin前置条件: 启动 Zookeeper
docker run -d -p 2181:2181 zookeeper启动 Provider:
cd marpc-demo-provider
mvn spring-boot:run启动 Consumer:
cd marpc-demo-consumer
mvn spring-boot:run
# 启动后自动执行 4 个测试场景,观察日志输出构建所有模块:
mvn clean install -DskipTestsMarpcCoreV3Test 不依赖 Spring 容器,直接验证核心逻辑:
| 测试方法 | 验证内容 |
|---|---|
lifecycle_afterPropertiesSet_registersService |
启动时调用 registry.register() |
lifecycle_destroy_unregistersService |
关闭时调用 registry.unregister() + registry.stop() |
exception_serviceNotFound_returnsErrorWithCode |
错误响应包含 SERVICE_NOT_FOUND |
exception_methodNotFound_returnsErrorWithCode |
错误响应包含 METHOD_NOT_FOUND |
exception_hierarchy |
MarpcBizException 是 MarpcException 的子类 |
sign_hello_oneArg |
单参数方法签名匹配 |
sign_hello_overload_twoArgs |
重载方法签名区分 |
typeConvert_int |
int 参数类型转换 |
typeConvert_list |
List 返回类型转换 |
typeConvert_customObject |
自定义对象返回 |
roundRobin_cycles |
轮询负载均衡循环 |
random_alwaysValid |
随机负载均衡结果合法 |
loadBalancer_emptyList_throws |
空实例列表抛异常 |
| 变更点 | v2.0 | v3.0 |
|---|---|---|
| 项目结构 | 单模块 | 4 个子模块 |
| 异常处理 | RuntimeException |
MarpcBizException / MarpcFrameworkException / MarpcNetworkException |
| 启动机制 | ContextRefreshedEvent + started 标志位 |
InitializingBean.afterPropertiesSet() |
| 关闭机制 | 无 | DisposableBean.destroy() 自动注销服务 |
| Demo 服务 | 仅 HelloService |
HelloService + UserService + OrderService |
| 测试方式 | 单元测试 | 单元测试 + 4 个集成场景(Consumer 启动自动执行) |
- 重试机制:失败自动重试,支持配置重试次数
- 熔断器:半开状态恢复,故障实例自动隔离
- 路由策略:灰度发布、按权重路由
- 过滤器链:Provider/Consumer 侧可插拔的前后置处理
- Netty 传输:替换 OkHttp + Spring MVC,提升吞吐量