| 知乎专栏 |
Undertow 是红帽公司开发的一款基于 NIO 的高性能 Web 嵌入式服务器
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Undertow instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@GetMapping(value = "/undertow/test")
public String undertow() {
return "hello undertow";
}
}
Undertow 日志配置
#存放目录 server.undertow.accesslog.dir= # 是否启用日志 server.undertow.accesslog.enabled=false # 日志格式 server.undertow.accesslog.pattern=common # 日志文件名前缀 server.undertow.accesslog.prefix=access_log # 日志文件名后缀 server.undertow.accesslog.suffix=log
HTTP 相关配置
# HTTP POST请求最大的大小 server.undertow.max-http-post-size=0 # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 server.undertow.io-threads=4 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 server.undertow.worker-threads=20 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 # 每块buffer的空间大小,越小的空间被利用越充分 server.undertow.buffer-size=1024 # 每个区分配的buffer数量 , 所以pool的大小是buffer-size * buffers-per-region server.undertow.buffers-per-region=1024 # 是否分配的直接内存 server.undertow.direct-buffers=true
使用 Jetty 替代 Tomcat
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <!-- Exclude the Tomcat dependency --> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <!-- Use Jetty instead --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency>
keytool -genkey -alias www.netkiller.cn -keyalg RSA -keystore /www/netkiller.cn/www.netkiller.cn.keystore
导入证书(Windows)
keytool -selfcert -alias www.netkiller.cn -keystore www.netkiller.cn.keystore keytool -export -alias www.netkiller.cn -keystore www.netkiller.cn.keystore -storepass passw0rd -rfc -file www.netkiller.cn.cer
找到 Java 安装路径
[root@localhost ~]# alternatives --list libnssckbi.so.x86_64 auto /usr/lib64/pkcs11/p11-kit-trust.so python auto /usr/libexec/no-python cifs-idmap-plugin auto /usr/lib64/cifs-utils/cifs_idmap_sss.so ifup auto /usr/libexec/nm-ifup ld auto /usr/bin/ld.bfd python3 auto /usr/bin/python3.6 dockerd auto /usr/bin/dockerd-ce java manual /usr/lib/jvm/java-14-openjdk-14.0.2.12-1.rolling.el8.x86_64/bin/java jre_openjdk auto /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64/jre jre_14 auto /usr/lib/jvm/java-14-openjdk-14.0.2.12-1.rolling.el8.x86_64 jre_14_openjdk auto /usr/lib/jvm/jre-14-openjdk-14.0.2.12-1.rolling.el8.x86_64 javac auto /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64/bin/javac java_sdk_openjdk auto /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64 java_sdk_14 auto /usr/lib/jvm/java-14-openjdk-14.0.2.12-1.rolling.el8.x86_64 java_sdk_14_openjdk auto /usr/lib/jvm/java-14-openjdk-14.0.2.12-1.rolling.el8.x86_64 jre_1.8.0 auto /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64/jre jre_1.8.0_openjdk auto /usr/lib/jvm/jre-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64 java_sdk_1.8.0 auto /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64 java_sdk_1.8.0_openjdk auto /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.262.b10-0.el8_2.x86_64 mvn auto /usr/share/maven/bin/mvn
导入证书(JVM)
keytool -importcert -alias www.netkiller.cn -file www.netkiller.cn.cer -keystore /srv/java/jre/lib/security/cacerts
配置Tomcat HTTPS 端口 8443(由于JVM不能fork和setuid,所以无法向nginx,apache httpd 那样设置 80 端口,除非你使用root用户运行,但这样做是不安全的。)
server.port=8443 server.ssl.enabled=true server.ssl.key-store=/www/netkiller.cn/www.netkiller.cn.keystore server.ssl.key-store-password=passw0rd server.ssl.key-store-type=JKS server.ssl.key-alias=www.netkiller.cn
keystore 文件可以放到 classpath 中,首先将证书文件放到 src/main/resources 目录中,然后配置 application.properties 如下:
server.port=8443 server.ssl.enabled=true server.ssl.key-store=classpath:www.netkiller.cn.keystore server.ssl.key-store-password=passw0rd server.ssl.key-store-type=JKS server.ssl.key-alias=www.netkiller.cn
/srv/java/bin/java -server -Xms2048m -Xmx8192m -Djava.security.egd=file:/dev/./urandom -jar /www/netkiller.cn/www.netkiller.cn/www.netkiller.cn-0.0.1.war
String url = "https://www.netkiller.cn:8443/public/test/version.json";
ResponseEntity<RestResponse<String>> result = restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<RestResponse<String>>() {});
启用 HTTP2 必须使用 Tomcat 9 以上, Springboot 2.1
创建证书
keytool -genkey -alias localhost -storetype PKCS12 -keyalg RSA -keysize 2048 -storepass passw0rd -keystore localhost.p12 -dname "CN=localhost, OU=netkiller, O=netkiller.cn, L=Guangdong, ST=Shenzhen, C=CN" keytool -selfcert -alias localhost -storepass passw0rd -keystore localhost.p12 keytool -export -alias localhost -keystore localhost.p12 -storepass passw0rd -rfc -file localhost.cer keytool -importcert -trustcacerts -alias localhost -file localhost.cer -storepass passw0rd -keystore /etc/pki/java/cacerts
如果你是自己安装的JDK,需要找到cacerts安装路径
keytool -importcert -trustcacerts -alias localhost -file localhost.cer -storepass passw0rd -keystore /srv/java/jre/lib/security/cacerts
MacOS 添加方法,当提示你输入密码的时候,输入:changeit
iMac:resources neo$ sudo keytool -importcert -trustcacerts -alias localhost -file localhost.cer -cacerts Password: 输入密钥库口令: 所有者: CN=localhost, OU=netkiller, O=netkiller.cn, L=Guangdong, ST=Shenzhen, C=CN 发布者: CN=localhost, OU=netkiller, O=netkiller.cn, L=Guangdong, ST=Shenzhen, C=CN 序列号: ffd28d78add2b56c 生效时间: Mon Sep 07 16:55:39 CST 2020, 失效时间: Sun Dec 06 16:55:39 CST 2020 证书指纹: SHA1: A0:DB:69:34:66:EA:16:A3:AF:65:31:F9:5D:6E:C0:70:CA:5F:0E:22 SHA256: 2C:04:B7:BB:28:25:B5:E6:7C:0F:73:4B:02:38:6E:04:80:42:E2:F7:61:5C:91:4D:A8:EA:5E:20:2E:82:4F:0C 签名算法名称: SHA256withRSA 主体公共密钥算法: 2048 位 RSA 密钥 版本: 3 扩展: #1: ObjectId: 2.5.29.14 Criticality=false SubjectKeyIdentifier [ KeyIdentifier [ 0000: 4E 30 9A EC C1 9D FB C2 CC 55 B2 6D 0D F4 01 CE N0.......U.m.... 0010: 13 C6 62 38 ..b8 ] ] 是否信任此证书? [否]: Y 证书已添加到密钥库中 iMac:resources neo$ keytool -list -cacerts -alias localhost 输入密钥库口令: localhost, 2020年9月8日, trustedCertEntry, 证书指纹 (SHA-256): 2C:04:B7:BB:28:25:B5:E6:7C:0F:73:4B:02:38:6E:04:80:42:E2:F7:61:5C:91:4D:A8:EA:5E:20:2E:82:4F:0C
配置启用 http2
server:
port: 8443
servlet:
context-path: /
ssl:
enabled: true
key-store: classpath:ssl/localhost.p12
key-store-type: PKCS12
key-store-password: 123456
http2:
enabled: true
我的配置
spring.application.name=web server.port=8443 #server.servlet.context-path=/ server.ssl.enabled=true server.ssl.key-store=classpath:localhost.p12 server.ssl.key-store-type=PKCS12 server.ssl.key-store-password=123456 server.http2.enabled=true
使用 curl 访问可以看到 HTTP/2 字样,表示成功
neo@MacBook-Pro ~ % curl -i -k https://localhost:8443/ping HTTP/2 200 content-type: text/plain;charset=UTF-8 content-length: 4 date: Tue, 09 Apr 2019 08:41:29 GMT Pong%