传输链路优化
虽然我们不能左右网络提供商例如联通移动的网络质量,但是我们可以通过一些手段来优化传输链路。
- 用 HTTP2 替代 HTTP 1.1
尽管我们在 1.1 的版本中使用了例如 keep-alive 的方法去保持长连接,然后让所有的请求按照 FIFO 的方法去请求,进而减少三次握手所带来的时间延迟,但随之而来的队列阻塞问题也是一个很大的缺陷。
HTTP1.1 中流是最小的单位,在 1.1 中我们没办法将请求拆开,一起发送,因为客户端无法识别这些碎片,然而 HTTP2 帧 (frame) 是最小的单位,用来描述各种资源,每个帧只要带上唯一标识就能判断是同属一个流,客户端可以通过标识来组装成一个完整的流
通过 io 多路复用,每一个域名仅需一个 TCP 的连接,我们可以任意传输资源,因为不需要考虑 tcp 的延迟问题,所以我们也不用刻意缩小连接的次数,所以在 1.1 上把小数据改成大数据的优化方法在 2 上反而变成了反模式,不过 2 中传输大数据如果不分片的话,反而比 1.1 要慢,毕竟你单点人 1.1 是多路分布式传输肯定比你更快了。
应用层 HTTP 的传输层协议在 1.1 和2时代都是 TCP 协议,然而在 HTTP3 的时候我们将 TCP 协议替换为 UDP 协议,UDP 没有丢包重传的机制,UDP 传了就不管了,所以 http3 的可靠性不依靠传输层,而是在应用层上进行安全设置的,HTTP3 可以对每一个流都能单独控制,在 2 的时候 io 多路复用,TCP 协议接收到了大量的数据然后遇到了损坏,这个时候又要开始重传,这就是 HTTP2 传输大文件慢的原因,HTTP3 不使用 TCP 所以它没有这个缺陷,tcp 在连接时不可避免的会三次握手,这在游戏等领域存在了超时,中断,重连,这个过程带来的问题非常的难受,HTTP3 拥有连接标识符,这个唯一标识符就是标识了客户端和浏览器的连接 token,切换网络的时候,只需要向服务器发送一个包含该 token 的数据包就可以重新连接了,即便 IP 地址发生更改也可以连接
总结一下,搞什么优化,用 HTTP3 不香吗?
下面演示一下 HTTP3 tls 证书,ipv6 的静态服务器
package main
import (
"github.com/gin-gonic/gin"
"github.com/quic-go/quic-go/http3"
"log"
)
func main() {
router := gin.Default()
router.Static("/", "./static")
// 指定现成的 TLS 证书和私钥文件路径
tlsCertPath := "path/to/your/cert.pem"
tlsKeyPath := "path/to/your/key.pem"
server := http3.Server{ // 可以自动开启ipv6和ipv4
Addr: ":8080",
Handler: router,
TLSConfig: generateTLSConfig(tlsCertPath, tlsKeyPath),
}
err := server.ListenAndServeTLS("", "")
if err!= nil {
panic(err)
}
}
func generateTLSConfig(certPath, keyPath string) *http3.TLSConfig {
return &http3.TLSConfig{
Certificates: loadCertificates(certPath, keyPath),
}
}
func loadCertificates(certPath, keyPath string) []http3.TLSConfigCertificate {
cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err!= nil {
log.Fatalf("加载证书和私钥失败: %v", err)
}
return []http3.TLSConfigCertificate{cert}
}