以 http server 为例，讨论下 server 的几个线程数配置：

```yml
#服务 http 最小线程数（默认：0表示自动，支持固定值 2 或 内核倍数 x2）//一般不用配置
server.http.coreThreads: 0 
#服务 http 最大线程数（默认：0表示自动，支持固定值 32 或 内核倍数 x32） 
server.http.maxThreads: 0
#服务 http 闲置线程超时（0表示自动，单位毫秒） //v1.10.13 后支持
server.http.idleTimeout: 0
#服务 http 是否为IO密集型？ //v1.12.2 后支持
server.http.ioBound: true

#启用虚拟线程池（默认false）//v2.7.3 后支持
solon.threads.virtual.enabled: false 
```

线程，不是越多越好（切换需要费时间），也不是越少越好（会不够用）。了解情况，作合适的配置为佳。

### 1、两个重要概念


* Cpu 密集型

比如写一个 “hello world” 程序，不做任何处理直接返回字符串。它就算是  cpu 密集型了。事情只在内存与cpu里完成了。

这种情况，一般响应非常快。如果线程多了，切换线程的时间反而成了一种性能浪费。

* Io 密集型

比如写 crud 的程序，一个数据保存到数据库里；或者上传文件，保存到磁盘里。事情“额外”涉及了网卡、磁盘等一些Io处理。

这种情况，一般响应会慢，有些可能还要10多秒。一次处理会占用一个线程，线程往往会不够用。


### 2、框架默认的配置

当 `server.http.ioBound: true` 时：

|  | 线程数 | 例：2c4g 的线程数 |
| -------- | -------- | -------- |
| coreThreads     | 内核数的 2倍（一般是不用配置的）     |  4 |
| maxThreads     | coreThreads 的32倍     |  128 |


当 `server.http.ioBound: false` 时：

|  | 线程数 | 例：2c4g 的线程数 |
| -------- | -------- | -------- |
| coreThreads     | 内核数的 2倍（一般是不用配置的）     |  4 |
| maxThreads     | coreThreads 的8倍     |  32 |


### 3、如何做简单的计算

* 关于 qps

比如一次请求响应为 0.1 秒，那一个线程1秒内可以做10次响应，100个线程，可以做1000个响应。即 qps = 1000

* 关于内存

一个线程最少会占用 1m - 2m的内存。100个线程，就算是 200m

一个请求包，如果是 200k，操作处理时可能会有多个副本（算它4个），那是 800k。qps 1000 时，每秒占用 800m/s 的内存，如果5s后才自动释放，那实际每秒占用为 4g/s


### 4、为什么 coreThreads 不需要配置

* 对 bio 来说，coreThreads 太大，就不会收缩了。

* 对 nio 来说，coreThreads 不能太大。nio 与 bio 一般做两段式线程池，coreThreads 即为它的第一段，maxThreads 则为第二段。


### 5、线程（即 maxThreads）不够时一般会怎么样


* 可能会卡，但卡一会儿还能接收请求

这种情况，一般是提交线程池被拒后，改用主线程处理。所以主线程没法再接收请求了，需要等手上的活完成后才能再接收请求。

* 直接是返回异常或者当前关闭链接（即拒绝服务）

通过协议直接返回异常，是为了让客户端马上知道结果，服务端吃不消了。如果直接关闭链接了，那是解析协议的线程也不够用了，没法按协议返回，就直接关链接了。


### 6、如何配置 maxThreads

一般默认即可。如果是单实例，流量大或请求慢。可以根据内存，把 maxThreads 配大些，比如这个服务能用1c2g标准的：

如果可以配成：x256 。即 512 个线程，每个线程按2m占用算，线程最大内存占用为 1024g。还有 1g 用于业务数据处理。可能有点吃紧，也可能内存会暴掉。
