简介: ubuntu20.04编译安装nginx 1.21.6并开启fastopen 先安装依赖 apt install -y perl libperl-dev libgd3 libgd-dev libgeoip1 1.21.6.tar.gz 解压 tar zxf nginx-1.21.6.tar.gz -C /opt 准备编译 需要开启tcp fast open需要在--with-cc-opt=里加入-DTCP_FASTOPEN -DTCP_FASTOPEN=23 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2
前面,张戈博客在折腾 Nginx 的 SSL 优化时,注意到前人在 Nginx 的 listen 配置中,添加了 fastopen=3 reuseport 这 2 个参数。 于是脑补了下,原来是启用 Nginx 对 TCP_FASTOPEN 和 TCP_SO_REUSEPORT 新特性的支持,至于有什么好处,请自行脑补下-->传送门 ? 一、必要环境 当我依葫芦画瓢也添加这 2 个参数时,报错了: nginx: [emerg] invalid parameter "fastopen=3" in *** 继续脑补了下,发现系统必须支持 TCP_FASTOPEN 关于 TCP_FASTOPEN 特性在 kernel-3.6 被客户端支持,在 kernel-3.7 被服务端支持,也就是说使用 TCP_FASTOPEN 需要 CentOS 6 更新内核至 3.7 或更高版本 =3 : listen 80 fastopen=3; 最后,reload 重载 Nginx 即可,这样就不会报错了。
解决方案 为了减少回源耗时,建议在tcp连接建立的时候,开启tcp fastopen。 下图是正常连接建立,以及发起http get的请求。 下图是开启tcp FastOpen,可以做到0RTT。大大降低了建立连接的时间。 tcp fastopen相对于quic,不需要进行额外的开发和适配,复用现有的架构,就可以实现0RTT。
mAdapter.getItem(index); dataList.add(new AppInfoLite(info.packageName, info.path, info.fastOpen ; Log.i("HSL", "packageName : " + info.packageName + " , path : " + info.path + " , fastOpen }); } } 使用 Log.i("HSL", "packageName : " + info.packageName + " , path : " + info.path + " , fastOpen : " + info.fastOpen); 代码 , 拦截一下数据 , 查看下传入的是什么参数 : I/HSL: packageName : com.example.filepath , path : /app-debug.apk , fastOpen : false 在 adb shell 中查看 , 该应用在 SD 卡根目录 ; 2、返回到 HomeActivity 执行的操作 使用的 MVP
*if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) ! = 0 && inet_csk(sk)->icsk_accept_queue.fastopenq == NULL) { // fastopen的逻辑 if ((sysctl_tcp_fastopen = 0) err = fastopen_init_queue(sk, backlog); else if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT2 = 0) err = fastopen_init_queue(sk, ((uint)sysctl_tcp_fastopen) >> 16); else err = 首先,我们看下除fastopen之外的逻辑(fastopen以后开单章详细讨论)。也就是最后的inet_csk_listen_start调用。
如果你是Linux系统,那么需要查看/proc/sys/net/ipv4/tcp_fastopen这个文件。 tcp_fastopen可以有四种值,如下所示: 0 — 表示TFO未开启 1 — 表示TFO开启了,但是只对客户端有效 2 — 表示TFO开启了,但是只对服务器端有效 3 — 表示TFO开启了,同时对客户端和服务器端有效 上面的代码中,我们看到ServerBootstrap可以设置option参数,ChannelOption中包含了所有可以设置的channel的参数,对应的TFO的参数是ChannelOption.TCP_FASTOPEN , 所以我们只需要添加到ServerBootstrap中即可: sb.option(ChannelOption.TCP_FASTOPEN, 50) ChannelOption.TCP_FASTOPEN ChannelFuture f = b.connect(HOST, PORT).sync(); client要支持TFO,需要添加这样的操作: b.option(ChannelOption.TCP_FASTOPEN_CONNECT
/app-debug.apk , fastOpen : false 通过 VirtualCore.get().getInstalledAppInfo(info.packageName, 0); 代码 , < 6; int flags = InstallStrategy.COMPARE_VERSION | InstallStrategy.SKIP_DEX_OPT; // fastOpen 值是 false , 该分支没有命中 if (info.fastOpen) { flags |= InstallStrategy.DEPEND_SYSTEM_IF_EXIST /app-debug.apk , fastOpen : false 此处找到了可以直接调用的 API 方法 , 调用 VirtualCore.get().installPackage( SD卡绝对路径
4.4 启用TCP_FASTOPEN选项TCP_FASTOPEN是一种TCP扩展选项,可以减少网络延迟,据测试,启用TCP_FASTOPEN选项可以将TCP连接建立时间降低约30%左右,建议启用该选项。 同时,对Nginx的性能优化进行了详细的讲解,包括启用缓存、使用gzip压缩、配置HTTP/2协议、启用TCP_FASTOPEN选项和调整文件描述符限制等。
路径作为默认查询路径,因此只需要将该路径前缀的请求转发到doh-server即可,如下: nginx配置(已配置好TLS与HTTP2) server { listen 443 ssl http2 fastopen =256 reuseport; listen [::]:443 ssl http2 fastopen=256 reuseport; server_name doh.wbuntu.com coredns在未配置TLS证书时,可使用nginx作为前端来复用web服务,如下: nginx配置(已配置好TLS与HTTP2) server { listen 443 ssl http2 fastopen =256 reuseport; listen [::]:443 ssl http2 fastopen=256 reuseport; server_name doh.wbuntu.com
*tcp_check_req(struct sock *sk, struct sk_buff *skb, struct request_sock *req, bool fastopen resetting legit local connections. */ req->rsk_ops->send_reset(sk, skb); } else if (fastopen ) { /* received a valid RST pkt */ reqsk_fastopen_remove(sk, req, true); tcp_reset(sk fastopen) { inet_csk_reqsk_queue_drop(sk, req); __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS
net.ipv4.tcp_fin_timeout = 30 net.ipv4.tcp_synack_retries = 1 net.ipv4.tcp_syn_retries = 1 net.ipv4.tcp_fastopen grep "net.ipv4.tcp_congestion_control" # 默认值: net.ipv4.tcp_congestion_control = cubic net.ipv4.tcp_fastopen 的内核版本下用来加速连续TCP连接的数据交互的TCP协议扩展(Client内核版本为3.6;Server内核版本为3.7中使用) sudo sysctl -a | grep "net.ipv4.tcp_fastopen " # net.ipv4.tcp_fastopen = 1 # net.ipv4.tcp_fastopen_blackhole_timeout_sec = 3600 # net.ipv4.tcp_fastopen_key
*/#define TCP_REPAIR_OPTIONS 22 /* Repair TCP connection options */#define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */#define TCP_TIMESTAMP 24 /* TCP time stamp */#define TCP_NOTSENT_LOWAT */#define TCP_FASTOPEN_CONNECT 30 /* Attempt FastOpen with connect. */#define TCP_FASTOPEN_KEY 33 /* Set the key for Fast Open (cookie). */#define TCP_FASTOPEN_NO_COOKIE 34 /* Enable TFO without a TFO cookie.
__u32 snd_cwnd_clamp; __u32 snd_ssthresh; __u8 syn_data:1, /* SYN includes data */ syn_fastopen :1, /* SYN includes Fast Open option */ syn_fastopen_exp:1,/* SYN includes Fast Open exp. option */ syn_fastopen_ch:1, /* Active TFO re-enabling probe */ syn_data_acked:1,/* data in SYN is
*) Bugfix: "getsockopt(TCP_FASTOPEN) ... failed" messages might appear in logs during binary
TCP_FASTOPEN:启用 TCP Fast Open 功能。该功能可以加速 TCP 连接建立过程,减少握手延迟。值:int 型,通常设置为 1(启用)或 0(禁用)。
这要通过tcp_fastopen 参数。由于只有客户端和服务器同时支持时,TFO 功能才能使用,所以 tcp_fastopen参数是按比特位控制的。 其中,第 1 个比特位为 1 时,表示作为客户端时支持 TFO;第 2 个比特位为 1 时,表示作为服务器时支持 TFO,所以当 tcp_fastopen 的值为 3 时(比特为 0x11)就表示完全支持 net.ipv4.tcp_fastopen = 33.4 提升TCP四次挥手的性能Tcp协议的关闭:close 和 shutdown 函数都可以关闭连接,但这两种方式关闭的连接,不只功能上有差异,控制它们的
--tcp-fastopen: 我们知道 tcp 一个被诟病的问题是建立连接比较耗时,需要三次握手,我们已经做了很多方法来减少建立 tcp 连接的次数,比如 内核层 keepalive,http 的 keepalive ;那么有没有办法直接让 tcp 建立连接本身变得更快呢,一个办法就是 TCP Fastopen, 他是怎么运作的可以参考 wiki 或者这两篇文章:TCP 的那些事 | TCP Fast Open_CoderAndClimber 的博客-CSDN博客_fastopen 和 Linux的TCP实现之:三次握手 | Zorro’s Linux Book; 这里我也简单概括一下,就是在客户端非第一次建立连接的时候可以带一个 cookieid
opt.ipv6only; #endif #if (NGX_HAVE_SETFIB) ls->setfib = addr->opt.setfib; #endif #if (NGX_HAVE_TCP_FASTOPEN ) ls->fastopen = addr->opt.fastopen; #endif #if (NGX_HAVE_REUSEPORT) ls->reuseport = addr->opt.reuseport
这要通过tcp_fastopen 参数。由于只有客户端和服务器同时支持时,TFO 功能才能使用,所以 tcp_fastopen参数是按比特位控制的。 其中,第 1 个比特位为 1 时,表示作为客户端时支持 TFO;第 2 个比特位为 1 时,表示作为服务器时支持 TFO,所以当 tcp_fastopen 的值为 3 时(比特为 0x11)就表示完全支持 net.ipv4.tcp_fastopen = 3复制代码3.4 提升TCP四次挥手的性能Tcp协议的关闭:close 和 shutdown 函数都可以关闭连接,但这两种方式关闭的连接,不只功能上有差异
public String packageName; public String name; public Drawable icon; public boolean fastOpen