前后端技术科普

数据处理

数据恢复

一种是存储介质损坏导致的数据丢失,另一种就是数据从存储介质上删除。前者的话,比如硬盘碎了,数据是无法恢复的;后者的话,大部分文件系统是这样设计的,一部分是索引区,另一部分是数据区。当我们新加一个文件时,先往索引区里添加一条文件索引信息,然后往数据区里写入文件的完整内容。当删除一个文件时,一般只会将它的信息从索引区里删除,而数据区里的内容却不做删除,只是标记为无人使用,如果有新的文件写入系统,那么这些被标记无人使用的区域很有可能被新文件覆盖掉。
所以,当我们手贱误删了一些文件后,想要恢复它们是有可能的,就是需要保证没有其它的数据进来,将误删的文件数据覆盖掉。

数据埋点

  1. 所谓「埋点」,就是在正常的功能逻辑中添加统计逻辑。
  2. 并不是每统计到一次事件或者状态就会发起数据上报,客户端统计到的数据会先暂时存储在内存或者磁盘上,当用户启动、退出应用程序的时候,或者在其他更合适的时机,将当前周期统计到的事件批量上报到服务器,这样做的目的主要是考虑到与服务器多次建立连接的性能损耗和流量问题。
  3. 数据上报到服务器后,服务器会将客户端上报的原始数据存储到服务器的磁盘中。
  4. 最终计算入库

数据库索引

数据库索引,对数据库里的某个属性的所有值进行排序,从而加快查询速度,是一种典型的空间换时间的思想。
聚簇索引
按照数据的物理存储顺序建立索引。建立聚簇索引会改变数据库表的存储结构和数据排序,所以一张表只能建立一个聚簇索引。
非聚簇索引
非聚簇索引并没有改变表的存储结构和数据排序,而是另外开辟了一块存储区域保存索引。索引中的关键字(name)是有序排列的,进而可以提供高效的查询。同时,索引中的每一行都有一个指向数据表中具体数据的指针,通过索引查找的结果可以快速的定位到具体的数据。

一张数据库表可以建立多个非聚簇索引,这样可以针对不同的查询需求对不同的列分别建立索引,但每个索引都会额外的消耗大量的存储空间。

硬件知识

CPU GPU

  1. CPU
    CPU 架构有 arm,x86,x64,手机中使用 普遍的就是 arm 架构的 CPU 了,而 PC 选用的是x86/x64。
    CISC:复杂指令集计算机,常见的x86架构,Intel的奔腾酷睿属于x86CPU,多用于计算机。
    RISC:精简指令集计算机,IBM的PowerPC,MIPS 的 MIPS 架构和 ARM 公司的 ARM 架构,多用于移动设备。
  2. GPU
    也叫显卡, GPU 的主要功能是快速高效地处理图形,而图形处理的一个特点就是数据量很大,但是对每块数据处理的流程是一样的。所以 GPU 一开始就被设计成有多核的,每个小的处理核心具有独立的运算能力和内存空间。
    相对于 CPU 来说,GPU 核心单元的逻辑运算能力远远低于 CPU 的逻辑运算能力,但是由于核心数量众多,可以使用人海战术,在处理一些简单指令的密集型数据时,GPU 的性能远远大于传统的 CPU。
    目前用 GPU 来做高性能计算的主要是医疗成像、挖掘比特币。

刷新率帧率

  1. 刷新率
  • 刷新率标识了一个输出设备每秒钟会更新多少次,它的单位是 Hz,例如我们常用的液晶显示器的刷新率 60Hz,显示器其实是每一秒中更新了六十幅图片。
  • 刷新率是由硬件决定的,越高的刷新率就会有越连贯的图像,并且刷新率决定了流畅度的极限,再好的软件遇到一个低刷新率的输出设备,图像也不会好。
  1. 帧率
  • 帧率标识了计算机软件,比如说游戏的质量,或者说显卡更新画面的次数,比如 1 秒钟60 帧,经常表示为 60fps,也就是显卡能够输出 60 幅画面,帧率直接反映了一个游戏的流畅度。
  • 帧率是由软件决定的,一个编好的软件会输出更高的帧率,也就有了更好的流畅度,但是代码并不能解决所有问题,它是有天花板的,有些高质量游戏需要同时配合显卡的使用才能达到流畅的状态,所以显卡也是不可或缺的一环。

码率带宽分辨率

  1. 码率也叫比特率,表示经过压缩编码后的视音频数据每秒需要用多少个比特来表示,即把每秒显示的图像进行压缩后的数据量,一般采用的单位是kbps即千位每秒。 码率只是一个描述音视频每秒的数据流量,如果码率很高的,则需要更高的网络带宽支持,如果不够的话,则可能造成画面延迟或丢失。
  2. 带宽反映了通道传输流量的能力,单位是bps。 简单来说,如果我想播放32kbps的歌曲,那我的带宽就应该达到32kbps;如果我的带宽是4mbps,那能支撑起的视频的码率最多就是4mbps。
  3. 帧率:影响视频流畅度。人眼识别大概是30帧。如果帧率一定,要求看视频清晰,那么就只能降低帧率了。如果要求帧率变高,清晰度不变,那么码率就需要变高。
  4. 分辨率:分辨率就是屏幕上像素点的个数,平时我们在描述分辨率时则是用横向的像素点个数*纵向的像素点个数。影响图像大小,与图像大小成正比:分辨率越高,图像越大;分辨率越低,图像越小。
    计量单位 是 PPI,每英寸像素数,我们通常将此作为衡量屏幕是否细腻的一个标准。

