跳转至

编写客户端

RPC 客户端主要的功能是连接到服务端,发送请求并接收响应。客户端需要实现的逻辑几乎没有,只需要根据 IDL 定义的函数签名构造好请求就可以了。复杂度主要在于客户端需要负责超时重试,以及连接复用避免大量创建连接的开销。其中,连接复用通常是通过连接池的方法来实现的。

总体来说,客户端的伪代码如下:

class RPCClient {
  ConnectionPool pool_;
  Response do_request(Request const& req) {
    auto conn = pool_.get();
    conn.send_request(req);
    auto resp = conn.recv_response();
    pool_.put(conn);
    return resp;
  }
public:
  RPCClient(string const &host, string const &port) : pool_(host, port) {}
  PingResponse ping(PingRequest const& req) {
    return do_request(req);
  }
};

连接池预先建立并维护了一些空闲连接,在发送请求的时候,直接从连接池中取出一个连接,在这个连接完成一次 RPC 之后,将连接重新放入连接池,等待下一次 RPC 调用。为了避免占用过多的服务器资源,连接池通常会设定一个空闲超时,将空闲时间太久的连接关闭。同时,连接池会设定一个最大连接数,如果连接数超过了这个数,后续的 RPC 调用则需要等待直到有可用连接为止。对于连接出错的情况,通常是直接关闭连接,并尝试重新创建一个新的连接。当然,重试也有超时和次数上限,如果超时或者次数超过了上限,则直接抛出异常。


最后更新: 2022-08-11 15:28:51
本页作者: Howard Lau