要实时就用同步,要吞吐率就用异步。
同步调用
流程略
实现负载均衡:连接池中建立了与一个RPC-server集群的连接,连接池在返回连接的时候,需要具备负载均衡策略。
实现故障转移:连接池中建立了与一个RPC-server集群的连接,当连接池发现某一个机器的连接异常后,需要将这个机器的连接排除掉,返回正常的连接,在机器恢复后,再将连接加回来。
实现发送超时:因为是同步阻塞调用,拿到一个连接后,使用底层socket带超时的send/recv即可实现带超时的发送和接收。
异步调用
流程略
为什么要待发送队列、待接收队列?
因为要将工作线程和io收发线程两者的同步关系解除,从而引入工作线程池和io收发线程池。
为什么要上下文
因为请求包的发送,响应包的callback回调不在同一个工作线程中完成,需要一个context来记录一个请求的上下文,把请求-响应-回调等一些信息匹配起来。通过rpc框架的内部请求id作为key,来保存调用开始时间time,超时时间timeout,回调函数callback,超时回调timeout_callback等信息。
注意:请求id由client端服务调用时生成,会序列化成字节流发送给server端,server端会返回该请求id。
负载均衡,故障转移
与同步调用的连接池思路基本相同。
注意:由于同步调用的连接池使用阻塞方式收发,需要与一个服务的一个server ip建立多条连接来保证client端多个服务同时路由到同一个server时不会阻塞。而由于异步调用,server端会很快返回response,所以client端多个服务同时路由到同一个server的情况是很少的,因此一个服务的一个server ip只需要建立少量的连接。
超时发送与接收
超时管理器启动timer对上下文管理器中的所有context进行扫描,看上下文中请求发送时间是否过长,如果过长,就不再等待result包,将该context从上下文管理器中移除,直接执行timeout_callback。
注意:如果timeout_callback执行后,client端接收到了server端的result包,此时因为通过req-id在上下文管理器里找不到对应的context(说明已经超时处理过了),就直接将请求丢弃。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。