客户端技术

广告追踪

一般是通过 GUID 来标识用户设备,通过手机的mac 地址以及 imei 号进行一定的运算后生成可以唯一标识一个设备的码(山寨手机很多,这种方式不能保证绝对唯一了),相当于标识一个用户了。
在一个应用中使用的时候应用将用户的唯一标识写入剪切板,如果用户
又打开另外一个应用,另外一个应用从剪切版中把用户标识取出,继续记录用户浏览器行为,这样就将整个跟踪过程串联起来了。

应用续命

  1. 监听系统事件,通过系统广播来唤醒自己
  2. 启动时创建守护进程,通过守护进程唤醒
  3. 全家桶系列之不同应用间相互唤醒

热补丁

  1. 热补丁,可以做到线上推送一段修补 BUG 的代码,终端无需更新版本,直接运行。
    这要从 Android 如何运行代码讲起。我们写 Android 程序,一般用 JAVA 语言。JAVA 是一种高级语言,需要有个翻译器,把它翻译成 CPU 才懂的机器语言,这个翻译器就是虚拟机。打个比方,清朝的皇帝不懂汉语(别当真),要看懂汉臣们写的奏折,就要雇一个翻译官。翻译官的工作就是,一条条的读取奏折里的内容,翻译成满语,然后一条条呈递给皇帝。
    这个例子里,奏折是我们写的JAVA 代码,翻译官是虚拟机,皇帝就是掌管一切的 CPU。一般一段代码执行一个功能,比如从网上下载一首歌曲,就好比皇帝看到奏折之后,开始调度资源着手执行。
  2. 要实现热补丁,现在有两种主流的方法。一种是利用 ClassLoader 的方法,来自 QQ 空间团队。原理是虚拟机在翻译 JAVA 代码的时候,会把所有代码分成一个一个的 dex(代码集合),依次执行。既然是依次执行,就有个谁先谁后的关系,我们只要把修复的代码段下载下来,改成跟原来有BUG 的代码段一样的名字,插入到这个执行队列的 前面,那么运行的时候就会执行替身,真身永远都没有机会执行到。(因为虚拟机有个特性,同名的代码段不能有两个在同时运行)。
  3. 另一种方法叫 Dexposed,来自阿里。这种方法更简单粗暴,它直接接管虚拟机的执行代码流程,本来虚拟机要执行一段有 BUG 代码,我们可以让它转而掉头去执行另一段没有 BUG的代码。这下不得了了,推而广之,如果我们能诱导虚拟机执行任何我们想要的代码的话,你想想,这不是就是外挂吗?好在用这种方法你只能改你自己的 APP,要想改别人的 APP 就要 Root 权限。还有,这种方法对 5.0 以上的 Android 系统不好使,原因是谷歌从 5.0 开始把虚拟机从 Dalvik换成了 ART。
    还是看例子,和珅这次直接买通了翻译官,要求他每次看到举报和珅的「BUG 奏折」之后,直接扔掉,用另一份准备好的「补丁奏折」替换之。然而,也不是人人都是可以被收买的,比如「Dalvik 同志」就是自己人,「ART 同志」就是一个两袖清风的人。

增量更新

增量更新就是只将 App 中有发生改变的部分发送给用户,而不是每次都重新下载一个完整的安装包,这样就可以为用户节约大部分的流量了。
首先生成差异包 - >下发差异包 - > 合成新包 - > 校验完整性

增量更新和动态更新比较容易混淆,虽然两者好像都是下载一个补丁包。增量更新是将补丁包合并后生成一个完整的应用安装包,用户需要重新安装才可以使用,而动态更新则是替换应用中的某个模块,用户不需要重新安装应用,甚至都不需要重启应用,两者各有自己的应用场景。

推送

app 会每隔一段时间向服务器报告自己还活着,就像心跳一样,服务器收到后,就知道这个通道是可以继续使用的了。然而天下没有免费的午餐,发送心跳是有代价的,一般手机锁屏之后,为了省电 CPU 是出于休眠状态的,然而发送心跳就会唤醒 CPU,必然会增加电量的消耗。这还只是一个长连接通道的情况,如果手机里装了 2、30 个带有推送的 app 呢?先别急着抱怨,聪明的 android 工程师和 ios 工程师早就想到了这一点,他们分别设计了 GCM 和 apns 来解决多个 app 有多个长连接通道的问题。以 apns 为例,ios 开通了一条系统级别的长连接通道,
通道的一端是手机的所有 app,另一端是苹果的服务器。app 的服务器如果有新的消息需要推送的话,先把消息发送到苹果的服务器上,再利用苹果的服务器通过长连接通道发送到用户手机,然后通知具体app。这样就做到了即使手机安装了 100 个 app,也只需要向一条通道里发送心跳。
回到 Android,系统提供的 GCM 只能在 Android2.2 以上才能使用,3.0 以下必须要安装Googleplay 并登陆了 Google 账号才能支持。而国内发行的手机大多是阉割掉了 google 服务的。因此,对于 Android 系统来说,各家 app 只能各显神通,开发自己的专用长连接通道了。然而这时候他们遇到了 app 的天敌:管家和卫士们。前文说了,app 想要及时收到服务器推送的消息,关键在于自己与服务器的长连接通道不被关闭,也就是自己的后台服务可以一直在后台运行,而管家和卫士们的一键清理功能就是专治这种「毒瘤」的。道高一尺魔高一丈,app 在与管家和斗士们的长期斗争中,总结了一系列躲避被清理掉的方法,什么定时
自启能力、什么相互唤醒、什么前台进程等等,当然这就是另一个话题了。
总结起来,app 和后台的连接方式有两种。一种叫 pull,也叫轮询,就是定期的不断向后台请求,缺点是耗电,费流量,不环保。对于一名有追求的程序员,他应该会比较恶心这种方式的,你千万不要对他说,我不管你怎么实现,我就要这种效果这种傻逼话了,凡事应该找到最优路径。另一种叫 push,app 和后台一直维持了一条通信通道,两端不定期的就会偷摸的约会,告诉对方「I‘m Here」,也能顺带把信息互相携带了。缺点是要维持一条长连接通道,这条通道容易被其他程序杀死,要多想复活办法。
在这里插入图片描述

