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