SpringBoot : server.tomcat.connection-timeout配置解析
server.tomcat.connection-timeout配置解析
SpringBoot版本:2.2.2.RELEASE
SpringBoot Application properties文档
/**
* Amount of time the connector will wait, after accepting a connection, for the
* request URI line to be presented.
*/
- 在
server
端accept()
一个连接之后,连接等待下一个请求出现的时间
文档中这个解释,实际的意思还是不够明确,也没有说明默认值
Tomcat文档
The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. Use a value of -1 to indicate no (i.e. infinite) timeout. The default value is 60000 (i.e. 60 seconds) but note that the standard server.xml that ships with Tomcat sets this to 20000 (i.e. 20 seconds). Unless disableUploadTimeout is set to false, this timeout will also be used when reading the request body (if any).
- 说明了默认值是60000ms
- 如果使用的是server.xml,则为20000ms
SpringBoot中可能也为60000ms,通过SpringBoot-Tomcat启动源码确认
server:
tomcat:
connection-timeout: 17s
- customize()处理自定义的配置
//org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer#customize
@Override
public void customize(ConfigurableTomcatWebServerFactory factory) {
......
propertyMapper.from(properties::getConnectionTimeout).whenNonNull()
.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
propertyMapper.from(tomcatProperties::getConnectionTimeout).whenNonNull()
.to((connectionTimeout) -> customizeConnectionTimeout(factory, connectionTimeout));
......
}
//org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer#customizeConnectionTimeout
private void customizeConnectionTimeout(ConfigurableTomcatWebServerFactory factory, Duration connectionTimeout) {
factory.addConnectorCustomizers((connector) -> {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof AbstractProtocol) {
AbstractProtocol<?> protocol = (AbstractProtocol<?>) handler;
//通过AbstractProtocol来设置
protocol.setConnectionTimeout((int) connectionTimeout.toMillis());
}
});
}
//org.apache.coyote.AbstractProtocol#setConnectionTimeout
public void setConnectionTimeout(int timeout) {
endpoint.setConnectionTimeout(timeout);
}
//org.apache.tomcat.util.net.AbstractEndpoint#setConnectionTimeout
public void setConnectionTimeout(int soTimeout) { socketProperties.setSoTimeout(soTimeout); }
//org.apache.tomcat.util.net.SocketProperties#setSoTimeout
public void setSoTimeout(int soTimeout) {
this.soTimeout = Integer.valueOf(soTimeout);
}
/**
* SO_TIMEOUT option. default is 20000.
*/
protected Integer soTimeout = Integer.valueOf(20000);
SO_TIMEOUT
Enable/disable SO_TIMEOUT with the specified timeout, in milliseconds. With this option set to a non-zero timeout, a read() call on the InputStream associated with this Socket will block for only this amount of time. If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0. A timeout of zero is interpreted as an infinite timeout.
确定默认值
- refresh()入口
//org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
......
try {
....
onRefresh();
....
}
}
}
//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
//org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
//初始化
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
customizeConnector(connector);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}
- Connector
//org.apache.catalina.connector.Connector#Connector(java.lang.String)
public Connector(String protocol) {
boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
AprLifecycleListener.getUseAprConnector();
if ("HTTP/1.1".equals(protocol) || protocol == null) {
if (aprConnector) {
protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";
} else {
protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";
}
}
.......
// Instantiate protocol handler
ProtocolHandler p = null;
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
//实例化Http11NioProtocol对象
p = (ProtocolHandler) clazz.getConstructor().newInstance();
}
.......
}
//org.apache.coyote.http11.Http11NioProtocol#Http11NioProtocol
public Http11NioProtocol() {
//默认初始化一个NioEndpoint, 其中SocketProperties的soTimeout默认是20000ms
super(new NioEndpoint());
}
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
//org.apache.coyote.http11.AbstractHttp11Protocol#AbstractHttp11Protocol
public AbstractHttp11Protocol(AbstractEndpoint<S,?> endpoint) {
super(endpoint);
//Constants.DEFAULT_CONNECTION_TIMEOUT为60000
setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
setHandler(cHandler);
getEndpoint().setHandler(cHandler);
}
//org.apache.coyote.AbstractProtocol#setConnectionTimeout
public void setConnectionTimeout(int timeout) {
//覆盖
endpoint.setConnectionTimeout(timeout);
}
- 默认为60000ms
总结
server.tomcat.connection-timeout
为socket调用read()等待读取的时间,如果在设置的时间内没有请求,则会主动断开连接- SpringBoot嵌入Tomcat默认为60000ms