缓存

缓存系统经常分为两级,称为一级缓存,二级缓存。一级缓存也叫内存缓存,二级缓存也叫硬盘缓存(手机 App 中,在 Sd 卡上)。显然,一级缓存存取速度更快,程序退出数据就消失,不可一直保留,且多占了一些内存。二级缓存容量可以更大,速度要慢一些,程序下次启动时候,依然可以使用。

登录账号

账号登录几乎是每个 APP 必备的一个功能。我们在开发一个 APP 的时候,第一件事情几乎就是建立一个账号系统。我们来看下技术上是如何实现的,主要会涉及到一些安全上的问题。

  1. 注册和登录的时候,你的密码会直接发送到服务器吗?
    不会。客户端和服务器之间是一条充满妖魔鬼怪的荆棘之路,我们前面也讲过,有搞劫持的,有搞 DNS 欺骗的,还有挂着羊头卖狗肉李鬼变李逵的。所以客户端拿到你输入的密码之后,第一件事就是:变身!先来一个哈希大保健。哈希的意思是,把你的密码(比如1234567)变成另一段谁也不认识的文字(比如 2345121),并且这个过程是不可逆推的。也就是说,别人偷到了哈希之后的密码,也不会推导出你真正的密码。这样你的密码就可以上路了。
  2. 服务器验证成功之后,服务器会记住我吗?
    不会。我们之前讲过服务器是记性不好的,你一走,他就忘了你是谁了。但是服务器不会让你白登录,这时候服务器会返回给你一个票据,下次请求数据的时候,把这个票据带上,服务器就知道你登录过了。打个比方,你要去坐飞机,在网上买了机票,付了钱,?交了身份证号码。这就相当于注册成功了,我们假设身份证就是你的密码,能证明你的身份。
    你去机场值机的时候,人家让你出示身份证,输入电脑一查,验证成功,会给你一张机票。这张机票的意义是,你现在可以把身份证收起来了,机票就相当于你的身份证。你要去坐飞机?出示机票就行了。你要去头等舱做一个安静的美男子?出示机票就行了。那为什么不每次都出示身份证,要这个机票干嘛呢?很简单,你的身份证多宝贵啊,天天拿在手里,丢了怎么办?所以这里有一个原则,尽量不要让密码在网络上传来传去(包括哈希之后的)。另一方面,票据是有过期时间的,飞机飞走了,你的机票就成了一张废纸。别人偷了你的机票,等飞机飞走了,还是一张废纸。
  3. 记住密码和自动登录是怎么回事儿?
    假如你勾选了记住密码,客户端就真的记住你的密码吗?不用。客户端只是我们的一个代理,是替我们去 APP 后台拉取数据的,你会把你的身份证交给一个代理保管吗?只需要把票据给他就行了。它会把票据存期来,下次登陆的时候拿去服务器做验证。那么这个票据,藏在哪里好呢?在计算机里面,理论上内存是 安全的,进程是个隔离的,没人能轻易的读到别人进程里的东西。不过也有个例外,如果你的 Android 手机 root 了,各种管家和卫士就会在你的进程里扎根,监视你的一举一动。内存断电会丢失,所以我们一般存在 SD 卡上。这里你会与盗号者们正面交锋,所以要用上各种变态的加密算法。哦,对了,浏览器的话还可
    以存在 Cookie 里,虽然不怎么安全,但是很方便。

授权登录

