什么是Socket?
    大家都用电脑上网,当我们访问运维社区https://www.unixhot.com的时候,我们的电脑和运维社区的服务器就会创建一条Socket,我们称之为网络套接字。那么既然是网络通信,肯定是成对的。至少有一个客户端和服务端,我们称之为套接字对。
    一个套接字对(socket pair)是一个定义该网络连接的两个端点的五元组,包括:

  1. 源IP地址
  2. 源端口
  3. 目的IP地址
  4. 目的端口
  5. 类型:TCP or UDP

那么针对于HTTP请求来说,我们知道底层是建立了一条TCP的Socket,那么TCP的套接字对就是一个四元组,因为协议已经确定了:
    1.源IP地址、2.源端口、3.目的IP地址、4.目的端口。

客户端的随机端口
为了更直观的认识这个TCP Socket,我们做一个小实验,我这里准备了两台服务器:

当客户端192.168.56.11访问192.168.56.12的9999端口的时候,那么会选择一个随机端口来进行通信,那么这个随机端口,到底是从什么范围随机出来了呢,端口总有一个范围不可能无穷多的。   
    那么对于TCP套接字来说客户端的一个IP地址,到底能有多少个端口呢?由于TCP协议头部使用16位来保存端口号,所以端口的个数最多为65536个,2^16=65536。

没错,是65536个。但是为什么我们经常看到网上说可用端口最大65535个呢,也就是2^16-1个。因为端口号是从0开始算的,0-65535那就是65536个。而0端口是保留端口,无论是TCP还是UDP都是不用使用的,当然这个是标准,那到底能不能监听端口0呢,下面我用一个python脚本,监听本地的端口0来试试。

