基本概念 VXLAN(Virtual Extensible LAN, 虚拟局域网扩展)是一种网络虚拟化技术,它试图改善大云计算部署相关的可扩展性问题。它采用类似 VLAN 的封装技术来封装基于 MAC 含括第4层的 UDP 数据包的 OSI 第2层 以太网帧,使用 4789 作为默认分配的 IANA 目的地 UDP 端口号。
VTEP是参与VXLAN网络中的主机、虚拟交换机或物理交换机设备,用于在VXLAN隧道和基础网络之间进行数据包的封装和解封装。 具体而言,VTEP设备负责将本地主机或虚拟机的数据包封装为VXLAN数据包,以便在底层IP网络中进行传输。它添加了VXLAN头部,其中包括VXLAN标识符(VNI)和源/目的VTEP IP地址。VTEP还负责在接收到VXLAN数据包时解封装数据包,并将其传递给目标主机或虚拟机。
VTEP (VXLAN Tunnel End Point(虚拟隧道端点)):vxlan 网络的边缘设备,用来进行 vxlan 报文的处理(封包和解包)。vtep 可以是网络设备(比如交换机),也可以是一台机器(比如虚拟化集群中的宿主机) VNI(VXLAN Network Identifier):VNI 是每个 vxlan 的标识,是个 24 位整数,一共有 2^24 = 16,777,216(一千多万),一般每个 VNI 对应一个租户,也就是说使用 vxlan 搭建的公有云可以理论上可以支撑千万级别的租户
在VXLAN(Virtual Extensible LAN)中,VNI(VXLAN Network Identifier)用于标识不同的虚拟网络。 VNI是一个32位的标识符,它在VXLAN隧道中的头部中承载,以便在底层IP网络中传递。VNI允许不同的虚拟网络共享同样的物理网络基础设施,每个虚拟网络都可以具有不同的VNI
具体而言,VNI的作用如下:
虚拟网络隔离:VNI用于将不同的虚拟网络隔离开来。当VXLAN网络中的主机或虚拟机发送数据包时,VNI用于将数据包与特定的虚拟网络关联起来。这样,VXLAN网络可以在相同的物理基础设施上同时支持多个虚拟网络,而不会相互干扰。 数据包识别:当接收到VXLAN数据包时,目的VTEP(VXLAN Tunnel Endpoint)设备会根据VNI解析数据包,并根据VNI将数据包交付到正确的虚拟网络。VNI充当了在底层IP网络上传递数据包,并识别数据包的虚拟网络归属的关键标识符。 FDB(Forwarding Database) 二层网桥的FDB表项格式可表达为:
<MAC> <VLAN> <DEV PORT> VXLAN设备的表项与之类似,可以表达为:
<MAC> <VNI> <REMOTE IP> VXLAN设备根据MAC地址来查找相应的VTEP IP地址,继而将二层数据帧封装发送至相应VTEP。 可以使用如下命令查看fdb表项:...
一个UDP客户可以创建一个套接口并发送一个数据报給一个服务器,然后立即用同一个套接口发送另一个数据报給另一个服务器。同样,一个UDP服务器可以用同一个UDP套接口从5个不同的客户一连串接收5个数据报。
UDP可以是全双工的
TCP连接断开时,主动要求断开的一方会存在TIME_WAIT状态,此状态需要持续60s时间(Linux),在此状态期间,连接未完全断开,依然占用一个socket连接。
存在TIME_WAIT状态的理由:
实现终止TCP全双工连接的可靠性 如果最后一个ACK丢失,服务器将重发最终的FIN,因此客户必须维护状态信息以允许它重发最终的ACK。
允许老的重复分节在网络中消逝。 如果某个连接被关闭后,在以后的某个时刻又重新建立起相同的IP地址可端口之间的TCP连接。后一个连接称为前一个连接的化身(incarnation),因为它们的IP地址和端口号都相同,TCP必须防止来自某个连接的老重复分组在连接终止后再现,从而被误解成属于同一连接的化身。 也就是说,某一个Socket对失效后,在网络中还有针对这个Socket对的分组的情况下又建立了一个一样的Socket对,为了防止网络中针对上一个socket对的分组被误认为是当前连接的分组,必须存在一个时间间隔,使得网络中针对上一个socket对的分组失效。
TCP连接耗尽: 对于客户端来说,其端口耗尽后,就不能再建立连接。 对于服务端来说,其使用socket对server_ip.server_port:client_ip.client_port来标识一个socket连接,对于某个特定服务来说,其server_ip和server_port是不变的,每次有一个连接进来,服务端都会fork出一个自身的子进程来对连接进行服务。这样,可服务的连接数就由client_ip和client_port两个共同决定,client_ip最多有$2^32$个,client_port最多有$2^16$个,因此理论上最多可服务连接数为$2^48$个。但每一个socket连接都需要消耗一个文件描述符,因此最大连接数还收到文件描述符数目的限制。除此之外,socket连接还会占用内存等资源,这些资源也限制了最大连接数。
Unix系统有保留端口的概念,它是小于1024的任何端口。这些端口只能分配給超级用户进程的套接口,所有众所周知的端口(0-1023)都为保留端口,因此分配这些端口的服务器启动时必须具有超级用户的特权。
TCP套接口编程 socket函数 为了执行网络I/O,一个进程必须做的第一件事就是调用socket函数,指定期望的通信协议类型。
#include <sys/socket.h> int socket(int family, int type, int protocol); 其中family指明协议族,type是某个常值,参数protocol一般设为0,除非用在原始套接口上。
对于family,其是以下常值之一:
族 解释 AF_INET IPv4协议 AF_INET6 IPv6协议 AF_LOCAL Unix域协议 AF_ROUTE 路由套接口 AF_KEY 密钥套接口 对于type,其是以下常值之一:...
这是一篇理论性较强的文章
1. HTTP/1的不足与面临的问题 此部分内容来自:https://segmentfault.com/a/1190000013519925
1.1 HTTP/1概述 1.2 队头阻塞 浏览器很少只从一个域名获取一份资源。大多数时候,它希望能同时获取许多资源。设想这样一个网站,它把所有图片放在单个特定域名下。HTTP/1 并未提供机制来同时请求这些资源。如果仅仅使用一个连接,它需要发起请求、等待响应,之后才能发起下一个请求。这显然会在加载页面时造成较大的延迟,降低了用户体验。
h1 有个特性叫 管道化(pipelining),允许一次发送一组连续的请求,而不用等待应答返回。这样可以避免连接延迟。但是该特性只能按照发送顺序依次接收响应。而且,管道化备受互操作性和部署的各种问题的困扰,基本没有实用价值。
在请求应答过程中,如果出现任何状况,剩下所有的工作都会被阻塞在那次请求应答之后。这就是队头阻塞(Head-of-line blocking或缩写为HOL blocking),它会阻碍网络传输和 Web 页面渲染,直至失去响应。
为了防止这种问题,现代浏览器会针对单个域名开启 6 个连接,通过各个连接分别发送请求。它实现了某种程度上的并行,但是每个连接仍会受到 队头阻塞 的影响。另外,这也没有高效利用有限的设备资源。
1.3 TCP复用 传输控制协议(TCP) 的设计思路是:对假设情况很保守,并能够公平对待同一网络的不同流量的应用。它的避免拥塞机制被设计成即使在最差的网络状况下仍能起作用,并且如果有需求冲突也保证相对公平。这是它取得成功的原因之一。
它的成功并不是因为传输数据最快,而是因为它是最可靠的协议之一,涉及的核心概念就是 拥塞窗口(congestion window) 。拥塞窗口是指,在接收方确认数据包之前,发送方可以发出的 TCP 包的数量。 例如,如果拥塞窗口指定为 1,那么发送方发出 1 个数据包之后,只有接收方确认了那个包,才能发送下一个。
一般来讲,每次发送一个数据包并不是非常低效。TCP 有个概念叫 慢启动(Slow Start), 它用来探索当前连接对应拥塞窗口的合适大小。慢启动的设计目标是为了让新连接搞清楚当前网络状况,避免给已经拥堵的网络继续添乱。它允许发送者在收到每个确认回复后额外发送 1 个未确认包。这意味着新连接在收到 1 个确认回复之后,可以发送 2 个数据包; 在收到 2 个确认回复之后,可以发 4 个;以此类推。这种几何级数增长很快就会到达协议规定的发包数上限,这时候连接将进入拥塞避免阶段 这种机制需要几次往返数据请求才能得知最佳拥塞窗口大小。但在解决性能问题时,就这 区区几次数据往返也是非常宝贵的时间(成本)。现代操作系统一般会取 4~10 个数据包作为初始拥塞窗口大小。如果你把一个数据包设置为最大值下限 1460 字节(也就是 最大有效负载),那么只能先发送 5840 字节(假定拥塞窗口为 4),然后就需要等待接收确认回复。
如今的 Web 页面平均大小约 2MB,包括 HTML 和所有依赖的资源。在理想情况下, 这需要大约 9 次往返请求来传输完整个页面。除此之外,浏览器一般会针对同一个域名开启 6 个并发连接,这意味着拥塞窗口波动也会并行发生 6 次。TCP 协议保证那些连接都能正常工作, 但是不能保证它们的性能是最优的。...
四种常见的POST类型 1. application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了。浏览器的原生 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):
POST http://www.example.com HTTP/1.1 Content-Type: application/x-www-form-urlencoded;charset=utf-8 title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3 首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。例如 PHP 中,$_POST[‘title’] 可以获取到 title 的值,$_POST[‘sub’] 可以得到 sub 数组。
很多时候,我们用 Ajax 提交数据时,也是使用这种方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默认值都是「application/x-www-form-urlencoded;charset=utf-8」。
2. multipart/form-data 这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:
POST http://www.example.com HTTP/1.1 Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form-data; name="text" title ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form-data; name="file"; filename="chrome.png" Content-Type: image/png PNG ....