从前有个大户人家姓白,富可敌国,家中收藏了大量的奇珍异宝。有一天,当地博物馆的馆长找到白先生,想为白先生在博物馆设立一个展台,每天借白先生家中的一些收藏品放在展馆展示。白先生觉得这个主意不错,但又不想把库房的钥匙给馆长,就让馆长去联系库房商量宝物借用事宜。库房跟白先生确认这件事之后,给了馆长一蓝一红两张令牌:蓝色的令牌上标注着使用日期,在有效期内,馆长可派人用蓝色令牌随意借还张家的宝物;当蓝色的令牌失效后,馆长需要派人带着红色令牌到库房这里换新的蓝色令牌。馆长拿到这两张令牌后,欣然离去。上面的栗子,简单叙述了移动应用微信登录的授权流程,以及授权后用户数据的获取方式(使用令牌),文中的「白先生」就是用户,他授权「馆长」(三方应用)使用自己存放在「库房」(微信服务器)中的宝物(用户数据、关系链等)。「蓝色令牌」是「库房」给「馆长」借用宝物的通行证,有一定的时效性,这是由于「蓝色令牌」使用的较为频繁,万一「遗失」或者「被盗」,造成的损失也有限。「红色令牌」则是「馆长」更换「蓝色令牌」的凭证。
微信授权登录系统基于 OAuth(发音:偶奥斯)2.0 协议标准,它提供了一套简单,安全的交互流程,让三方应用可以在不知道用户微信登录名和密码的情况下,访问用户在授权方服务器上的私密数据和资源。当三方应用需要使用微信授权登录功能时,需要先在微信开放平台获得对应的AppID 和 AppSecret。下面,我们看下微信授权登录系统的授权流程:
1、 用户请求三方应用用微信号登录。
2、 三方应用使用 AppID 向微信开放平台(客户端)发送登录请求。
3、 客户端加载授权页面,请求用户确认。
4、 用户点击确认按钮。
5、 微信客户端拉起三方应用,并将临时授权码(code)传递给三方应用,予授权完成。
6、 三方应用使用临时授权码(code)、AppID 和 AppSecret,通过 https 协议向微信开放平台(服务器)请求 access_token。
7、 服务器返回 access_token 和 refresh_token。
access_token 就是从服务器获取用户数据的「蓝色令牌」,refresh_token 则对应「红色令牌」。
access_token 的有效期是两个小时,refresh_token 的有效期是 30 天。
通过分析授权流程可以看出,要想获取 access_token,需要同时具备临时授权码(code)、 AppID 和 AppSecret 这三个信息,其中临时授权码由用户点击「确认登录」按钮后由服务器生成,它的有效期只有几秒,所以三方应用只要妥善的保管 AppSecret 和access_token,整个流程的安全性是值得信赖的。

定位

APP 请求了定位权限之后,就会通过系统接口获取当前手机的经纬度,上传给服务器。如何获取经纬度?首先想到的就是 GPS 了。GPS 的原理是,天上飘着几颗卫星,不断的广播自己的位置。定位时,打开你的手机里的 GPS 信号接收器,收集至少 4 颗卫星发出的信号,用收到信号的时间乘以光速可以算出你和每颗卫星之间的距离,再加上每个卫星的位置已知,就可以确定你的位置了。
GPS到了室内没了卫星信号就不行了,这时候就轮到定位两兄弟:基站定位和 WIFI 定位出场了。他们的原理很相似。前面说定位的关键是参照物,基站定位的参照物是就是基站。运营商通过查询你手机连接的基站的位置,就能找到你。WIFI 定位的参照物是无线路由器。是你连接到无线路由器的时候,上传了该路由器的 MAC 地址,服务器通过查询公开的 MAC 地址对应的经纬度来找到你。

应用间的调用

整个过程相当于应用在系统中注册自己,通常应用公布自己的能力的方式是注册 Scheme,我们 常见的 Scheme 就是 http:了,声明了这个 Scheme 的应用声称自己支持 http 协议,能够打开网页了(不过实际能不能打开,鬼知道),还有一些常见的 Scheme比如 file:,tel:等,当然,应用不仅可以声明这些标准的 Scheme,也能声明自己独有的Scheme,比如微信的就是 weixin:,QQ 的是 mqq:,那如果多个应用都声明相同的 Scheme呢?比如王五说自己会发照片,赵六也说自己会发照片,这时系统会有一定的策略来保证公平性,比如 Android 上,系统就会弹出支持的应用列表,让用户选择,IOS 则替用户选择近打开过的支持应用。
理解了调用的方法,那么后面数据传递就很简单了,只需要在 Scheme 后面携带上需要传递的信息就可以了,比如:wangwu://action=sendphoto,photopath=xxxx,后面的数据 终会带到声明 wangwu 这个 Scheme 的应用中,但是王五收到了信息并不知道是谁发的,该回信息给谁,那么怎么回调呢,也很简单,发起调用的张三在 Scheme 后面的参数加一个backScheme=zhangsan: , 这 样 王 五 就 知 道 了 如 果 需 要 回 信 息 , 则 构 造 一 个zhangsan://xxxxxx,这种自定协议可以叫做伪协议,这些字段也不是规定死的,只要交互双方自己能识别处理就行。

计算机网络

协议栈

网络中的数据传输过程与量子传输技术类似,需要先将原始数据拆解,最终转化为电平或者光信号后在物理介质上传输。原始信息的「分解」和「还原」都是在协议栈中进行的。
在这里插入图片描述
• 应用层:为应用程序提供数据传输的网络接口,例如我们常见的 http、ftp 等协议都工作在这一层;
• 传输层:传输层提供端到端的连接,说白了就是让 A 主机上的程序 a 找到 B 主机上的程序 b,TCP 和 UDP 协议都是工作在这一层,端口号的概念也定义在这一层;应用层协议将数据打包好了之后丢给传输层进行传输。
• IP 层:这个就不用多说了,路由的主机寻址都是靠它,它存在的目的就是为了让两台主机能在 Internet 的茫茫「机海」中找到彼此。
• 数据链路层:网卡就工作在这一层,负责将数字信号转化成可供物理层传输的电信号或者光信号;
• 物理层:这个没啥好说的,就是信号传输的物理通道,比如网线和配套的接口。
协议栈中的每一层都起着承上启下的作用,应用程序产生的数据,经过这五层协议栈模型自上而下逐层「分解」最终变成可供物理介质传输的信号,当到达目的主机后,再自下而上「还原」成应用程序数据。
网络层的ip帮我们区分子网,以太网层的mac帮我们找到主机。那么我们通过ip和mac找到了一台特定的主机,接下来通过端口来标识这台主机上的应用程序,端口即应用程序与网卡关联的编号。
详情可见:https://blog.csdn.net/yonggeit/article/details/79115649

