当前位置:首页 > 知识

tomcat等应用服务器的配置

Tomcat 装完不调,等应的配等于白装。用服我见过太多人解压完 apache-tomcat-9.0.x 就直接扔生产环境跑,等应的配结果连接数一上来就卡死,用服日志里全是等应的配 Socket accept failed。问题不在 Tomcat 本身,用服默认配置是等应的配给开发环境用的,不是用服给你扛流量的。

先说 Connector。等应的配Tomcat 的用服 server.xml 里那个 <Connector port="8080" protocol="HTTP/1.1">,默认 maxThreads 是等应的配 200,acceptCount 是用服 100。什么意思?等应的配200 个线程同时处理请求,满了之后新连接排队等 100 个位置,用服再多了直接拒绝。等应的配你拿 ab 压一下就知道,超过 300 并发就开始丢请求。我一般把 maxThreads 调到 500 到 800,acceptCount 给 200,但这不是拍脑袋定的——得看你的 CPU 核数和每个请求的 IO 等待时间。CPU 密集型的应用调太高反而上下文切换开销大,IO 密集型的可以往上加。

还有个坑是 connectionTimeout,默认 20 秒(60000 毫秒,不同版本有差异)。客户端连上来半天不发数据,线程就一直占着。调成 5000 到 10000 毫秒比较合理。keepAliveTimeout 也别忽略,默认跟 connectionTimeout 一样,长连接保持太久会浪费线程资源。

JVM 参数比 Tomcat 本身的配置更影响性能。catalina.sh 里加 JAVA_OPTS="-Xms4g -Xmx4g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m",堆内存设成一样大避免动态扩展。GC 用 G1,-XX:+UseG1GC -XX:MaxGCPauseMillis=200。别用默认的 Parallel GC 跑 Web 应用,停顿时间不好控。有个项目我接手的时候堆只给了 1G,Full GC 每几分钟一次,每次停两三秒,换成 G1 加 4G 堆之后直接降到一天一两次。

线程池不能只看 Connector。Tomcat 的 executor 可以单独配,在 server.xml 里定义 <Executor name="tomcatThreadPool" maxThreads="600" minSpareThreads="50"/>,然后 Connector 里引用 executor 属性。这样线程池跟 Connector 解耦,多个 Connector 可以共享。minSpareThreads 别设太小,不然突发流量来了要临时创建线程,那一下延迟很明显。

access log 默认是关的。生产环境建议开,但别用默认的 Common 格式写本地文件——IO 开销大。要么写到独立磁盘,要么用异步 appender。我习惯在 server.xml 的 Host 标签里加 <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs/tomcat" prefix="access" suffix=".log" pattern="%h %l %u %t "%r" %s %b %D" resolveHosts="false"/>,%D 是处理时间毫秒数,排查慢请求全靠它。

Nginx 跟 Tomcat 配合的时候,proxy_read_timeout 要大于 Tomcat 的 connectionTimeout,不然 Nginx 先断了 Tomcat 还在处理。还有 proxy_buffer_size 和 proxy_buffers,默认值偏小,大响应体会报 upstream sent too big header。我一般设 proxy_buffer_size 16k,proxy_buffers 8 16k。

最后说个容易忽略的:Tomcat 的临时目录。默认在 $CATALINA_BASE/temp,上传大文件或者 Jasper 编译 JSP 都往那写。磁盘满了 Tomcat 直接崩,日志里还不一定看得到明显报错。单独挂一块盘或者定期清理,别等出事再查。

配置这东西没有标准答案。8G 内存的机器和 32G 的机器,跑同样代码,参数差一倍都正常。拿压测数据说话,别抄网上的模板。

分享到: