←

一个 RPC 调用实际落在哪三层

RPC 框架把一次调用藏在本地方法后面。要判断它能不能用、坏了该看哪一层,得先把这三层分开。

接口侧解决「看起来像本地调用」。动态代理把方法调用收成一次请求。Hessian2、Kryo、Protostuff 决定这份请求怎么变成字节,差别在体积、速度和是否要求双方先有同一份结构。线程池和 CompletableFuture 决定这次调用会不会把业务线程堵住。

传输侧用 Netty。服务端通常两个 EventLoopGroup:boss 只接受连接,worker 处理已经接上的连接。客户端一个就够。ServerBootstrap 和 Bootstrap 分别把两边拉起来。一条 Channel 是一条连接,上面有一条 ChannelPipeline,入站和出站的 ChannelHandler 分开挂。ByteBuf 把读指针和写指针分开,避免为了拼一次请求来回拷贝。读写都是异步的,完成与否看 ChannelFuture。超时和缓冲区在 ChannelOption。粘包、拆包和心跳是这条管道上的处理器,不是连接本身的属性。

发现侧用 ZooKeeper 存「谁提供这个服务」。节点结构先定下来,再用 Curator 做注册和摘除。调用方拿到的是一份会变的地址列表,不是写死的主机名。

一次失败先分清是代理没发出去、字节对不上、连接断了,还是注册信息过期。这三层混在一个超时里,就只能重试。