Dcoker

如何解决环境依赖?如何解决大规模部署?如何解决应用与应用的互相影响?Docker 就是这些问题的一种解决方案,它是一个容器,也可以说是一个软件集装箱,这个箱子里面可以塞入特定版本的操作系统、数据库、服务器程序和web 应用,这样一套完整的 web 服务就集成在这个箱子里面了,当要发布服务的时候,直接将这个集装箱放在我们的服务器船上。Docker 算是一种轻量级的虚拟机,它比起传统的虚拟机更快,更节省资源。

IP

电脑IP要看你指的是局域网还是公网,局域网是自己设置的,公网是由宽带连接决定的。服务商对接入网络时的电脑都会动态分配一个IP地址。

公网IP是没有重复的,不过通常一个出口IP可以有多设备连接。比如公司的公网IP是52.8.8.8,所有连接公司网络的电脑上报的公网IP就全是52.8.8.8

不同局域网的IP可能有重复,但同一局域网的IP没有重复。同一局域网会根据mac由DHCP服务器分配内网IP,员工A和员工B的内网IP分别是172.1.1.1和172.1.1.2

www.ip138.com 上查到的IP 是 NAT 转换后的外网 IP,而系统属性中查到的 IP 是内网 IP。

Ping和网关

ping 是 TCP/IP 协议族中的一部分,它的原理是向目标 IP 地址发送一个数据包,如果对方返回一个同样大小的数据包,则证明连通。并且整个过程能够测试时延。
以太网适配器,也就是常说的网卡。
网关的意思类似,是两个网络之间的桥梁, TA 仅仅是一个逻辑上的概念,在物理上,TA 表现为一个 IP 地址。网关启到了转发、过滤和安全的作用。

session

虽然 Http 协议是无状态的,但是仍然可以在协议层之上对其进行扩展,也就是现在主要讲述的 session 机制。session 翻译成中文为「会话」,其实是指客户端和服务端会产生联系,在标准的 http协议中,他们其实是不会产生联系的,session 机制弥补了这种不足,弥补了 http 协议无状态的问题。session 机制主要是指服务端记住用户的能力,这往往要靠客户端 cookie 机制来辅助实现。
在系统编程实现的时候,相当于后台对浏览器种植 cookie,这样对小明进行了标识,同时在后台系统中增加一条记录,称为 sessionid,session id 的值,就是浏览器的 cookie 的值,这样浏览器端和服务器端就可以对应上了。

端口

端口,即终端留给外部的接口,是不同设备间通信的桥梁。物理上用来沟通的我们可以叫做物理端口,比较常见的像电脑的网孔,USB 端口这些。一个 USB 端口是要如何才能适应这繁多的外设呢?靠的是驱动,驱动是外部硬件设备跟计算机之间交流时的翻译。
计算机中有很多的服务,这些服务运行在各自的进程当中,很多服务都和外部有沟通的需求。很显然,我们不能为每个服务都开一个物理网络端口,一般情况下,所有的服务发的数据都是从一个物理网络端口发出去的,当然,外部回应的数据包也都是从这一个网孔挤进来的。
那么问题来了,如果数据都挤在一起收发,服务怎么知道哪个回来的数据才是自己需要的?为了解决这个问题,计算机有了虚拟端口这个概念,一个服务想和外部进行信息互通时,需要先绑定一个端口号,不需要真实打孔,用一个数字表示就好,这个服务在发数据包的时候带上自己的端口号,同时还要指定目标服务的端口号。计算机收到数据包时,会根据数据包中标明的端口号,将数据放到对应服务声明端口的缓冲区中,等待服务取走数据包。

TCP UDP

TCP/IP 协议,其中 TCP(Transmission Control Protocol)称为传输控制协议,IP(Internet Protocol)称为因特网互联协议。其实 TCP/IP 协议,是一个协议簇,就是一大堆协议的集合,这一大套协议定义了整个互联网通信的基础,比如一次网络链接要经过哪些步骤,一块数据传输过程中应该如何解释,这块数据该如何展示给编程者等等问题。
TCP/IP 协议又分为了 4 层,分别为应用层,传输层,IP 层,物理层。重点介绍下传输层,也就是 TCP,UDP 两个协议。TCP 是需要对方确认的,也就是传输之前需要进行「三次握手」(这里又是一个专有名词,就是传输的两端要经过三次确认,才能开始通信)。UDP 是比较粗暴的,不管对方什么情况,直接发送,不需要确认过程。很多博客和书籍中说的,TCP 是可靠的链接,UDP 是不可靠的链接就是这个意思。可靠的链接带来的是效率的下降,比如一次网络请求很大一部分时间都是浪费在互相确认的过程当中,资源消耗比较多,但是保证了数据的传输是可靠的,并且数据传输是有序的。不可靠的链接带来的是效率的提升,但可能服务质量有下降。

