工作线程池的设计

在后端服务器程序的设计中,通常采用线程池的方式来管理工作线程。当一个外部请求到来时,系统从线程池中选择出一个工作线程来服务请求。

选择工作线程的策略有很多,最常见的包括(1)随机选择 (2)活跃线程优先选择 


(1)随机选择

系统启动的时候会创建N个工作线程。

        default_task_queue_thread_.setThreadParameter(thread_count_, this, NULL);
        default_task_queue_thread_.start();

L1设置了任务队列的线程数,L2创建并启动了这些线程。

启动成功后,这些线程都等在CondWait上,一旦有请求到来,其中之一就会被唤醒,具体唤醒的机制就是POSIX提供的那一套:pthread_cond_wait, pthread_cond_signal,显然,仅仅依靠这一套机制,唤醒的策略必然是随机的。如果请求与线程之间是有状态的(上一个请求和当前请求都希望让同一个线程处理,两个请求之间存在一定的逻辑关联),则还需要增加一些逻辑来判断请求类型并为它检索对应线程。


这种策略的好处是简单,并且在所有线程都繁忙的情况下性能表现良好。缺点是在负载比较轻时浪费资源。为什么这么说呢?往下看策略(2)就明白了。


(2)活跃线程优先

当线程负载比较轻的时候,随机选择算法有一定的缺陷。这是今天遇到的一个问题。@苏真 让我看看CTU的一个疑似内存泄露问题,一个测试集群跑了几天后就出现内存耗尽。因为是测试集群,机器能力并不强,负载也小,所以server的memory limit设置为5GB。结果跑了十来天后就再也malloc不出来内存了。按照常识,这台测试机的负载特别轻,基本一个线程就能服务所有请求,占用的内存最多也就几百MB,因此怀疑出现了内存泄露。开始我也是按照内存泄露的思路找问题,没啥发现,在@曲山 的提示下,发现不是内存泄露,5GB内存是正常消耗!为什么呢?每个线程一旦开始处理请求就会分配大约100MB大小的线程局部内存(这个100MB应该大力优化,羞愧。。。),从此以后无论忙闲,这些内存绝不释放。CTU的这台机器,配置了60个工作线程,实际启动到48个工作线程的时候内存就达到memory limit了,后来的请求再想分配内存都会失败。


上面问题的本质原因就是内存资源没有得到充分利用。如果总是优先用有过服务经验的线程来处理请求,则三五个“熟练工”线程就能搞定所有请求。其余工作线程都处于未激活状态,并不持有线程局部内存(线程局部内存总在第一次使用的时候分配,永不释放)。这样,内存资源利用率最高。这种调度方式称为“活跃线程优先”。


对于淘宝的线上服务器来说,使用随机选择策略就足够了,因为(1)线上机器基本上总是处于繁忙状态,(2)这种策略实现简单可靠。

对于配置较低的线下测试机器,可以通过手工配置更少的工作线程数来实现内存的节省。


据说采用策略2在某些情况下效率更高,但我还没想到到底是怎样的场景。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值