问题: 我写了一个服务,并为每个请求分配一个线程来处理,我这样做的原因是因为基本上每个请求都是一次数据库的查询操作。我使用了一个线程池的库来减少线程的创建和销毁。 我的问题是:像这样的I/O多线程,什么才是一个好的临界点?我知道这需要一个粗略的估计值,但这个值应该是几百呢还是几千? 更新: 非常感谢你们所有的回答,看起来我需要去测试找出线程数上限,问题是:我怎么知道线程数已经到达了上限?我究竟该如何去测量? 回答:有的人可能会说,两个线程就算是太多的线程了。我不是特别同意这种看法。 我的建议是:测试,而不是猜想。我建议把线程数设置为可配置的,并初始化为100个线程,然后运行你的软件并对它进行监控。 如果线程的使用峰值才为3,那说明100个线程就是太多了。如果一天中的大部分时间都保持在100个线程,那就将线程的数量提高到200,然后再监视其运行情况。 你确实可以让你的代码自动监控线程的使用,并在下次启动的时候自动修改配置选项,但没必要这么做。
% t6 m8 j. r B; O" ]8 }( W- v6 z 详述:我不支持经常变动你的线程池,而是尽可能的使用某一个值,你可能会问一个线程池合适的临界点是什么,现假定你的线程池可以限制线程池的最大线程数(这是一件非常好的事情)。
: O: n! ~/ U; I! H我写过线程池和数据库连接池,他们拥有以下最基本的特征(我认为这些对系统的性能来说是必要的): - 最小活动线程数
- 最大线程数
- 多久关闭一个未被使用的线程4 Y. J3 U3 d" H: f: K$ L
第一条是为了确保线程池的最低性能标准(这些线程是一直可以被使用的)。第二条是为了限制活动线程的资源使用。第三条是在一定的时间内将线程数返回到基准的设置,以减少资源的使用。 你需要去平衡线程未被完全使用(情况A)和没有足够的工作线程(情况B)的情况。 A通常指内存的使用(栈等等),因为一个不工作的线程不会占用太多的CPU资源。B通常会延迟处理到达请求,直到有可以使用的线程。 这就是为什么要去测算,正如你遇到的这种情况,绝大部分线程需要等待数据库的响应才能运行。这就有两个主要因素影响线程的数量: 第一个因素是数据库的有效连接数。这是一个硬性的限制,除非你能通过数据库管理系统增加数据库的连接数。在这里,我假设你的数据库管理系统能够承担的数据库连接数是无限制的。(虽然,理想情况下,你也应该测量一下) 其次,线程数量应该依赖于你系统的历史运行情况。最小的线程数你应该设置为在历史最低的线程数的基础上加上A%和一个绝对的最小数值(例如,让它也可被配置,就像A一样)5。 线程池的最大数应该设置为在历史最大线程数的基础上加上B%。 你也应该监控你系统运行情况的变化,如果因为某些原因,在某一个非常重要的时刻,你的线程池使用率达到100%(这将影响你客户端的性能),这就应该增加你线程池所允许的最大线程的数量,使其再增加B%。 对于“我究竟如何去测试”的回答:你应该明确测算当前运行(例如,等待数据库调用的返回)负载下的最大线程数量。然后增加一个安全因子,如10%(强调一下,很多人貌似把我举得例子当做了固定的建议) 此外,在生产环境下,这点也应该是需要去调节的。在刚开始的时候先估计一个值是没问题的,但是,你永远也无法预料生产环境下会产生什么情况(这就是为什么要把所有的这些都设置为运行时可配置的原因)。这就能应付各种客户端调用时所出现的不可预期的情况。
( r$ H; Q6 _0 ~' a9 C1 Q7 z |