在TCP/IP协议族中,链路层的主要有三个目的:
(1)为IP模块发送和接受数据报
(2)为ARP模块发送ARP请求和接受ARP应答
(3)为RARP发送RARP请求和接受RARP应答
TCP/IP支持多种不同的链路层协议,这取决于网络所使用的硬件,如以太网,令牌环网,FDDI,及RS-232串行线等。
两个串行接口链路层协议:
SLIP:(Serial Line IP)它是一种在串行线路上对IP数据报进行封装的简单形式,SLIP适合用于家庭中每台计算机及都有的RS-232串行端口和告诉调制解调器接入Internet。
下面的规则描述了SLIP协议定义的帧格式:
(1)(来自上一层协议的)IP数据报以一个称作END(0xc0)的特殊字符结束。同时,为了防止数据报到来之前的线路噪声被当成数据报的内容,大多数实现在数据报的开始处也传入一个END字符(如果有线路的噪声,那么END字符将结束这份错误的报文。这样当前的报文得以正确地传输,而前一个错误的报文交给上层协议后,会因为其内容无效而被丢弃)
(2)如果IP报文中某个字符为END,那么就要连续传输两个字节0xdb和0xdc来取代它,0xdb这个特殊的字符被称作SLIP的ESC字符,但是它的值与ASCii码的ESC字符(0x1b)不同。
(3)如果IP报文中某个字符为SLIP的ESC字符,那么就要连续传输两个字节0xdb和0xdd来取代它。
SLIP是一种简单的帧封装方法,还有一些值得一提的缺陷:
(1)每一端必须知道对方的IP地址,没有办法把本端的IP地址通知给另一端。
(2)数据帧中没有类型字段(类似于以太网中的类型字段)。如果一条串行线路用于SLIP,那么它就不能同时使用其它的协议。
(3)SLIP并没有加上数据帧的内容检验,如果SLIP传输的内容因为线路的噪声而发生了错误,这只能由上层的协议来发现(或者用新型的调制解调器可以检测并且纠正错误报文)
PPP:(Point-to-Point Protocol)点对点协议修改了SLIP协议中的所有缺陷,PPP包括以下三个部分:
(1)在串行链路上封装IP数据报的方法。PPP既支持数据为8和无奇偶检验的异步模式,还支持面向比特的同步连接。
(2)建立,配置及测试数据链路的链路控制协议(LCP:Link Control Protocol)。它允许通信双方进行协商,以确定不同的选项。
(3)针对不同网络层协议的网络控制协议(NCP:Net Work Protocol)体系。
PPP协议的每一帧都以标志字符0x7e开始和结束,紧接着是一个地址字节,值始终是0xff,然后是一个值为0x03的控制字节,然后是协议字段,类似于以太网中的类型字段的功能。当它的值为0x0021时,表示信息字段是一个IP数据报,当它的值为0xc021时,表示信息字段时链路控制数据(LCP),当值为0x8021时表示信息字段是网络控制数据(NCP)。
由于结束和开始的标志字符是0x7e,因此当该字符出现的时候,PPP需要对它进行转义,在同步链路中,该过程是通过一种称作比特填充的硬件技术来完成的。在异步链路中,特殊字符0x7d用作转义字符,当它出现在PPP数据帧中的时候,那么紧接的字符的第六个比特要取其补码,具体过程如下:
(1)当遇到字符0x7e时,需连续传送两个字符0x7d和0x5e,以实现标志字符的转义。
(2)当遇到转义的字符0x7d时,需连续传送两个字符:0x7d和0x5d,以实现转义字符的转义。
(3)默认的情况下,如果字符的值小于0x20,一般都要进行转义。例如,遇到0x01时需连续传送0x7d和0x21两个字符。
与SLIP相似的是,由于PPP通常是用于低速的串行链路,因此减少每一帧的字节数可以降低应用程序的交互时延,利用链路控制协议,大多数的产品通过协商可以省略标志符和地址字段,并且把协议字段由2个字段减少到1个字节。如果我们把PPP的帧格式与前面的SLIP的帧格式进行比较就会发现,PPP只增加了额外的3个字节。
总的来说,PPP协议由以下这些优点:
(1)PPP支持在单根串行线路上运行多种协议,不只是IP协议
(2)每一帧都有循环冗余检验
(3)通信双方可以进行IP地址的动态协商(使用IP网络控制协议)
(4)连路控制协议可以对多个数据链路选项进行设置。
环回接口(loopback):
大多数的产品都支持环回接口,以允许运行同一台主机上的客户程序和服务器程序通过TCP/IP协议进行通信。A类网络号127就是为环回接口预留的,根据惯例环回地址为localhost。
一旦传输层检测到目的端地址是环回地址时,应该可以省略部分传输层和所有网络层的逻辑操作。但是大多数的产品还是照样完成传输层和网络层的所有过程,只是当IP数据报离开网络层时把它返回给自己。
最大传输单元(MTU):
不同的网络对数据的帧的长度有一个不同的限制,如果IP层有一个数据要传,而且数据的长度比链路层的MTU还大,那么IP层就要进行分片,把数据报分成若干片,这样每一片都小与MTU。点到点的链路层(如SLIP和PPP)的MTU并非指的是网络媒体的物理特性。相反,它是一个逻辑限制,目的是为交互使用提供足够快的响应时间。
路径MTU:
当在同一个网络上的两台主机互相进行通信的时候,该网络的MTU是非常重要的,但是如果两台主机通信要经过多个不同的网络的时候,重要的不是两台主机所在的网络的MTU值,而是两台通信主机路径的最小MTU,它被称作路径MTU。
## 接下来几个简单的命令来看下我们的主机的信息吧:##
netstat -r 路由表,我的ip是192.168.1.108可以知道我们在是在C类地址下,网络号为43009,主机号为108,无子网,维护的路由表的默认路由是192.168.1.0即“1号主机”
netstat -i 网络接口 MTU如图所示 其中65536并不代表网络的MTU,IP数据报的总长度最大为0xffff及65536,这也是dos攻击的理论依据。
本文链接:<再看TCP/IP第一卷>关于链路层的知识细节及相关协议,转载请注明。
我们时时在踩坑,有时也忍不住埋怨前人给我们留下了无数的坑,可回头想想,自己是不是也在挖坑等别人踩...
上次听 赵海平 的讲座,他提到 Facebook 没有测试人员,以前和现在都没有,以后也不打算有。还提到上线之后就开发者坐在系统前等着,只要有bug,系统能够在五分钟之内检测到,并提供快捷方式修复。我惊叹的是他们能够在五分钟之内监控到所有的问题,实时回馈并及时修复。
当然在探讨质量保障这个话题前,我们需要明确几个关键点:编码前、提交代码、测试、上线、回滚、上线后。针对这几个点,下面我谈一谈我的看法。
一、编码前
来阿里之前在百度实习过三个月,实习期间印象最深的交流是参与编码规范讨论,当时我还呼呼的整理了两份文档:前端编码规范之JavaScript,前端编码规范之CSS。后来也看到团队在各种工具上添加控制和提示,如 Sublime Text 添加 jslint 配置,项目目录下添加 .jslint 配置,打包工具提示代码的不规范,强制修复等等。
上面提到的代码规范主要是代码展现层面的规范,他可以让团队写出来的代码就跟一个模子刻出来似的,结构、命名、函数体大小等等很接近,看着很舒服。举几个例子说明他的重要性。
1. 统一使用 UTF8 编码
我平时开发都是使用的 UTF8 编码。有次从仓库拉下来发现很多文件都是 GBK 编码,修改时一个文件忘记转换编码,提交发现 锟斤拷 出来了。
2. TAB 缩进
我比较喜欢使用四个空格作为 TAB 缩进。一次多人开发的时,发现同事的代码是两个空格的缩进,结果,我改成了四个空格提交之后,又被改回来两个空格,然后我接着改回去…
3. 加不加分号
以前写过一篇文章,谈了下自己对分号的看法:Javascript分号,加还是不加?,我的回答是加但非必须。
代码的规范,对程序本身的意义并不是很大,他不会作用在程序的逻辑上,作用点在于团队合作。一个项目可能是多人开发,也可能是今天我开发,明天托付给你。如果两个人在编码习惯上的差异很大,就会偏头痛…有一点需要特别提出来,就是写注释!某次排查一个线上问题,找到了问题所在的文件,但是文件中的逻辑实在是太过复杂,四五百行代码仅三行注释,眼睛都看花了。其实只要在大段的代码前加几句注释,说明本段代码的大意,在排查定位问题的时候就可以忽略一部分代码块,可以为修复线上bug争取不少时间。
二、提交代码
这部分特指工具。可以说过了工具这一道关卡,代码基本就获得自由,bug 也就开始横飞了。目前工具可以为我们做的事情:
1. 检测
- 现在并没有做 jslint 之类的配置,所以代码的展示是没怎么规范的。
- 编码应该统一为 UTF-8 格式,如果不是这种格式,工具应该有所提示。
- 代码块过长提示,一个函数不应该写到几百上千行,拆分代码刚开始是辛苦,一旦后续复用的时候,就会很爽很爽了(当然,刚开始编码的时候就应该考虑一个函数的颗粒度控制)。
更重要的是对语法的检测,我们可能把 document
拼写成了 doucment
,甚至使用 for in
来遍历一个数组,这种问题时而出现,工具是否考虑帮助我们处理掉一些简单的愚蠢的错误。
2. 压缩
压缩代码的时候,我踩过坑:gulp打包压缩css遇到的坑,我相信很多人都认识 grunt 和 gulp,但是一定鲜有人自己配置过这些东西,并投入到项目中。
代码的压缩,一方面可以减少线上流量,一方面也是出于安全的考虑。压缩后的代码线上报错很难定位到准确的位置,有些问题只能在用户的电脑上复现,“代理到本地这个法子”远程操作的时候是不靠谱的。压缩不仅仅应该把代码缩短,还要考虑线上排查问题的难度。
在压缩的时候可以考虑添加空行,将网页错误定位范围缩减到单个文件。也可以使用 sourceMap 之类的辅助方式。在这篇文章中有过一些讨论。
3. 合并
很多事情,别人不考虑,工具就得考虑。
这里有一个思考,HTTP2.0 支持多路复用,一个连接可以进行多次 HTTP 的传输,那以后的 sprite 图、文件的合并等是不是也应该重新考虑了。文件的全部合并真的是最省资源的方式么?是否可以考虑更多的合并方案?
三、测试
赵海平 说,技术实践中的三件套:功能 + 测试 + 监控。很多大公司的工程师,深谙功能开发之道,测试方面也能达到 60 分的水平,但是程序的监控上,做的很差,包括 Facebook 的程序员。三件套,对一个优秀的工程师来说,缺一不可。
这里要说的是程序开发三板斧的第二板,测试。
我们很自然地联想到了QA,阿里有一大波的测试人员。写完代码提测,好像剩下的就只是测试同学找BUG,我们等着修BUG。前端的测试跟后端还不太一样,逻辑可以测,但是 UI 效果、交互效果不好测,只能靠几双眼睛盯着看,几个鼠标不停地点点点。。。
虽说逻辑可以通过写测试用例进行测试,会去写测试用例的人却不多。我记得当时学习 AOP 编程的时候,给 ajax 添加了一些 mock 功能,可以在页面上模拟请求测试效果(如jquery-mockjax)。
编写测试用例确实可以解决很多的问题,但是如何培养编写测试用例的习惯,如何更加便利的测试我们的测试用例,这又是一个值得思考的话题。
自动化工具一大缺点是很难捕获到特定环境下的错误。据统计,不管你的代码写得多健壮,在一千个用户下,总有那么一个用户,因为浏览器安装了插件、网络问题等导致代码报错,再比如我们在做灰度测试的时候,让用户名首字母为 a-m 的用户命中灰度时出现的错误等等,这些错误自动化测试工具是无法发现的。
所以我们要把 错误日志统计 灵活地使用起来,他能够使你深入用户,拿到最原始的错误信息。
四、上线
现在涉及到前端上线的,有多个地方(公司有很多发布系统):
- TMS发布
- aone2发布
- gitlab发布
- awp发布
- etc.
gitlab发布通过域名严格区分测试、预发和线上环境,操作界限明确,出错的概率还是很低的(这要求开发者对 git 命令的操作十分熟练),如果几次 reset revert stash 之后便开始犯蒙,那出问题的概率就增大了。每次打下 tag 之前,我都会很仔细地 diff 下代码,看看本次发布和上次发布之间做了哪些修改,确认这些修改点再 push tag。
aone2的发布,并不是每个人都用过,它的靠谱在于有三种发布方式:
- 全网发布,半小时完成
- 小淘宝环境灰度发布,两小时完成
- 分三次发布,小流量上线,一天完成
同时也提供了十分方便的回滚机制,只要拥有应用的权限,可以随时回滚代码,效率极高。
TMS 的发布,我觉得是问题最多的。首先,前端和运营都会拥有发布前端,运营喜欢“瞎搞”,部分页面(如JSON输出)并没有提供页面预览,运营填完之后也不会跑到页面查看效果,于是就出问题了。。TMS发布每次修改只发布一个文件,CDN 发布一个文件的速度是很快的,当你点击发布的那个瞬间,整个同步就基本完成了。可是,当某个节点同步出错,TMS 并没有给出提示,这是第二个隐患。第三个点,TMS坑爹的没有灰度,对一些重要的发布,没有灰度就需要十分十分的谨慎,虽说出错可以及时回滚,但万一没有看到隐性的错误,那就悲惨了。
五、回滚
没人可以保证自己写的东西绝对不出问题,因为有太多的环境因素是我们想也想不到的,比如今天淘宝首页阿里妈妈的广告全挂了(小淘宝环境下),试问,前端怎么会想到这是Nginx 的灰度系统出问题了,在灰度发布的时候文件没有同步成功,导致整个灰度环境出错。
所以,一定要给你的程序想一套快速回滚方案。尤其是在做 ABTest 的时候,新版的效果不好需要回滚到之前的状态,这种事情经常有。
回滚需要注意两点:
- 要快。
- 上一个状态要保证无错误。
只要我们能够保证发到线上的每一个版本都是稳定版,那回滚就是 0 风险的事情。
六、监控
程序开发三板斧的第三板,监控。前端对测试就不太重视,更不用提监控了。没有监控就只能提心吊胆的过日子。
其实我们使用自动化工具测试、每天用肉眼顶着自己的页面看,这些都属于监控,但是深入到用户的监控,我们做的太少!
七、小结
看到老大在群里发了几条研发相关的红线:
1、禁止代码为经测试发布;
2、禁止代码发布后不进行线上验证;
3、禁止核心应用发布没有对应的回滚方案。
毫无疑问,这些都是必须严格遵守的。规范会先把坏习惯压住,进而被理解,最后被消化吸收。
前端质量保障之路,任重而道远!
本文链接:对前端质量保障的思考,转载请注明。
没有评论:
发表评论