Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Linux系统服务端口的那些事
Search
yongboy
June 28, 2014
Technology
2
1.4k
Linux系统服务端口的那些事
了解Linux服务器端口的用途和局限,以及如何突破端口限制。
yongboy
June 28, 2014
Tweet
Share
Other Decks in Technology
See All in Technology
Zennのパフォーマンスモニタリングでやっていること
ryosukeigarashi
0
200
Oracle Cloud Infrastructureデータベース・クラウド:各バージョンのサポート期間
oracle4engineer
PRO
29
13k
RubyのWebアプリケーションを50倍速くする方法 / How to Make a Ruby Web Application 50 Times Faster
hogelog
3
950
VideoMamba: State Space Model for Efficient Video Understanding
chou500
0
190
これまでの計測・開発・デプロイ方法全部見せます! / Findy ISUCON 2024-11-14
tohutohu
3
370
AIチャットボット開発への生成AI活用
ryomrt
0
170
アジャイルチームがらしさを発揮するための目標づくり / Making the goal and enabling the team
kakehashi
3
150
心が動くエンジニアリング ── 私が夢中になる理由
16bitidol
0
100
10XにおけるData Contractの導入について: Data Contract事例共有会
10xinc
7
680
Introduction to Works of ML Engineer in LY Corporation
lycorp_recruit_jp
0
140
SREが投資するAIOps ~ペアーズにおけるLLM for Developerへの取り組み~
takumiogawa
2
470
マルチプロダクトな開発組織で 「開発生産性」に向き合うために試みたこと / Improving Multi-Product Dev Productivity
sugamasao
1
310
Featured
See All Featured
A Philosophy of Restraint
colly
203
16k
Producing Creativity
orderedlist
PRO
341
39k
The Cult of Friendly URLs
andyhume
78
6k
A designer walks into a library…
pauljervisheath
204
24k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Making Projects Easy
brettharned
115
5.9k
Scaling GitHub
holman
458
140k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
Rails Girls Zürich Keynote
gr2m
94
13k
Keith and Marios Guide to Fast Websites
keithpitt
409
22k
VelocityConf: Rendering Performance Case Studies
addyosmani
325
24k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
Transcript
Linux服务器端口的那些事 了解端口的用途和局限,以及如何突破端口限制 聂永@2014/06/26
目录 目录 IP和协议端口 网络四元组、二元组 突破端口限制 代码绑定IP和端口 外部程序绑定IP和端口 地址和TIME_WAIT 服务器地址重用和释放 演示和用途
数据进入栈封装过程
IP地址位置 IP报文 IP地址属于IP数据报,标识源主机和目标主机
协议端口在TCP数据包中位置 只有TCP数据包头部中包含端口 端口号和TCP服务器进程存在映射关系 端口,具有数据包路由作用 TCP传输层根据端口路由数据包到服务器程序所申请的缓存队列中
协议端口用途 一台服务器好比一座院子 IP地址比作院子大门;一座院子对应至少一个大门 每一个具体的服务程序进程好比一个房子 端口号好比进入房间的门
一个房间至少一个门 服务器程序可以决定由哪一个大门才能进入房间 以太网帧根据IP地址决定投递主机位置,端口决定数据报送达应用程 序映射 服务器内核接收的数据将根据端口进行路由传递到对应程序中
协议端口的一些常识 16位表示 范围:从0 到65535(2^16-1) 已知端口号[0,1023],这些端口由IANA分配和控制 Linux下需要root权限才能使用
[1024,65535],可自由使用端口数量不超过64512个 但不要和已有服务进行冲突
UNP对网络四元组的解释 《UNIX网络编程卷1:套接字联网API(第3版)》(简称UNP)解 释: 一个TCP连接的套接字对(socket pari)是一个定义该连接的两个端点 的四元组,即本地IP地址、本地TCP端口号、外地IP地址、外地TCP 端口号。套接字对唯一标识一个网络上的每个TCP连接。
...... 标识每个端点的两个值(IP地址和端口号)通常称为一个套接字。
四元组解释 仅针对TCP IP用于标识通讯的机器,端口号用于标识通信的进程。 网络四元组,一个完整TCP连接参阅双方体现: {请求者本机IP地址,请求者本机端口,目标IP地址,目标端口} 一次TCP请求必须把自身IP、PORT以及目标IP、目标PORT都要携
带上
Linux系统端口范围 默认范围:1~65535 0-1023已知端口,已被分配,需要ROOT权限 可被自由使用端口范围:65535 - 1024 ≈
64000 查看Linux系统默认可使用端口范围: sysctl -a | grep 'net.ipv4.ip_local_port_range' 32768 61000 修改其端口范围: sysctl -w net.ipv4.ip_local_port_range=1024 65535 保存修改: sysctl -p 持久化
如何突破端口数量限制 默认情况下,系统对外发出的请求数量受限于可用端口数量! 网络四元组中{本机IP,本机Port}两元组表示一个套接字 一个套接字表示系统可以向外请求的一个完整的TCP连接 套接字的数量表示系统可对外请求的完整TCP连接数量!
本机可用TCP套接字数量 = 本机IP数量 * 本机可用端口数量 绑定10个IP地址,自由可用端口约64000,那么可用端口数量 10 * 64000 = 640000,64万!
其它受限条件 打开文件句柄的限制,必须要大于可用端口数量 系统内存限制 每一个连接最少占用4K内存,连接数*4K = 需要的内存数,要求系 统内存要能够完全满足
线程/IO模型,非阻塞型:同步非阻塞/异步非阻塞,不用占满CPU 系统绑定的物理网卡数量受限
虚拟IP来帮忙 添加物理网卡,费时费劲,不太方便 可分配一个或多个IP地址给系统的虚拟IP,很方便! Linux添加虚拟IP: ifconfig eth0:0 192.168.190.151
netmask 255.255.255.0 up 写入/etc/rc.local里可防止重启后丢失 试试Docker 已经释出Docker 1.0,可以尝试一下
代码指定IP和端口 C语言如何做 struct sockaddr_in clnt_addr; clnt_addr.sin_addr.s_addr = inet_addr(server_ip); clnt_addr.sin_port
= htons(server_port); Java如何做 java.net.InetSocketAddress 此类实现 IP 套接字地址(IP 地址 + 端口号)。它还可以是一个对 (主机名 + 端口号),在此情况下,将尝试解析主机名。 如果解析失败,则该地址将被视为未解析地址,但是其在某些情形下 仍然可以使用,比如通过代理连接。 服务器程序可以绑定所有可用IP地址 客户端请求者只能绑定一个具体IP(若非手动指定,系统默认选择可 用IP)
代码示范 服务器端示范程序,绑定IP和端口 https://gist.github.com/yongboy/37875ad2476b0a8cab90 客户端示范程序,可绑定所有可用IP和端口,对外发出海量请求 https://gist.github.com/yongboy/5476214 后面会演示
指定已有程序绑定IP/端口? 已有程序,如何修改其绑定的IP地址和端口 ? 修改配置文件 试试linux系统的bindp小程序吧! https://github.com/yongboy/bindp
可在运行之前硬绑定的指定IP和端口 原理: LD_PRELOAD,允许定义在程序运行前优先加载的动态链接库 如何使用: BIND_ADDR="your ip" BIND_PORT="your port" LD_PRELOAD=/your_path/bindp.so the real command ...
bindp + nginx + curl的示范1 nginx默认80端口, 设置nginx以8888端口进行启动 BIND_PORT="8888" LD_PRELOAD=/home/yongboy/bindp/bindp.so
/usr/sbin/nginx -c /etc/nginx/nginx.conf 测试端准备 绑定特定IP和端口: BIND_ADDR="192.168.192.141" BIND_PORT="16888" LD_PRELOAD=/home/yongboy/bindp/bindp.so curl http://192.168.192.130 nginx日志输出:
bindp + nginx + curl的示范2 测试端第一次请求 BIND_ADDR="192.168.192.141" BIND_PORT="16888" LD_PRELOAD=/home/yongboy/bindp/bindp.so
curl http://192.168.192.130 测试端第二次请求(间隔很短,不超过10秒钟) BIND_ADDR="192.168.192.141" BIND_PORT="16888" LD_PRELOAD=/home/yongboy/bindp/bindp.so curl http://192.168.192.130 持续观察Nginx日志输出
端口释放以及TIME_WAIT阶段 端口释放发生在四次挥手期间 主动关闭方产生TIME_WAIT 主动方最后一次发送挥手时计算 等待真正关闭
占用端口何时释放? 测试端连接虽已关闭,但被占用端口系统不会立即释放 主动关闭方产生TIME_WAIT TIME_WAIT需要等待分组彻底消失,2倍MSL(Maximum Segment Life), 1MSL
= 30s(Linux系统) sysctl -a | grep net.ipv4.tcp_fin_timeout net.ipv4.tcp_fin_timeout = 60 原因: 1)TIME_WAIT可确保系统有足够时间让对端收到Fin ACK,如果 对方没有收到Fin Ack,会触发重发Fin ACK,2个MSL时间周期 2)系统有足够的时间让已关闭的连接不会跟后面的连接混淆(避免 连接被重用时,可能路由器层面缓存IP数据包,导致混淆) 3)TIME_WAIT下一站是真正的关闭
服务器程序地址重用 服务器程序启动时需要显式标注自身需要地址重用 C语言版: int reuseaddr_on = 1; if
(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on))) err(1, "setsockopt failed"); Java&Netty 版本 Java: ServerSocket socket = new ServerSocket(); socket.setReuseAddress(true); Netty 3.x bootstrap.setOption("reuseAddress", true); Netty 4.x/5.x ServerBootstrap server = new ServerBootstrap(); server.group(bossGroup, workerGroup) .option(ChannelOption.SO_REUSEADDR, true); 演示实际效果 ?
服务器程序地址重用2 不指定地址重用,在短时间内(60S内)再次重启: server: bind failed: Address already in use
地址重用 可以快速重启 同一端口可以被多次使用,但需要绑定到不同IP上 不同IP绑定同一端口 绑定不存在的IP地址: bind failed: Cannot assign requested address 不指定具体IP,意味着继续使用默认IP,其它进程绑定端口 bind failed: Address already in use 已绑定的指定IP和端口,其它进程再次绑定: bind failed: Address already in use
服务器如何快速回收端口? Linux系统默认值: net.ipv4.tcp_tw_reuse = 0 net.ipv4.tcp_tw_recycle =
0 默认都是关闭 tcp_tw_recycle,比较激进,若开启需同时设置 tcp_timestamps=1 不建议修改 修改可能会产生意想不到的问题 服务器端尽量不要主动关闭连接
Linux一些小工具 通过端口查看进程 lsof -i:port 进程查看端口 netstat
–nltp|grep 进程号 SS命令
突破端口限制的示范/用途 若有时间,演示从测试机发出超过64000个对外请求 只要机器性能够好,可以发出超过100万个并发长连接请求 绑定IP和端口,突破端口数量限制,用途: 访问代理服务器
内网/外网百万长连接压力测试 ......
谢谢聆听!