引言
随着移动互联网的疯长式发展,互联网公司开始因为自身产品的用户指数级增长的同时,内心是复杂的.用户量的增加往往会给自己的产品提升知名度和经济效益.另一方面,超大用户访问量也给系统的维护和开始带来了挑战.目前国内面临着巨大高并发的企业典型的有两家,12306和阿里的各种购物狂欢节.2011年的时候12306还在春运时遭到广大刷票党的吐槽,到15年的今天,12306一点一点的在进步着.而淘宝每年的双11一天的进账就是千亿级,这么大的用户访问量是如何做到服务器不当机的呢.这里涉及到一个非常典型的问题,一台再好的服务器,带宽再强大也无法保证上亿的用户同时访问,可以说服务器是一个高并发时的瓶颈,如何解决这个瓶颈?阿里和12306是怎么克服这个问题的呢?作为开始工程师,我对此十分感兴趣,做了一些研究,并用Cisco Packet做了简单的模拟.
在进一步解决服务器瓶颈问题之前,需要有具备一些基础的计算机网络知识,理解这些基本概念.这是解决高并发问题的一个基本前提,离开这个根基,去谈集群就是耍流氓.
知识准备
- 计算机两种分层结构OSI和ISO
- IP地址/子网掩码
- 网关/默认网关
- TCP连接的三次握手与四次分手
- 数据包/mac地址/端口号
- 路由器
- 交换机
- 网卡
互联网中计算机间的通信
名词解释
host1 --- 主机1(可以理解成互联网中做任意一台电脑)
host2 --- 主机2
host3 --- 主机3
switcher1 --- 交换机(物理设备,二层,只看目标与源的mac地址与端口)
router1 --- 路由器(三层,看目标与源的IP地址)
网卡 --- 物理设备,维护着一个IP地址,该地址与一个mac地址是绑定关系.
任意两台主机想要通信,需要先互发数据包,进行三次握手,成功建立连接后,再由请求主机向目标主机发送数据包.这是一个互联网请求的大前提.
假如有一台主机host1, 它本地维护着一张路由表,数据结构如下
host1与host2通信
Step1: 确认要发送的数据包三大内容,mac地址,IP地址,端口.
Step2: 发送数据包建立进行三次握手,这是关于最小网络连接的导图.一个简单的http请求,必须完成的最小粒度应该是三次握手---数据---四次分手.只有双方主机都确认分手以后,客户端才会释放本次连接使用的端口号,以节省资源.
Step3: 发送真实数据,下图显示了其发送数据的过程.图中host1与host2处于同一个网段中,中间只连了一台交换机,于是直接将数据包扔给交换机,交换机通过物理网卡收发数据,这个速度无疑是非常快的.具体过程下图有详细说明.
host1与Host3通信
step1与step2同上.
step3:host1与host3不在同一个网段,因此在确认数据包时,需要取网关的mac地址;此后host1将请求数据扔给肉头,也就是router1.这后router1要做的事情是重复操作step1,step2,step3,直到找到目标主机.如果目标主机根本不存在,那么连接会超时.过程分析图如下.
服务器的瓶颈
设计一个极简单的web网站, 很容易搭建一台服务器,上面放着用户可能需要的所有资源文件,图片,视频和日记等等.这个模型实现了非常简单的网络结构,效果显著.但也存在问题,当你在为网站做了大量推广时后,用户量猛增,同一时间的访问量跟着涨起来,保持一天增1000个(假设这个网站做的不错,用户不会流失),那么三个月后,这台服务器变得力不从心.用户关于访问页面总是404的一系列负面反馈也日益频繁.这就是高并发形成的服务器瓶颈.
这个现象揭示了两个问题
- 用户访问量大的时候,服务器甚至都无法保证与每个请求建立连接.
- 同样是高并发,一台服务器毕竟只能提供有限的IO,终究导致往外写数据十分缓慢.
解决办法1
既然一台服务器已经无法满足海量用户的访问,那么就多买几台服务器好了.话说顾客是上帝,互联网时代,用户群就是王道,一切为用户.
不幸的是问题依然存在.比如:
- 你有多台服务器,用户请求的地址始终都是同一个域名这个请求最终该由哪台服务器响应呢?
- 即使现在的域名解析支持一个域名绑定多个IP地址.那这个IP地址就必须是公网IP,而公网IP资源有限,一台服务器一个公网IP,显然不是良策.
解决办法2
既然不能用公网IP,那么就在这些服务器与客户端之间再搭一台中间服务器,这台服务器负责持有公网IP,然后将用户请求的数据转发给其后的真实负服务器,即可.
这种解决方案,会遇到一个网络技术问题.
用户在发送请求时,首先会给中间服务器发送数据包,进行三次握手,这个过程建立连接的是用户与中间服务器.这就会导致负载服务器给用户发送响应数据时,被用户认为是不合法的连接,将被用户丢弃.
解决办法3
其实这个问题在实际生活中,早在1998年国内就有人提出了解决方案,那就是章文嵩士提出的LVS虚拟服务器.
它是这么解决的.
中间服务器D(10.211.55.2)收到用户C1(192.168.1.100)的请求数据包后,只是拆包,将目标的mac地址修改到自己网段中一台真实服务器RS1,然后将数据包打好后发给RS1.
这台RS1收到数据后,判断请求信息,其中源信息和目标信息本地都拥有,于是给予自己直接给用户发送确认连接.而收到请求的用户C1,再次向中间服务器D发送确认连接的数据包.最终建立TCP连接的是C1与RS1.这样就使得RS的收发数据变得合理合法与高效.
这就是著名的LVS(Linux Virtual Server).
结束语
有幸的是LVS被Linux内核收录,只要你的主机上运行着Linux内核,就自带有LVS软件服务,这很容易让有需求了解LVS的人自己动手搭一个集群,模拟这种负载均衡技术.
这将在明天的博文中更新,会有大概三种LVS实现方式.