邮件协议

POP 的大名是 Post Office Protocol,中文是邮局协议,听起来高大上,但是它很弱,只是支持从邮件服务器上将用户的邮件下载到本地。标准的协议中,使用 POP 下载过的邮件都会从邮件服务器上删除,不过大家都觉得这种行为很不合理,然后大部分邮件服务器都改良了它,支持下载邮件并不删除服务器上的副本。POP 的一个优点,就是支持离线所有邮件,如果你长期处于断网的情况,又想查看每一封邮件,那你可以在客户端上配置使用 POP来接收邮件。
IMAP 是另一种从邮件服务器下载邮件的协议,它比 POP 要强大一些,它在从服务器获取邮件的时候,可以选择先获取标题和摘要,当你想看具体内容时,再去拉取正文,同时,它还可以将你对邮件处理的一些状态(如标记为已读、删除)同步给服务器,这样你在另外一个客户端上就不用再处理一次了。
接着谈发送邮件,一封邮件从客户端到自己的邮箱服务器,再从自己的邮箱服务器到对方的邮箱服务器,都是使用的 SMTP(Simple Mail Transfer Protocol)协议进行传输的,它是一种「推」的协议,将邮件推送给服务器。

反向代理

通常我们所说的代理,都是指的客户端向外界发起请求时,并不是直接与目标服务器连接,而是经过一个代理服务器,将所有请求交给代理服务器,由它去负责连接外界的目标服务器,同时从服务器返回的数据,也经过代理服务器,返回到客户端。在外界看来,所有请求都是来自这台代理服务器,这样就成功的将客户端隐藏在自己身后,起到了一种保护客户端的作用。
而『反向代理』却是反过来的,它是针对服务器的一种代理技术。反向代理服务器可以接受客户端的请求,然后将它分发到被代理的服务器上,待这些服务器处理完请求后,再将结果转发给客户端,它是将服务器隐藏在自己的身后。从客户端看来,它面对的只有一台服务器,但是背后可能有 1000 台服务器在提供服务。
首先,它可以做『负载均衡』。比如说,对于同一个 web 服务,有 10 台服务器可以提供服务,但是每台服务器的负荷不太一样,如果一个请求发送到负荷较高的服务器,那么它的处理时间可能会稍长一点,但是客户端是不知道哪一台服务器比较空闲,所以将请求发送到『反向代理』服务器,它是知道每台服务器的负载的,这样由它将请求转发到相对空闲的服务器,以便更快的响应客户端。
然后,它可以减轻后端服务器的一些压力,比如很多静态资源或者缓存数据,可以直接放在反向代理服务器上,不用将这些请求传递到后端服务器,相对来说减轻了后端服务器的压力。
它还可以对请求做进一步的封装和解封,比如想把所有请求升级到 ssl 加密连接,却不想改造后端服务器,那么可以只在客户端-反向代理服务器之间使用 ssl 加密连接,而代理服务器-后端服务器之间仍旧使用普通 http 连接,这样就事半功倍了。

CDN

「内容分发网络」,英文名是 Content Delivery Network。
CDN 专注于「内容」,也就是 CDN 的 C 所代表的 Content,专注于静态资源的分发和访问,比如一张图片,一个文本文件,一个视频,一个 CSS,一个 JS 等等,任何以文件形式存储的,为了提高在互联网上的访问速度和质量,都可以将这个资源部署在 CDN 这个网络上。
CDN 动作是「分发」,也就是如何让刚才提到的那些「内容」快速的部署在这个网络中,从而快速为用户服务,其实还有一层更重要的含义是用户的快速访问与就近接入,分发的目的是为了用户更好的体验。
CDN 落定于「网络」,是部署于全国或者全世界的一大堆服务器,这些服务器基于当前互联网的基础架构在其上层再构成一个网络,这个网络专为资源分发而生。
我们可以推导出 CDN 的作用是:CDN 厂商构建了一个基于互联网数量巨大的服务器,专注于内容和资源分发,方便用户快速访问,提升用户体验的一个内容网络。
首先要说的是应用服务器和资源服务器应该解耦,也就是应用服务器只处理逻辑,而资源服务器存放内容或者叫资源。术业有专攻,如果混在一起,会拖慢应用服务器的速度,如果没有 CDN 来专门处理资源,那所有的资源部署可能会离用户很远,保证不了体验,专业的CDN 服务商专注于这里,并且规模也让成本不断下降,就像许多公司周边产品都是外包出去,自己也可以做,只不过专门生产礼品的公司会更有效率、更专业、价格也更低、不耗费自己公司的人力资源。
总结一下,CDN 是一种资源的分布式存放和备份的方法。

