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