1.調(diào)研目的
解決接口大并發(fā)量情況下章办,接口響應(yīng)速度問題带膜,提升接口QPS批狐,主要方向在使用netty長連接扇售、websocket協(xié)議、http2.0優(yōu)化網(wǎng)絡(luò)請求嚣艇。
2.調(diào)研方向
2.1 netty長連接
http1.1默認支持tcp長連接承冰,使用netty長連接在根本上沒有太大區(qū)別。不做深入調(diào)研食零。
2.2 websocket
websocket最大的特點是建立服務(wù)器和客戶端的平等對話困乒,能夠讓服務(wù)器主動向客戶端推送消息。與我們的調(diào)研目的不相符贰谣,不做深入調(diào)研娜搂。
2.3 HTTP/2
HTTP/2是現(xiàn)行的HTTP/1.x的替代迁霎,但它不是重寫,HTTP方法/狀態(tài)碼/語義都與HTTP/1.x一樣百宇。HTTP/2基于SPDY考廉,專注于性能,最大的一個目標(biāo)是在用戶和網(wǎng)站間只用一個連接(connection)恳谎。HTTP/2通過多路復(fù)用芝此、二進制流、Header壓縮等特性因痛,極大的提高了性能婚苹。
HTTP/1.1和HTTP/2的區(qū)別,可以通過 https://http2.akamai.com/demo 直觀感受鸵膏。
綜合上述膊升,使用HTTP/2代替HTTP/1.1以提高接口響應(yīng)的速度,以達到提高qps的目的是此次調(diào)研的方向
3.調(diào)研過程
3.1 HTTP/2相對于HTTP/1.1解決的問題
連接復(fù)用問題:
HTTP/1.1解決了HTTP/1.0的短連接問題谭企,默認使用tcp長連接廓译,減少了客戶端請求接口數(shù)據(jù)時建立tcp連接的開銷,但是HTTP/1.1協(xié)議中瀏覽器客戶端在同一時間债查,針對同一域名下的的請求有一定的數(shù)量限制非区,超出限制會請求會被阻塞,一些網(wǎng)站圍了解決此問題盹廷,配置多個靜態(tài)資源CDN域名征绸。HTTP/2通過多路復(fù)用的方式解決了此問題。
HTTP/1.1隊頭阻塞問題:
HTTP1.1允許客戶端不用等待上一次請求的結(jié)果俄占,就可以發(fā)起下一次請求管怠,但是要求服務(wù)器必須按照接收請求的順序響應(yīng)客戶端的請求,因此一旦隊頭請求出現(xiàn)延遲缸榄,會影響連接中所有的請求響應(yīng)渤弛。HTTP/2基于多路復(fù)用+二進制分層幀的機制,使服務(wù)的請求和響應(yīng)可以實現(xiàn)亂序發(fā)送甚带,解決了此問題她肯。
報頭壓縮
HTTP1.1對于HTTP1.0的很多功能優(yōu)化和擴充其實是增加更多的請求頭和響應(yīng)頭來實現(xiàn)的,一次請求的頭部占有很大開銷欲低,HTTP/2的報頭壓縮辕宏,基于專門為首部壓縮而設(shè)計的HPACK算法,能夠很好的降低協(xié)議的開銷砾莱。
3.2 HTTP2與HTTP/1.1的接口性能測試對比
3.2.1 服務(wù)端功能及代碼
框架基于springboot2.3.1.RELEASE
1.編寫一個用于測試的接口瑞筐,針對每個請求會延遲100ms響應(yīng),對于特殊請求延遲500ms響應(yīng)
@RestController
public class IndexController {
private static Integer oneNumber = 0;
private static Integer twoNumber = 0;
@GetMapping("/hello")
public String testHello(@RequestParam String key) {
try {
if ("1".equals(key)) {
oneNumber ++;
}
if ("2".equals(key)) {
twoNumber ++;
}
if (("1".equals(key) && oneNumber % 100 == 0) || ("2".equals(key) && twoNumber % 100 == 0)) {
Thread.sleep(500L);
} else {
Thread.sleep(100L);
}
System.out.println("請求響應(yīng) key:" + key);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello world";
}
}
IndexController.java
2.設(shè)置監(jiān)聽8443端口,使用HTTP/2協(xié)議
Jar包依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--移除掉了starter-web中的tomcat依賴-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!--注意這里使用undertow聚假,移除掉了starter-web中的tomcat依賴-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
應(yīng)用啟動參數(shù)配置
#端口號
server.port=8443
#ip地址
server.address=0.0.0.0
#啟用HTTP響應(yīng)壓縮
server.compression.enabled=true
# 啟用http2
server.http2.enabled=true
# 啟用ssl
server.ssl.enabled=true
#證書位置
server.ssl.key-store=classpath:keystore.p12
# 證書密碼
server.ssl.key-store-password=123456
# 證書類型
server.ssl.key-store-type= PKCS12
# 協(xié)議類型
server.ssl.protocol=TLSv1.2
server.ssl.key-alias=undertow
注:這里需要生成一個密鑰块蚌,因為HTTP2必須基于HTTPS才能使用
3.增加一個監(jiān)聽8080端口,使用HTTP/1.1協(xié)議
@Component
public class CustomizationBean implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Undertow.Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
}
});
}
}
3.2.2 使用Jmeter測試接口(測試HTTP/2需要配置插件)
線程數(shù)/單個線程請求次數(shù) | HTTP/1.1平均響應(yīng)時間(ms) | HTTP/2平均響應(yīng)時間(ms) |
---|---|---|
10/500 | 187 | 141 |
200/30 | 520 | 246 |
600/10 | 1185 | 571 |
具體數(shù)據(jù)如圖:
線程數(shù)10膘格,單個線程請求次數(shù)500時分別對應(yīng)HTTP/1.1峭范、HTTP/2的呈現(xiàn)情況。
線程數(shù)200瘪贱,單個線程請求次數(shù)30時分別對應(yīng)HTTP/1.1纱控、HTTP/2的呈現(xiàn)情況。
線程數(shù)600菜秦,單個線程請求次數(shù)10時分別對應(yīng)HTTP/1.1甜害、HTTP/2的呈現(xiàn)情況。
4.調(diào)研結(jié)果
經(jīng)過上述實驗球昨,對比使用HTTP/2及HTTP/1.1協(xié)議尔店,在性能優(yōu)化方面有很大提升,后續(xù)可以考慮將HTTP/1.1協(xié)議替換為HTTP/2協(xié)議主慰。
上述實驗使用的是mac筆記本實驗嚣州,實驗接口設(shè)置的100次請求平均sleep 104ms,而最后的平均響應(yīng)時間HTTP/1.1達到了1185ms共螺,HTTP/2達到了571ms该肴,說明請求瓶頸在網(wǎng)絡(luò)傳輸上,因此造成接口性能的優(yōu)化能夠達到原先一倍的情況藐不,實際情況應(yīng)該是網(wǎng)絡(luò)傳輸效率HTTP2相對于HTTP/1.1能有很大的提高沙庐。實際使用到項目上時,需要考慮網(wǎng)絡(luò)傳輸效率提高后對服務(wù)器處理請求造成的壓力佳吞,整體請求的效果優(yōu)化可能達不到上面實驗中翻倍的提升情況。
5.使用風(fēng)險
使用HTTP/2協(xié)議使用了多路復(fù)用解決了應(yīng)用層隊頭阻塞的問題棉安,建立的TCP連接數(shù)更加的少底扳,客戶端和服務(wù)器之間的數(shù)據(jù)傳輸在單個TCP連接上能跑進行更多傳輸,是HTTP/2的優(yōu)勢贡耽,同時也是HTTP/2的劣勢衷模,一旦發(fā)生數(shù)據(jù)包丟失的情況,整條TCP連接上的數(shù)據(jù)傳輸都會受到影響蒲赂,這就是TCP的隊頭阻塞阱冶,此時HTTP/2就會受到很大影響。