醋醋百科网

Good Luck To You!

答记者问之 - 从 0 到 1 手撕一个高可用 RPC 框架:架构、实现与实战

大多数程序员都用过 Dubbo、gRPC、Spring Cloud 等成熟框架。但你是否想过:RPC 的本质到底是什么?
本文带你从零手撕一个具备通信、注册、负载均衡、限流熔断、监控告警、CI/CD 等完整能力的 RPC 框架,真正搞懂它的原理、设计思路和可落地的工程实现。

什么是 RPC?

orderService.createOrder(order);

你以为调用的是本地方法,其实请求已经通过网络,发到了远程机器上。


我们要实现一个什么样的 RPC 框架?

目标:打造一个高可用、模块化、具备生产级能力的轻量 RPC 框架:

特性包括:
 基于 Netty 的通信能力
 支持自定义协议编解码
 支持服务注册与发现
 支持多种负载均衡策略
 实现限流熔断机制
 实现调用链追踪(TraceId)
 集成 Prometheus 监控 & 告警
 支持 GitHub Actions + Docker + K8s 的 CI/CD

最终,你将收获一套真实可用、具备核心治理能力的 RPC 框架,并搞懂它的每一层实现原理。

一、框架架构总览

┌────────────┐ ┌────────────┐
│ Consumer │─────│ Provider │
└────────────┘ └────────────┘
│ │
▼ ▼
┌────────────────────────────────────┐
│ 通信层(Netty) │
│ 编解码层(自定义协议) │
│ 注册中心(ZK/Nacos) │
│ 路由负载均衡(轮询/Hash) │
│ 服务治理(限流、熔断、重试) │
│ 监控链路追踪(TraceId + Prom) │
└────────────────────────────────────┘

二、从底层开始:通信协议 & 编解码

我们设计一套简单的协议:

魔数 + 版本 + 消息类型 + 请求ID + 数据长度 + 请求体

使用 Netty 实现通信:

// 编解码器
class MessageEncoder extends MessageToByteEncoder<RpcRequest> { ... }
class MessageDecoder extends ByteToMessageDecoder { ... }
// Netty 服务端/客户端
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.childHandler(new ChannelInitializer<>() { ... });

支持心跳包、超时机制、自定义序列化(JSON / Protobuf)。

三、注册中心:服务注册 & 发现

我们用 Zookeeper 实现一个简单的服务注册中心:

/rpc-services/OrderService/providers/ip:port
  • Provider 启动时向 ZK 注册临时节点
  • Consumer 启动时订阅节点变化,动态维护 Provider 列表

可封装:

interface RegistryService {
void register(String serviceName, String ip, int port);
List<Endpoint> discover(String serviceName);
}

四、负载均衡策略

支持策略:

  • 轮询(RoundRobin)
  • 随机(Random)
  • 一致性哈希(ConsistentHash)
  • 最少连接数(LeastActive)
public interface LoadBalancer {
Endpoint select(List<Endpoint> endpoints);
}

五、服务治理:限流 + 熔断 + 重试

限流(令牌桶算法)

class TokenBucketLimiter {
int capacity = 100;
AtomicInteger tokens = new AtomicInteger(capacity);
...
}

熔断器状态图

CLOSED ——→ OPEN ——→ HALF-OPEN ——→ CLOSED
  • 错误率高 → OPEN
  • 定时尝试恢复(半开)→ 成功后 CLOSE
  • 六、链路追踪 & 调用监控

    每次 RPC 请求打上唯一 TraceId:

    ThreadLocalContext.set("traceId", UUID.randomUUID().toString());

    日志中统一打印:

    [traceId=abc123] 调用 OrderService 耗时 48ms 成功

    监控系统使用 Micrometer + Prometheus:

    • QPS
    • RT(响应时间)
    • 错误率
    • 在线 Provider 数量

    结合 Grafana 做可视化展示。

    七、CI/CD:从构建到部署

    构建方式

    • 使用 GitHub Actions 编译 + 打包 + Docker 镜像
    • Docker 镜像推送到 Registry(如 Aliyun、Harbor)
    • 使用 Helm 部署到 Kubernetes 集群

    示例流程:

    - name: Build
    run: mvn clean package
    - name: Docker Build
    run: docker build -t my-rpc-service .
    - name: Push to Registry
    run: docker push my-rpc-service
    - name: Deploy to K8s
    run: helm upgrade --install ...

    八、告警系统接入

    • Prometheus + AlertManager 设置告警规则
    • 支持钉钉 / 飞书 / 邮件 Webhook
    • 典型告警场景:
      • Provider 数量变为 0
      • 错误率超过 10%
      • 响应延迟高于 500ms

    九、一套完整使用示例(业务开发者视角)

    服务提供者:

    @RpcService
    public class OrderServiceImpl implements OrderService {
    public void createOrder(Order order) {
    ...
    }
    }

    服务消费者:

    @RpcReference
    private OrderService orderService;
    orderService.createOrder(order); // 框架自动路由 + 远程调用

    十、总结

    模块

    状态

    技术

    通信层

    完成

    Netty

    编解码

    完成

    Protobuf

    注册发现

    完成

    Zookeeper

    负载均衡

    多策略

    Hash、轮询

    熔断限流

    支持

    自研限流器、熔断器

    调用链追踪

    完成

    TraceId

    监控告警

    接入

    Prometheus + Grafana

    CI/CD 自动部署

    集成

    GitHub Actions + Docker

    最后

    写这个 RPC 框架不是为了“造轮子”,而是:

    了解分布式通信的本质

    训练系统设计能力

    拥有架构思维

    打开深入中间件开发的大门

    控制面板
    您好,欢迎到访网站!
      查看权限
    网站分类
    最新留言