netty系列之:让TCP连接快一点,再快一点
简介
经典的TCP三次握手大家应该很熟悉了,三次握手按道理说应该是最优的方案了,当然这是对于通用的情况来说的。那么在某些特殊的情况下是不是可以提升TCP建立连接的速度呢?
答案是肯定的,这就是今天我们要讲的TCP fast open和netty。
TCP fast open
什么是TCP fast open呢?
TCP fast open也可以简写为TFO,它是TCP协议的一种扩展。为什么是fast open呢?这是因为TFO可以在初始化建立连接的时候就带上部分数据,这样在TCP连接建立之后,可以减少和服务器交互的次数,从而在特定的情况下减少响应的时间。
既然TFO这么好,为什么我们很少见到使用TFO协议的呢?
这是因为TFO是有缺陷的,因为TFO会在sync包中带上一些数据信息,那么当sync包重发的时候,就会造成接收方接受到重复的数据。
所以,如果是用TFO,那么接收方则需要具有能够处理重复数据的能力。
在程序界,防止数据重复提交有一个好听的名字叫做幂等性,只有具有幂等性的服务器才能够使用TFO。
开启TFO
既然TFO这么优秀,怎么才能开启TFO呢?
TFO的开启首先需要操作系统的支持,如果你是mac系统,恭喜你,mac默认情况下已经支持TFO了,你不需要进行任何操作。
如果你是Linux系统,那么需要查看/proc/sys/net/ipv4/tcp_fastopen这个文件。
tcp_fastopen可以有四种值,如下所示:
0 -- 表示TFO未开启
1 -- 表示TFO开启了,但是只对客户端有效
2 -- 表示TFO开启了,但是只对服务器端有效
3 -- 表示TFO开启了,同时对客户端和服务器端有效
通过上面的设置,我们就在操作系统层开启了TFO的支持。
接下来,我们看一下如何在netty中使用TFO。
netty对TFO的支持
首先我们看下如何在netty的服务器端开启TFO支持。
在这之前,我们先回顾一下如何建议一个普通的netty服务器:
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new TFOServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true);
// 绑定端口并开始接收连接
ChannelFuture f = b.bind(port).sync();
上面的代码中,我们看到ServerBootstrap可以设置option参数,ChannelOption中包含了所有可以设置的channel的参数,对应的TFO的参数是ChannelOption.TCP_FASTOPEN, 所以我们只需要添加到ServerBootstrap中即可:
sb.option(ChannelOption.TCP_FASTOPEN, 50)
ChannelOption.TCP_FASTOPEN的值表示的是socket连接中可以处于等待状态的fast-open请求的个数。
对于客户端来说,同样需要进行一些改动,先来看看传统的client端是怎么工作的:
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new TFOClientHandler());
}
});
// 连接服务器
ChannelFuture f = b.connect(HOST, PORT).sync();
client要支持TFO,需要添加这样的操作:
b.option(ChannelOption.TCP_FASTOPEN_CONNECT, true)
还记得TFO是做什么的吗?TFO就是在sync包中发送了一些数据。所以我们需要在client端对发送的数据进行处理,也就是说在client和server端建立连接之前就需要向channel中发送消息。
要获得非建立连接的channel,则可以调用Bootstrap的register方法来获取channel:
Channel channel = b.register().sync().channel();
然后向该channel中写入byteBuf:
ByteBuf fastOpenData = directBuffer();
fastOpenData.writeBytes("TFO message".getBytes(StandardCharsets.UTF_8));
channel.write(fastOpenData);
最后再和服务器建立连接:
// 连接服务器
SocketAddress serverAddress = SocketUtils.socketAddress("127.0.0.1", 8000);
ChannelFuture f = channel.connect(serverAddress).sync();
总结
这样一个一个支持TFO的客户端和服务器就完成了。尽情使用吧。
本文的例子可以参考:learn-netty4
本文已收录于 http://www.flydean.com/44-netty-tcp-fast-open/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
netty系列之:让TCP连接快一点,再快一点的更多相关文章
- 前端通信:ajax设计方案(八)--- 设计请求池,复用请求,让前端通信快、更快、再快一点
直接进入主题,本篇文章有点长,包括从设计阶段,到摸索阶段,再到实现阶段,最后全面覆盖测试阶段(包括数据搜集清洗),还有与主流前端通信框架进行对比PK阶段. 首先介绍一下一些概念: 1. 浏览器的并发能 ...
- 我为 Netty 贡献源码 | 且看 Netty 如何应对 TCP 连接的正常关闭,异常关闭,半关闭场景
欢迎关注公众号:bin的技术小屋,本文图片加载不出来的话可查看公众号原文 本系列Netty源码解析文章基于 4.1.56.Final版本 写在前面..... 本文是笔者肉眼盯 Bug 系列的第三弹,前 ...
- Netty系列(四)TCP拆包和粘包
Netty系列(四)TCP拆包和粘包 一.拆包和粘包问题 (1) 一个小的Socket Buffer问题 在基于流的传输里比如 TCP/IP,接收到的数据会先被存储到一个 socket 接收缓冲里.不 ...
- TCP系列07—连接管理—6、TCP连接管理的状态机
经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看TCP连接的状态变化 一.TCP状态机整体状态转换图(截取自第二版TCPIP详解) 二.TCP连接建立 ...
- TCP系列05—连接管理—4、TCP连接的ISN、连接建立超时及TCP的长短连接
一.TCP连接的ISN 之前我们说过初始建立TCP连接的时候的系列号(ISN)是随机选择的,那么这个系列号为什么不采用一个固定的值呢?主要有两方面的原因 防止同一个连接的不同实例(di ...
- TCP系列03—连接管理—2、TCP连接的同时打开和同时关闭
在前面的内容中我们介绍了TCP连接管理中最常见的三次握手方式和四次挥手的方式.但是有可能A和B两端同时执行主动打开并连接对方或者同时执行主动关闭连接(尽管发生这种情况的可能性比较低低),这个时候的流程 ...
- 支持并发的httpclient(基于tcp连接池以及netty)
闲来无事,将曾经自己写的一个库放出来吧. . 有的时候会有这样子的需求: (1)serverA通过HTTP协议来訪问serverB (2)serverA可能会并发的像B发送非常多HTTP请求 类似于上 ...
- netty系列之:来,手把手教你使用netty搭建一个DNS tcp服务器
目录 简介 搭建netty服务器 DNS服务器的消息处理 DNS客户端消息请求 总结 简介 在前面的文章中,我们提到了使用netty构建tcp和udp的客户端向已经公布的DNS服务器进行域名请求服务. ...
- TCP系列04—连接管理—3、TCP连接的半打开和半关闭
在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...
随机推荐
- ShardingJDBC
ShardingJDBC的核心流程主要分成六个步骤,分别是:SQL解析->SQL优化->SQL路由->SQL改写->SQL执行->结果归并,流程图如下: sharding ...
- css处理工具PostCss
在 Web 应用开发中,CSS 代码的编写是重要的一部分.CSS 规范从最初的 CSS1 到现在的 CSS3,再到 CSS 规范的下一步版本,规范本身一直在不断的发展演化之中.这给开发人员带来了效率上 ...
- 深入理解Java虚拟机之图解Java内存区域与内存溢出异常
Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...
- 图解GNN:A Gentle Introduction to Graph Neural Networks
1.图是什么? 本文给出得图的定义为:A graph represents the relations (edges) between a collection of entities (nodes) ...
- PCx安装使用
PCx安装使用 注意:不要到Mittleman的网页下给的那个网站去下载,版本太老,只能在REDHAT操作系统上编译,且不能运行 mkdir PCx cd PCx/ git clone https:/ ...
- Go环境配置和GoModule
Linux相关 Linux常用操作 mkdir directory --创建文件夹 vi file --创建文件,再关闭vim rm file --删除文件 rm -rf directory --递归 ...
- [Raspberry Pi] 入门使用
今天开始介绍Raspberry Pi(简称RPi,下同)入门的一些基础知识. 第1部分: 安装RPi 1.1 从 http://www.raspberrypi.org/downloads 下载RPi ...
- 【记录一个问题】android opencl c++: 不要Context, CommandQueue类的赋值函数
一开始代码中这样写了: cl::Context ctx = cl::Context(CL_DEVICE_TYPE_GPU, NULL); cl::CommandQueue queue= cl::Com ...
- WSL删除子系统后无法重装
问题 WSL卸载后安装error 解决办法 UWP应用卸载后没有删除目录下的文件 C:\Users\wwwfe\AppData\Local\Packages路径下删除就可以了 再次安装会卡顿很久,可能 ...
- 实习之bii--配置esxi重启时,虚拟机也跟随重启
由于初创环境不稳定又是服务器会重启,而内部安装的多部虚拟机并不默认跟随启动,需要设置,方法如下: 1.在本地通过vsphere client 登录到esxi的服务器上,然后点击配置找到虚拟机启动/关机 ...