使用jetty作为容器,想要更早的关闭不需要的链接,减少没用的TCP链接数量,方便同时处理更多请求。
在创建Connector的时候调用setMaxIdleTime(15 * 1000);将链接的最大空闲时间从默认的30秒换成15秒。
但是服务器开始出现报错
WARN o.e.j.i.nio:720 - javax.net.ssl.SSLException: illegal change cipher spec msg, conn state = 6, handshake state = 1
WARN o.e.j.i.nio:720 - java.io.IOException: java.lang.IllegalStateException: Internal error
尝试解决未果。
为了减少idleTime尝试升级jetty。之前使用的jetty8.1.16/8.1.19,
在maven官网的org.eclipse.jetty决定更新到最新的稳定版9.4.35.v20201120。
netbean成功下载后发现变了很多,跨越了太多的版本,只能从头来。
eclipse官网上jetty教程
pom:
org.eclipse.jetty
jetty-server
${jetty.version}
org.eclipse.jetty
jetty-rewrite
${jetty.version}
org.eclipse.jetty
jetty-util
${jetty.version}
org.eclipse.jetty
jetty-servlet
${jetty.version}
org.eclipse.jetty
jetty-servlets
${jetty.version}
9.4.35.v20201120
Main.java:
import io.swagger.jaxrs.config.BeanConfig;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.glassfish.jersey.servlet.ServletContainer;
public class Main {
public static void main(String[] args) throws Exception {
startServer();
}
/**
* 服务器 jetty doc
* https://www.eclipse.org/jetty/documentation/9.4.35.v20201120/#embedding-jetty
* jetty api
* https://www.eclipse.org/jetty/javadoc/9.4.35.v20201120/index.html?overview-summary.html
*
* @return http server
* @throws Exception
*/
private static Server startServer() throws Exception {
//Set the maximum number of threads.
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(5000);
Server server = new Server(threadPool);
Connector[] connectors = createConnectors(server);
server.setConnectors(connectors);
ContextHandlerCollection contexts = createContextHandlerCollection();
server.setHandler(contexts);
server.start();
server.join();
return server;
}
/**
* 创建connector,acceptors,selectors都用默认值
*
* @param server
* @return
*/
private static Connector[] createConnectors(final Server server) {
boolean http = true;
int httpPort = 8070;
boolean https = true;
int httpsPort = 8071;
long idleTimeOut = 15 * 1000;
// Configuration
HttpConfiguration httpConfig = new HttpConfiguration();
// httpConfig.setSecureScheme("https");
// httpConfig.setSecurePort(httpsPort);
// httpConfig.setOutputBufferSize(32768);
httpConfig.setRequestHeaderSize(32768);
httpConfig.setResponseHeaderSize(32768);
// httpConfig.setSendServerVersion(true);
// httpConfig.setSendDateHeader(false);
httpConfig.setIdleTimeout(idleTimeOut);
// httpConfig.addCustomizer(new ForwardedRequestCustomizer());
ServerConnector httpConnector = null, httpsConnector = null;
if (http) {
httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfig));
httpConnector.setPort(httpPort);
httpConnector.setIdleTimeout(idleTimeOut);
}
if (https) {
HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
// SSL
// SslContextFactory sslContextFactory = new SslContextFactory();
SslContextFactory sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("123.jks");
sslContextFactory.setKeyManagerPassword("sslPWD");
sslContextFactory.setKeyStorePassword("jksPWD");
httpsConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(httpsConfig));
httpsConnector.setPort(httpsPort);
httpsConnector.setIdleTimeout(idleTimeOut);
}
if (httpsConnector != null) {
if (httpConnector != null) {
return new Connector[]{httpsConnector, httpConnector};
} else {
return new Connector[]{httpsConnector};
}
} else if (httpConnector != null) {
return new Connector[]{httpConnector};
} else {
return null;
}
}
/**
* 创建handler
*
* @return
* @throws Exception
*/
private static ContextHandlerCollection createContextHandlerCollection() throws Exception {
String path = "/test";
ContextHandler apiContextHandler = buildContextHandler(path);
ContextHandler swaggerContextHandler;
boolean swaggerEnabled = true;
if (swaggerEnabled) {
swaggerContextHandler = buildSwaggerUI(path, "com.test.mavenproject.rest");
return new ContextHandlerCollection(
apiContextHandler, swaggerContextHandler
);
}
return new ContextHandlerCollection(apiContextHandler);
}
/**
* servlet handler : 实现后端功能
*
* @param basePath
* @return
*/
private static ContextHandler buildContextHandler(String basePath) {
ServletHolder jerseyServlet = new ServletHolder(ServletContainer.class);
jerseyServlet.setInitParameter("javax.ws.rs.Application", "com.test.mavenproject.inject.TestJerseyConfig");
jerseyServlet.setInitOrder(1);
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
contextHandler.setContextPath("/");
contextHandler.addServlet(jerseyServlet, basePath + "/*");
return contextHandler;
}
/**
* resource handler : swagger文档
*
* @param base_path
* @param resourcePackage
* @return
* @throws Exception
*/
private static ContextHandler buildSwaggerUI(String base_path, String resourcePackage) throws Exception {
// This configures Swagger
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setResourcePackage(resourcePackage);
beanConfig.setScan(true);
beanConfig.setBasePath(base_path);
beanConfig.setDescription("Entity Browser API to demonstrate Swagger with Jersey2 in an "
+ "embedded Jetty instance, with no web.xml or Spring MVC.");
beanConfig.setTitle("Entity Browser");
final ResourceHandler swaggerUIResourceHandler = new ResourceHandler();
swaggerUIResourceHandler.setResourceBase("swaggerui");
final ContextHandler swaggerUIContext = new ContextHandler();
swaggerUIContext.setContextPath("/docs");
swaggerUIContext.setHandler(swaggerUIResourceHandler);
return swaggerUIContext;
}
}
/*参数及意义
参数 所属模块 说明
jetty.http.host http HTTP链接器绑定的主机地址,默认本机所有有效IP地址。
jetty.http.port http HTTP链接器监听的端口号,默认为8080。
jetty.http.idleTimeout http HTTP链接的最大空闲时间,单位为毫秒,默认为30000。
jetty.http.soLingerTime http HTTP链接器Socket Linger时间,默认为-1,即禁用。
jetty.http.acceptors http HTTP链接器用于接收请求的线程数量,默认为-1,Jetty基于处理器核数选择一个值,具体规则是低于16核为1,低于24核为2,低于32核为3,32核以上为4。
jetty.http.selectors http Socket selector的数量,默认为-1,Jetty基于处理器核数选择一个值,具体规则是低于4核为1,低于8核为3,8核以上为4。
jetty.http.acceptorQueueSize http 用于设置ServerSocket绑定时的backlog值,输入连接指示(对连接的请求)的最大队列长度。如果队列满时收到连接指示,则拒绝该连接。
jetty.threadPool.minThreads server Jetty线程池最小线程数,默认为10。
jetty.threadPool.maxThreads server Jetty线程池最大线程数,默认为200。
jetty.threadPool.idleTimeout server Jetty线程池线程空闲超时时间,单位为毫秒,默认为60000。
jetty.httpConfig.secureScheme server HTTP安全重定向时,URI的Scheme,默认为https。
jetty.httpConfig.securePort server HTTP安全重定向端口,默认为8443。
jetty.httpConfig.outputBufferSize server HTTP响应内容缓冲大小,单位为字节,默认为32768。
jetty.httpConfig.outputAggregationSize server 可以缓冲的响应内容最大写入长度,单位为字节,默认为8192。
jetty.httpConfig.requestHeaderSize server HTTP请求头的最大值,单位为字节,默认为8192。
jetty.httpConfig.responseHeaderSize server HTTP响应头的最大值,单位为字节,默认为8192。
jetty.server.stopAtShutdown server 在控制台按下ctrl+c停止Jetty服务器。
jetty.server.stopTimeout server Jetty优雅停止的超时时间,单位为毫秒,默认5000。
jetty.server.dumpAfterStart server Jetty启动之后,输出服务器、组件以及Web应用的状态。
jetty.server.dumpBeforeStop server Jetty关闭之前,输出服务器、组件以及Web应用的状态。
jetty.ssl.host ssl TLS/SSL链接器绑定的主机地址,默认本机所有有效的IP地址。
jetty.ssl.port ssl TLS/SSL链接器监听的端口,默认为8443。
jetty.ssl.idleTimeout ssl TLS/SSL链接器空闲超时时间,单位为毫秒,默认30000。
jetty.ssl.soLingerTime ssl TLS/SSL链接器Socket Linger时间,默认为-1,即禁用。
jetty.ssl.acceptors ssl TLS/SSL链接器用于接收请求的线程数量。
jetty.ssl.selectors ssl TLS/SSL链接器Socket selector的数量。
jetty.ssl.acceptorQueueSize ssl 设置TLS/SSL链接器ServerSocket绑定时的backlog值
jetty.ssl.sniHostCheck ssl 是否检查请求主机名是否匹配SNI 名称。
jetty.ssl.stsMaxAgeSeconds ssl 设置Strict-Transport-Security 响应头的过期时间,单位为秒,默认为3153600。
jetty.sslContext.keyStorePath ssl 密钥库文件路径,相对于$JETTY_BASE。
jetty.sslContext.trustStorePath ssl 信任库文件路径,相对于$JETTY_BASE。
jetty.sslContext.keyStorePassword ssl 密钥库密码。
jetty.sslContext.keyStoreType ssl 密钥库类型(JCEKS、JKS、DKS、PKCS11、PKCS12)。
jetty.sslContext.keyStoreProvider ssl 密钥库提供者。
jetty.sslContext.keyManagerPassword ssl KeyManager密码。
jetty.sslContext.trustStorePassword ssl 信任库密码。
jetty.sslContext.trustStoreType ssl 信任库类型(JCEKS、JKS、DKS、PKCS11、PKCS12)。
jetty.sslContext.trustStoreProvider ssl 信任库提供者。
jetty.sslContext.needClientAuth ssl 是否要求客户端证书认证,如果为true并且客户端选择不提供自身的验证信息,则协商将会停止。
jetty.sslContext.wantClientAuth ssl 是否请求客户端证书认证,如果为true并且客户端选择不提供其自身的验证信息,则协商将会继续。
jetty.sslContext.sslSessionCacheSize ssl SSL会话缓存大小。
jetty.sslContext.sslSessionTimeout ssl SSL会话缓存超时时间,单位为秒。
jetty.gzip.minGzipSize ssl 指定一个HTTP响应内容长度的限制,当超过该值时,Jetty启动GZIP压缩。
jetty.gzip.compressionLevel ssl GZIP压缩级别。
jetty.gzip.excludedUserAgent ssl 正则表达式,用于指定禁用GZIP的User Agent。如果请求的User Agent匹配该表达式,则将不启用GZIP压缩。默认为.MSIE.6.0.,即IE6不支持GZIP压缩。
jetty.deploy.monitoredDir deploy Jetty部署模块监控目录,相对于$JETTY_BASE,用于热部署监控文件变更。
jetty.deploy.monitoredPath deploy Jetty部署模块监控路径(绝对目录),用于热部署监控文件变更。
jetty.deploy.defaultsDescriptorPath deploy Web应用使用的默认部署描述文件,该文件中的配置信息将会被所有Web应用继承,默认为/etc/webdefault.xml。
jetty.deploy.scanInterval deploy Jetty部署模块扫描监控目录的时间间隔,单位为秒,默认为1秒。
jetty.deploy.extractWars deploy 是否解压WAR包,默认为true。
jetty.jmxremote.rmihost jmx-remote JMX远程访问绑定的RMI主机地址。
jetty.jmxremote.rmiport jmx-remote JMX远程访问RMI监听的端口,默认为1999。Jetty在启动时,会自动获取参数的键值对,并在加载各个模块时,将参数值以IoC的方式注入到各个组件对象。这是Jetty与Tomcat在参
*/