push数据例子

  1. 在出生之前,我身体的每一部分甚至我的灵魂早就在配置平台上定义清楚了。当这一切都配置完毕后,母亲只是在等待一个时机来孕育我,这个时机可能是墙上的那台老挂钟(服务器时间),也可能是来自远地方朋友的信件(客户端行为反馈)。
  2. 在长途车站,我取到了我的单程票,上面写着一个 ip 地址和一个端口号。候车室的那头是一片壮观的景象,无数条高速路(长连接)密密麻麻的排列着。通道上总会时不时的从远处驶来一些只有车头(数据报Header),但并没有车厢(数据)的车辆。这些空箱车辆的目的就是为了确认高速通道的有效性,只要有车辆从高速路驶入,就说明高速路另一端是可达的!高速路失效后,如果想再次建立,就需要远端用新的地址发送车辆过来。
  3. 当咱们到达目的地的时候,客户端就会立即派人过来向服务器报平安(ACK)。刚出发的时候服务器登记了我们的出发时间,如果在规定的时间内没有收到客户端的反馈(ACK),服务器就会认为我们在路上遇到了特殊情况,无法到达目的地(数据发送失败),这时,服务器就可以根据策略决定是否要重新发一辆车来完成任务(重传机制)。
  4. 旅途磕磕绊绊,每一会司机就要停下到岗亭(路由器)取一个卡片然后再出发。这次司机又把车停了下来,因为好奇,我跟着司机一起来到岗亭,只见业务员拿着司机给他的 IP 地址在一个表格(路由表)上检索了一下后,就开始拿着喇叭大喊「谁的 IP 是192.168.2.1?」(ARP 广播),好像要让整个网络中的人都听到。没过多久,就有人打电话过来,告知业务员自己的 IP 地址就是「192.168.2.1」,并同时告诉了业务员自己的 MAC 地址。业务员将 MAC 地址写到一张卡片上后,交给了司机。
    咱们现在所处的庞大的 Internet 网络系统,由无数个子网组合而成,每个子网之间,都由各自的网关路由器连接。当我们从服务器出发后,需要经过一个个网关路由器的中转才能最终到达目的地。而到达下一个路由器之前,我们需要用目的 IP 地址在当前路由器的路由表中拿到下一个网关的 MAC 地址,按这个地址行驶才能到达指定的路由器,刚才业务员的狮吼功,就是创建路由表的一种手段。如果没有下一跳路由器的MAC 地址,就等着做网络中的孤魂野鬼吧!

HTTP

HTTP(HyperText Transfer Protocol)超文本协议,是互联网上的一个基本协议,而在打开一个网页时,表示以 http 协议的方式来获取这个网页的内容,其中包括了网页文本和各种图片资源。如果你想以加密的方式访问,还可以使用 https 协议来获取资源。

HTTPS 协议

在传统的 HTTP 协议中,应用层的 HTTP 协议将应用程序?供的数据封装后,明文交给位于运输层的 TCP 协议发送到网络上。由于是明文传输,发送的信息可以在传输过程中被任意篡改,甚至被完全替换。
HTTPS 中文学名「安全超文本传输协议」,HTTPS 协议在 HTTP 和 TCP 之间添加了一层 SSL 协议。SSL 是用来保障网络上数据传输安全的一套协议,它在传输层对 HTTP 进行封装加密,然后将数据交由 TCP协议发送到网络上。使用 HTTPS 的服务器,需要在受信任公司申请一套数字证书,也就是密码学中的公钥和私钥,用于进行非对称加密。公钥加密的数据需要用私钥解密,私钥加密的数据需要用公钥解密。

1、 客户端发起 https 请求;
2、 服务器将公钥发送给客户端,客户端可以根据公钥验证服务器的身份。
3、 客户端生成一个加密密钥,公钥加密后,将密钥传输给服务器,服务器用私钥解
密报文获得客户端密钥;
4、 服务器和客户端的数据传输都通过客户端密钥进行加解密。

抗日战争时期,我党两个指挥部之间需要进行加密电报通信安排作战计划,但是两方当前用的都是非加密的电码本(明文传输),通信内容很容易被敌方破解。正巧,指挥部 A(服务器)有一个便携保险箱(公钥)和钥匙(私钥),于是便派通信员小张单独将保险箱(公钥)秘密送达了指挥部 B(客户端),保险箱的钥匙(私钥)还是被保存在指挥部 A。指挥部 B(客户端)收到箱子后,一看上面印着的五角星,便知其来由,于是将加密后的电码本(客户端加密密钥)放在了箱子里,将箱子锁好,由小张带回了指挥部 A。指挥部 A 收回箱子后,用钥匙将保险箱打开,这样,两个指挥部便都有了加密后的电码本(客户端加密密钥),后续的作战计划电报报文都用新的密码本编码,保证了信息的安全传递!

访问网页流程

输入网页域名 www.baidu.com,首先发生的是 DNS 解析,也就是将域名转换成为 IP 地址。提供这个服务的一般都是宽带运营商。
从我们的电脑到百度的服务器之间还隔了多个路由节点,其中任意一个路由不帮助我们转发消息,都有可能连接不上。
假如成功连上了百度的服务器,这个时候百度开始处理我们的请求,有可能我们请求的网址是个错误页面,或者是我们的请求导致了服务器处理异常,都有可能导致我们看不到正确的网址,而是一堆错误页面。

前端

web语言

html:超文本标记语言
CSS:级联样式表
Javascript:一种脚本语言,主要用于前端页面的 DOM 处理

开发工具/开发技术

数据结构