[root@test ~]# catbind_port_zero.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''本脚本监听本地的127.0.0.1的端口0,
探索端口0的奥秘'''
import socket
def bind_port_zero():
ss = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ss.bind(('127.0.0.0', 0))
addr, port = ss.getsockname()
ss.close()
print(addr, port)
bind_port_zero()

执行脚本,看看到底能不能正常监听:

[root@test ~]# pythonbind_port_zero.py
('127.0.0.0', 53692) [root@test ~]# pythonbind_port_zero.py
('127.0.0.0', 59444)

可以发现,可以正常监听,但是呢并没有监听到端口0。实验证明在Linux下如果在bind的时候指定端口0,那么由系统随机选择一个可用端口来bind。

好的,我们现在知道了端口的范围0-65535,那么作为客户端访问其它服务端的时候,能用多少呢?并不是这个范围都可以用的。那么在Linux下我们可以这么获取本地的随机端口范围:

[root@test ~]# cat/proc/sys/net/ipv4/ip_local_port_range
32768 61000

不要惊讶答案确实是32768到61000,现在你应该明白,别人说的发10万并发进行压力测试代表什么意思了吧。至少默认情况下是无法实现的,读完这句话,是否有启发呢?并不是不能实现哦。

瓶颈真的只有随机端口范围吗?

刚才我们也看了,我们访问其它服务器,作为客户端,我们要使用一个随机端口,32768-61000,貌似也不少,当然你还可以修改它,扩大随机端口范围。例如我们使用Nginx做反向代理负载均衡的时候,用户端和Nginx建立Socket进行通信,Nginx还需要和后端真实服务器也建立Socket进行通信,在高并发的场景下,这个随机端口肯定是一个瓶颈。但是真的只有随机端口范围是瓶颈吗?下面我们使用ab命令来对百度进行一次压力测试。

ab是Apache的性能测试工具,可以模拟并发进行Web性能测试。在CenotOS下,你可以这样来安装:

[root@test ~]# yuminstall -y httpd-devel

按照咱们之前的认识,随机端口61000-32768=28232,那么我实验的机器是一台刚安装的系统,没有什么网络传输,即便有,我们创建2万个套接字对应该是没问题吧。事实真的如此吗?我们用实验来证明:

我们模拟发送2万个请求,2000的并发来测试百度:

[root@test ~]#ab -n 10000 -c 2000 https://www.baidu.com/
This isApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to TheApache Software Foundation, http://www.apache.org/ Benchmarkingwww.baidu.com (be patient)
socket: Toomany open files (24)

这不可能,为什么报错了?不要担心,报错我们很容易看懂了socket: Too many open files (24)

,不能打开太多的文件。我们使用ulimit来看看系统资源限制。

[root@test ~]# ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 31219
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
(省略部分输出)

没错,默认情况下,当前用户能够打开的文件数量最大是1024,但是这个和我们使用ab测试有什么关系呢?ab测试创建的不是socket吗?如果你不理解,那就要回归本质,想想我们刚刚学习Linux的时候,经常听到的一句Linux的思想“一切皆文件”!谁说socket不是一个文件呢?
    我相信你知道怎么做了,你可以使用ulimit –n来修改当前用户、当前session的限制,也可以修改配置文件/etc/security/limits.conf来彻底解决这个问题,这也是进行系统性能调优的必备基础。

创建一条TCP Socket

好的,刚才只是一个小插曲,我们继续探索TCP Socket,光说不练是个棒槌。我们来创建一个套接字对看看:
服务端:
首先,我们在192.168.56.12上使用nc命令,来监听9999端口。

[root@192.168.56.12 ~]#nc -l -4 -p 9999 -k
[root@192.168.56.12 ~]#netstat -ntlp | grep 9999
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 26789/n

客户端:
在客户端,同样使用nc命令来连接到服务端的9999端口。

[root@192.168.56.11 ~]#nc 192.168.56.12 9999

好的,现在你可以在客户端上输入任何的语言和服务端愉快的聊天了?不过这不是重点。

查看Socket

我们先来看看客户端的TCPSocket。

[root@192.168.56.11 ~]#netstat -na | grep 9999
tcp 0 0 192.168.56.11:11525 192.168.56.12:9999 ESTABLISHED

服务端的TCP Socket

[root@192.168.56.12 ~]#netstat -na | grep 9999
tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN
tcp 0 0 192.168.56.12:9999 192.168.56.11:11525 ESTABLISHED

我相信你已经真正理解了Socket,剩下的就是无尽的想象,还记得TIME_WAIT吗?如果有大量的TIME_WAIT存在,那么这个套接字对是不释放的,不释放也就代表着占用一个,资源嘛,占用一个就少一个。怎么优化呢?且听下回分解!
    不过,如果你真的理解了Socket的概念,你已经有了一个终极解决方案。既然一个TCP Socket是一个四元组,那如果我这台机器有多个IP地址呢?哈哈,这是一句画龙点睛之语,你懂的!

使用伪终端发送数据
    最后,留一个小彩蛋,除了使用nc进行数据发送之外,其实Linux还提供了一种称之为伪设备的方式,让我们来体验下/dev下面的tcp伪设备。/dev下面提供了很多的伪设备,比如tcp就可以用来直接进行远程端口的访问。

[root@192.168.56.11 ~]# echo"886" > /dev/tcp/192.168.56.12/9999

赶紧看看服务端有没有收到886。

转载处:https://www.unixhot.com/article/65

Web性能优化之-深入理解TCP Socket的更多相关文章

  1. 关于WEB 性能优化 (摘抄)

    压缩源代码和图片 JavaScript文件源代码可以采用混淆压缩的方式,CSS文件源代码进行普通压缩,JPG图片可以根据具体质量来压缩为50%到70%,PNG可以使用一些开源压缩软件来压缩,比如24色 ...

  2. Web 性能优化:Preload与Prefetch的使用及在 Chrome 中的优先级

    摘要: 理解Preload与Prefetch. 原文:Web 性能优化:Preload,Prefetch的使用及在 Chrome 中的优先级 作者:前端小智 Fundebug经授权转载,版权归原作者所 ...

  3. Web 性能优化:21 种优化 CSS 和加快网站速度的方法

    这是 Web 性能优化的第 4 篇,上一篇在下面看点击查看: Web 性能优化:使用 Webpack 分离数据的正确方法 Web 性能优化:图片优化让网站大小减少 62% Web 性能优化:缓存 Re ...

  4. Web 性能优化: 图片优化让网站大小减少 62%

    摘要: 压缩各种格式的图片. 原文:Web 性能优化: 图片优化让网站大小减少 62% 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 这是 Web 性能优化的第二篇,上一篇在下面看点 ...

  5. Web性能优化 高并发网站解决 单例 已看1

    Web性能优化分为服务器端和浏览器端两个方面. 一.浏览器端,关于浏览器端优化,分很多个方面1.压缩源码和图片JavaScript文件源代码可以采用混淆压缩的方式,CSS文件源代码进行普通压缩,JPG ...

  6. 对于Web性能优化, 了解和经验

    我们在发布项目之前压缩CSS和JavaScript源代码,这样文件体积就变小了,用户加载必要资源所花的时间也就更短了. 压缩源码和图片 JavaScript文件源代码可以采用混淆压缩的方式,CSS文件 ...

  7. Web性能优化-合并js与css,减少请求

    Web性能优化已经是老生常谈的话题了, 不过笔者也一直没放在心上,主要的原因还是项目的用户量以及页面中的js,css文件就那几个,感觉没什么优化的.人总要进步的嘛,最近在被angularjs吸引着,也 ...

  8. web性能优化——浏览器相关

    简介 优化是一个持续的过程.所以尽可能的不要有人为的参与.所以能自动化的或者能从架构.框架级别解决的就最更高级别解决. 这样即能实现面对开发人员是透明的.不响应,又能确保所有资源都是被优化过的. 场景 ...

  9. Web性能优化系列

    web性能优化之重要,这里并不打算赘述.本系列课程将带领大家认识.熟悉.深刻体会并且懂得如果去为不同的站点做性能优化 同时,本系列将还会穿插浏览器兼容性相关问题的解决方案,因为在我看来,兼容性同样属于 ...

随机推荐

  1. Vertica的这些事(十三)——Vertica备份元数据信息

    ---备份资源池 SELECT 'CREATE RESOURCE POOL ' || name || CASE WHEN memorysize IS NULL THEN ' ' ELSE ' MEMO ...

  2. WEB缓存系统之varnish缓存项修剪

    前文我们聊了下varnish的状态引擎和不同类型的变量对应该使用在那个状态引擎中,以及每个状态引擎的对应处理事务:回顾请参考https://www.cnblogs.com/qiuhom-1874/p/ ...

  3. java中eclipse的安装和JDK的环境变量的配置以及记事本的使用

    2020-04-09 23:26:15 学习java的第一步当然就是环境配置了,java中的配置作为小白刚刚开始肯定会有点一点晕头转向的,开没等开始入门呢!就要准备放弃了.哈哈哈哈,没关系的,都是这么 ...

  4. 29.1 collection层次结构 中的根接口

    /* * Collection * boolean add(E e) * void clear() * boolean contains(Object o) * boolean isEmpty() * ...

  5. String 对象-->indexOf() 方法

    1.定义和用法 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置,即下标. 如果没有找到匹配的字符串则返回 -1. 语法: string.indexOf(searchvalue ...

  6. Google 浏览器 离线包下载方式

    最近因工作需要,需要安装google浏览器,并且安装在系统固定目录,用360软件管理下载后发现默认安装在C:\Users\administrator\AppData\Local\Google\Chro ...

  7. 【Selenium06篇】python+selenium实现Web自动化:日志处理

    一.前言 最近问我自动化的人确实有点多,个人突发奇想:想从0开始讲解python+selenium实现Web自动化测试,请关注博客持续更新! 这是python+selenium实现Web自动化第六篇博 ...

  8. 从谷歌面试翻车到offer收割的心路历程

    首先声明,这只是我的播客随感,其中无法避免有一些个人色彩的见解,请不要在意,我尊敬任何的互联网公司,尊敬研究生期间的老师同学,我只希望给在求学路上的CS同学一些启发. 先介绍一下背景,我是ACM铜牌退 ...

  9. Java入门系列之线程池ThreadPoolExecutor原理分析思考(十五)

    前言 关于线程池原理分析请参看<http://objcoding.com/2019/04/25/threadpool-running/>,建议对原理不太了解的童鞋先看下此文然后再来看本文, ...

  10. 011-指针(上)-C语言笔记

    011-指针(上)-C语言笔记 学习目标 1.[掌握]字符串常用函数 2.[掌握]指针变量的声明 3.[掌握]指针变量的初始化 4.[掌握]函数与指针 5.[掌握]指针的数据类型 6.[掌握]多级指针 ...