调用服务器上的 getUserInfo()为什么代码写起来像本地函数底层却走了十万八千里做客户端开发的时候最爽的就是写一行userApi.getUserInfo(userId)然后就像调用本地函数一样拿到结果。结果真出问题的时候才发现这一行函数调用根本不是本地的。它要把参数序列化、打包、过网络、到服务器、执行、把结果序列化、再传回来。中间任何一步出问题都是用户看到的加载失败。一、先想清楚这一行函数调用到底做了什么先把最基础的问题想明白。你写的是letuserawaituserApi.getUserInfo(userId);看起来就是调了一个函数。但实际上背后发生了这么多事阶段做什么参数序列化把 userId 打包成网络能传的格式建立连接跟服务器建立 TCP/UDP 连接发送请求把请求包发出去服务端执行服务器收到请求执行业务逻辑结果序列化把返回值打包返回响应把结果传回来反序列化把结果解成你要的对象这一套走下来可能几十毫秒也可能几百毫秒。网络不好的时候可能直接超时。二、URPC 和普通 HTTP/REST 有什么区别很多人以为RPC 不就是换个方式发 HTTP 请求吗不对。HTTP/REST 是面向资源的你请求一个 URL拿到一个资源。RPC 是面向方法的你调用一个远程方法就像调用本地函数一样。类型思维方式适合场景HTTP/REST请求资源公开 API、跨平台URPC调用方法内部服务、高性能URPC 是 HarmonyOS 提供的高性能远程过程调用。它不是简单的 HTTP 封装是一套完整的 RPC 框架。三、Client、Server 和远程方法URPC 的基本结构很简单Client 调用方Server 提供方中间是远程方法。这段代码解决什么问题定义远程方法。文件rpc/UserService.ets用途远程服务接口定义接入位置客户端和服务端共用import{rpc}fromkit.RemoteCommunicationKit;// 定义远程接口exportinterfaceIUserService{getUserInfo(userId:string):PromiseUserInfo;updateProfile(userId:string,profile:Profile):Promiseboolean;}客户端拿到这个接口调用的时候就像调用本地方法一样。但实际上调用会被框架拦截打包发到服务端。四、一次调用的完整生命周期完整的远程调用是这样的客户端调用getUserInfo(userId)框架拦截调用把方法名和参数序列化建立连接发送请求包服务端收到请求反序列化找到对应方法服务端执行业务逻辑服务端把返回值序列化把响应包发回客户端客户端反序列化拿到结果把结果返回给调用方。五、弱网环境为什么容易出问题URPC 特别强调弱网传输。为什么因为手机网络不是一直稳定的。网络情况问题Wi-Fi 信号差丢包、延迟高蜂窝网络切换连接中断、重连多径传输Wi-Fi 和蜂窝同时传选快的多径传输是什么意思就是 Wi-Fi 和蜂窝网络同时传同一份数据哪条路快走哪条。这样即使 Wi-Fi 断了蜂窝网络还在传不会整个挂掉。六、超时和异常传播为什么很重要很多人写 RPC 只处理成功这一种情况。不对。RPC 的失败情况太多了失败类型说明网络超时服务器没响应网络断开连接断了服务端错误业务报错序列化失败参数打包出错反序列化失败结果解不开每一种失败客户端都要能处理。不能网络一断整个应用就崩了。七、几个容易踩的坑第一个坑把远程调用当成本地函数。它不是本地的它有网络延迟会失败。第二个坑循环里大量细粒度 RPC。循环调十次十次网络往返太慢了。应该批量传。第三个坑接口幂等性没有设计。网络重试了服务器执行了两次业务就乱了。第四个坑客户端超时但服务端仍继续执行。客户端不等了服务端还在跑资源浪费。第五个坑网络重试导致业务重复提交。点一次提交网络不好重试结果提交了两次。第六个坑把网络断开当普通函数异常。网络断开是常见情况不是异常。第七个坑RPC 对象长期持有失效连接。连接断了还拿着用每次都超时。这次做远程调用最大的体会是RPC 看起来像本地函数但它本质是网络调用。你必须把它当网络问题来处理超时、重试、幂等、异常。每一个环节都有它存在的理由序列化把参数打包、连接管理管网络、超时控制防卡死、异常处理防崩溃。真正做的时候最容易忽略的不是 API 怎么调而是周边的工程问题重试策略、幂等设计、连接生命周期、弱网处理。这些才是 RPC 真正难的地方。