数据结构就是用来帮助程序员处理批量的数据的(主要是插入、删除、修改、查询,简称 CRUD)。
这个世界一开始并没啥数据结构,后来有了数据,数据越来越多,人们为了方便处理,也就发明了各种结构。所以每一种数据结构都是用来解决一些特定的问题的。

  1. 数组
    数组的特点就是一下子可以呈很多数据,它们挨个排放,每个位置都有一个编号,数据就是通过编号来访问的。
    对数组来说,插入操作比较费力。上面的例子里,后台突然推送了一条最高优先级的新闻过来,要求插入到数组的最前端。这样一来,数组里的所有数据必然都要往后挪,给新来的腾空间。但是数组总体的容量是一定的,所以一般的做法是,重新弄一个稍微大一点的数组,写入新数据,再把之前的数据一个一个拷贝进来。
    数组删除一个元素也比较复杂。数组不能在中间出现空格,删除一个元素后,你就得把后面所有元素依次向前挪一个格。
    数组也不是一无是处,它的修改操作非常方便,前问讲过,你只需要喊出数据的编号,
    然后就可以修改它了。至于数组查询,你得一个一个遍历加对比,表现一般。
  2. 链表
    数组是一种最简单的数据结构,学名叫线性表。还有一种线性表,经常拿来和数组做对比,叫链表。链表跟数组差不多,但是它的数据不是挨个放的,也没有编号。链表的每个数据中,都有一个指向下一个数据位置的指针。
    在这里插入图片描述插入数据的操作。例如我要在 A 新闻和 C 新闻后面插入一条 B 新闻,我只要从链表头部开始,顺藤摸瓜,先找到 A 新闻,把 A 新闻的指针写成 B 的位置,然后把 B 新闻的指针写成 C 的位置,就可以了。所有改动只是改一下地址,并不会牵扯到数据的大范围移动,这一点非常方便。
    在这里插入图片描述删除也很简单,先顺着链子找到要删除的位置,然后把这个位置前后数据接起来就行。
    在这里插入图片描述而修改操作,就不是链表的强项了。你依然需要顺藤摸瓜找到要修改的数据,不像数组那样,一个编号就能找到。至于链表的查找,和数组一样,你得一个一个遍历,中规中矩。
  3. 队列
    队列是一种「先进先出」的数据结构。所谓进,就是数据的插入,所谓出,就是数据的删除。「先进先出」的意思是,你插入的时候是什么顺序,删除的时候还是什么顺序,不能乱插,也不能乱删。一个很直观的例子就是去食堂排队打饭。如果把人看做数据,那么整个队伍就是专门「存储」人的一个队列。先来的人,先进入队列,也就享受先打饭的权利。第一个人打完饭之后,前面的人出队(删除),后面的人跟上,以此循环,知道整个队伍空了为止。在这里插队是被禁止的,随意调整顺序(比如排在中间的家伙跑到第一个去)也是被禁止的,队列的实现者会保证这一点。
    总结一下,如果你的数据在处理过程中需要保持原有的顺序,用队列来处理,准没错。

  4. 有的需求必须「先进后出」才行,于是就有了栈。关于栈,每次我进电梯的时候,都会想起这个词。同事中有几个行动不便的大胖子,进电梯都要最后进,因为可以最先出来喘口气。类似的例子还有不少,比如你用 chrome 看网页,点了一个链接进入下一页,如此重复了十几次,最后想回到一开始的地方,你开始不停的按回退键,此时你浏览过的网页便一个接一个的出现,它们的顺序,就是「后进先出」。这个结构,叫做「历史栈」。不光浏览器,很多 APP 也有「历史栈」。不信你看知乎。
    栈溢出(stackoverflow)
    操作系统会划分一些内存给 APP 使用,并且内存中数据的组织结构会用到栈这个东西。但是这些内存并不是取之不尽的,相反会有大小的限制。「栈溢出」就是你的 APP 用的内存不小心超过了系统的限制,然后系统把你杀死,小船儿就这样说翻就翻了。

名词解释

搜索引擎基石-倒排索引

简单的做法就是,搜索引擎将会遍历它抓取到的所有文档,从中挑选出与关键词相关的文档,这种叫做正向索引。可是要知道,Google 现在收录的网页数目是万亿级别的,要是真像这样遍历全部文档,那估计你搜索一个关键词,要等个一年才能看到搜索结果。
那么为了加快搜索速度,需要建立相反的一个索引的列表,在爬虫抓取回一个网页后,先对它进行分词处理,然后把这些提取出来的关键词与这个网页的 ID 做一个映射,这就是倒排索引(Inverted index)。
比如我们有编号 T0-T2 的三篇文档,它们的内容分别是:T0=“it is what it is”,T1=“what is it”, T2=“it is a banana”,可以对每篇文章都先分词处理,然后统计每个词对应的文档,得到这样一个倒排索引:
在这里插入图片描述当我们要搜索"what is it"时,可以直接找出这三个词索引的文档编号的并集,即 T0 和T1,这就是用倒排索引搜索关键词的基本流程。所以平时我们使用搜索引擎时,它的搜索结果并不是实时查找出来的,而是使用了?前做好的倒排索引,将关键词的索引结果合并展示出来的。
当然了,倒排索引只是搜索引擎的一个基础架构,一个单词的索引结果也会有成百上千万个,如何对这些结果进行有效的排序,让用户真正想要的搜索结果排名靠前,才是关键技术。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页