rpc(Remote Procedure Call)是一种通过网络从远程计算机程序上请求服务而不用了解细节的协议。通常client端为服务的调用方,server端为服务的提供方。他们之间可以在不同的网络、不同的机器,使用不同的语言。
server端作为一个网络的服务提供者,需要能为多个client端提供高质量的服务,如下总结了几种服务端的模型。
(一)单线程模型
一个线程顺序处理所有请求。
优:简单
缺:同一时刻只能处理一个连接请求
(二)多线程模型(短连接)
一个线程处理一个请求后即刻关闭该连接,重新接受新的连接请求。
优:可以同时处理多个请求
缺:频繁的建立连接&关闭连接,额外开销大;并发多少请求就需要多少个线程。
(三)多线程模型(长连接)
一个线程处理一个连接上的多个请求,每个请求完毕后不关闭连接,继续监听该连接,直到对方关闭连接。
优:长连接模式,一个线程顺序处理一个连接上的所有请求
缺:线程数固定,当请求量小时浪费资源,请求量大时可能线程数不够而使得有的请求失败
一般将线程数设置的足够大。
(四)线程池模型
生产者+消费者模式
一个accept线程处理所有的连接请求,建立连接&将请求放入任务队列。
多个worker线程从任务队列取请求进行处理。
优:
1、将接受请求和处理请求分开,使用单独的线程处理轻量的工作(建立连接and接受请求),线程数不用再与并发连接数相同;
2、提前创建好线程,避免频繁创建&销毁线程带来的开销;
3、使用epoll同时监听多个socket,IO复用
缺:
如果线程数设置的不够,导致任务队列满,后续的请求被拒绝。
【处理】
- 连接fd数超限制:直接关闭连接、拒绝请求
- 队列满:直接关闭连接、拒绝请求
【多少线程合适】
里特尔法则
L = f W
L - 系统里的请求数量
f - 请求到达的速率
W - 每个请求的处理时间
如果f(请求达到的速率)为100/s,W(每个请求处理的时间)为10ms,如果是单线程,1s到来的请求刚好可以在1s内处理完;如果f变为1000,则L=1000*0.01=10,因此需要10个线程才能使请求不堆积。
- 线程数少了
无法充分利用资源,任务堆积,客户端长时间等待
- 线程数多了
系统资源消耗
【远端调用】
如果该服务的处理还需要调用其他的远程服务,那该服务的性能很大程度上依赖于远端服务的性能。如果远程服务的性能下降,系统中的线程数量就会迅速达到线程池的上限,其他后续到达的请求就会被丢弃。
- 隔离不同远程服务
如果不同的请求依赖不同的远程服务,一个服务出问题可能影响到其他服务。针对不同的后端服务请求,设置不同的线程池可以解决。
- 截止时间
给需要远程调用的请求规定一个截止时间,如果规定的时间没有响应,就丢弃这个请求。避免远程服务给本服务带来的影响。
- 快速失败
对后端服务做请求监控,将判定出问题的远程服务标记为失效。当后端服务被标记为失效时,所有的后续请求都会迅速失败,而不是进行不必要的等待。当然,也需要一种机制判断远程服务何时恢复为可用的。
- 并发
如果一个请求需要独立地请求多个后端服务,那么这个请求就应该能并行地调用这些服务,而不是串行地调用。