每天进步一丢丢

程序设计语言中的 一等公民,二等公民,三等公民

一等公民

一般来说,如果某程序设计语言中的一个值可以作为参数传递,可以从子程序中返回,可以赋值给变量,就称它为一等公民

二等公民
可以作为参数传递,但是不能从子程序中返回,也不能赋给变量

三等公民

它的值连作为参数传递都不行(比如label)

字面量

在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)。几乎所有计算机编程语言都具有对基本值的字面量表示,诸如:整数浮点数以及字符串;而有很多也对布尔类型字符类型的值也支持字面量表示;还有一些甚至对枚举类型的元素以及像数组记录和对象等复合类型的值也支持字面量表示法。

CS/BS架构

1、CS架构

是Client/Service这两个单词的首字母,指的是客户端服务器架构的意思,很多常见的软件都是这种架构。

解释:对于CS架构,最为常见的例子就是网络游戏,比如LOL、WOW如果不联网无法使用,你在软件内的所有操作通过互联网能够传递到其他的玩家身上。

优点:第一,性能较高:可以将一部分的计算机工作放在客户端上,这样服务器只需要处理数据即可。第二,界面炫酷:客户端可以使用更多系统提供的效果,做出更为炫目的效果。

缺点:第一,更新软件:如果推出了新版本,不更新客户端无法登录使用(一部分)。第二,不同设备访问:如果使用其他的电脑,没有安装客户端的话就无法登录软件。

2、BS架构

是Browser/Server这两个单词的首字母,指的是浏览器服务器,是WEB兴起后的一种架构。

解释:现在所有的网站都是BS架构,较为常见的例子有知乎、百度、网易云音乐Web等等,所有只需要通过浏览器即可使用。

优点:第一,更新简洁:如果需要更新内容了,对开发人员而言需要更改服务器的内容,但是对用户而言只需要刷新浏览器即可。第二,多设备同步:所有数据都在网上,只要能够使用浏览器即可登录使用。

缺点:第一,性能较低:相比于客户端应用性能较低,但是随着硬件性能的提升,这个差距在缩小。第二,浏览器兼容:处理低版本的浏览器显示问题一直是开发人员头疼的问题之一,移动设备兼容性较好,ie6已经越来越少人用了。

IaaS、PaaS、SaaS

假设你是一家超牛X的技术公司,根本不需要别人提供服务,你拥有基础设施、应用等等其它一切,你把它们分为三层:基础设施(infrastructure)、平台(platform)和软件(software),如下图:

这其实就是云计算的三个分层,基础设施在最下端,平台在中间,软件在顶端,分别是分别是Infrastructure-as-a-Service(IaaS),Platform-as-a-Service(PaaS),Software-as-a-Service(SaaS),别的一些“软”的层可以在这些层上面添加。

而你的公司什么都有,现在所处的状态叫本地部署(On-Premises),就像在自己家做pizza一样。几年前如果你想在办公室或者公司的网站上运行一些企业应用,你需要去买服务器,或者别的高昂的硬件来控制本地应用,让你的业务运行起来,这就叫本地部署。

IaaS: Infrastructure-as-a-Service(基础设施即服务)

有了IaaS,你可以将硬件外包到别的地方去。IaaS公司会提供场外服务器,存储和网络硬件,你可以租用。节省了维护成本和办公场地,公司可以在任何时候利用这些硬件来运行其应用。

一些大的IaaS公司包括Amazon, Microsoft, VMWare, Rackspace和Red Hat.不过这些公司又都有自己的专长,比如Amazon和微软给你提供的不只是IaaS,他们还会将其计算能力出租给你来host你的网站。

PaaS: Platform-as-a-Service(平台即服务)

第二层就是所谓的PaaS,某些时候也叫做中间件。你公司所有的开发都可以在这一层进行,节省了时间和资源。

PaaS公司在网上提供各种开发和分发应用的解决方案,比如虚拟服务器和操作系统。这节省了你在硬件上的费用,也让分散的工作室之间的合作变得更加容易。网页应用管理,应用设计,应用虚拟主机,存储,安全以及应用开发协作工具等。

一些大的PaaS提供者有Google App Engine,Microsoft Azure,Force.com,Heroku,Engine Yard。最近兴起的公司有AppFog,Mendix和Standing Cloud.

SaaS: Software-as-a-Service(软件即服务)

第三层也就是所谓SaaS。这一层是和你的生活每天接触的一层,大多是通过网页浏览器来接入。任何一个远程服务器上的应用都可以通过网络来运行,就是SaaS了。

你消费的服务完全是从网页如Netflix,MOG,Google Apps,Box.net,Dropbox或者苹果的iCloud那里进入这些分类。尽管这些网页服务是用作商务和娱乐或者两者都有,但这也算是云技术的一部分。

一些用作商务的SaaS应用包括Citrix的Go To Meeting,Cisco的WebEx,Salesforce的CRM,ADP,Workday和SuccessFactors。

CI/CD

CI/CD 的出现改变了开发人员和测试人员发布软件的方式。本文是描述这一变化的系列文章第一篇, 这些文章将提供各种工具和流程的讲解,以帮助开发人员更好的使用 CI/CD。

从最初的 瀑布模型, 到后来的 敏捷开发, 再到今天的 DevOps, 这是现代开发人员构建出色产品的技术路线。 随着 DevOps 的兴起,出现了持续集成,持续交付(CI/CD)和持续部署的新方法, 而传统的软件开发和交付方式在迅速变得过时。过去的敏捷时代里, 大多数公司的软件发布周期是每月、每季度甚至每年(还记得那些日子吗?), 而在现在 DevOps 时代,每周、每天甚至每天多次都是常态。 当 SaaS 成为业界主流后尤其如此,您可以轻松地动态更新应用程序, 而无需强迫用户下载更新组件。很多时候,用户甚至都不会注意到正在发生变化。

开发团队通过软件交付流水线(Pipeline)实现自动化,以缩短交付周期, 大多数团队都有自动化流程来检查代码并部署到新环境。 我们一直在关注自动化测试流程,但这将在之后的文章中介绍。 今天,我们将介绍什么是 CI/CD/CD ,以及现代软件公司如何使用工具将部署代码的流程自动化。

持续集成注重将各个开发者的工作集合到一个代码仓库中,通常每天会进行几次, 主要目的是尽早发现集成错误,使团队更加紧密结合,更好地协作。 持续交付的目的是最小化部署或发布过程中团队固有的摩擦, 它的实现通常能够将构建部署的每个步骤自动化,以便任何时刻能够安全地完成代码发布(理想情况下)。 持续部署是一种更高程度的自动化,无论何时代码有较大改动, 都会自动进行构建/部署。

以上的每一个阶段都是交付流水线的一部分。 Humble 和 Ferley 在他们的书作《持续交付:通过自动化构建、测试和部署实现可靠软件版本发布》中解释说: “对软件的每次更改都要经过一个复杂的过程才能发布,该过程包括多个测试和部署阶段进行软件的构建。 反过来看,这个过程需要许多人之间的合作,甚至可能需要几个团队间合作。 部署流水线对这一过程进行建模,并且它的持续集成和发布管理工具能让您在代码从版本控制转移到各种测试和部署时, 查看和控制每次更改的过程。”

持续集成(CI)

通过持续集成,开发人员能够频繁地将其代码集成到公共代码仓库的主分支中。 开发人员能够在任何时候多次向仓库提交作品,而不是独立地开发每个功能模块并在开发周期结束时一一提交。

这里的一个重要思想就是让开发人员更快更、频繁地做到这一点,从而降低集成的开销。 实际情况中,开发人员在集成时经常会发现新代码和已有代码存在冲突。 如果集成较早并更加频繁,那么冲突将更容易解决且执行成本更低。

当然,这里也有一些权衡,这个流程不提供额外的质量保障。 事实上,许多组织发现这样的集成方式开销更大,因为它们依赖人工确保新代码不会引起新的 bug 或者破坏现有代码。 为了减少集成期间的摩擦,持续集成依赖于测试套件和自动化测试。 然而,要认识到自动化测试和持续测试是完全不同的这一点很重要,我们会在文章结尾处详细说明。

CI 的目标是将集成简化成一个简单、易于重复的日常开发任务, 这样有助于降低总体的构建成本并在开发周期的早期发现缺陷。 要想有效地使用 CI 必须转变开发团队的习惯,要鼓励频繁迭代构建, 并且在发现 bug 的早期积极解决。

持续交付(CD)实际上是 CI 的扩展,其中软件交付流程进一步自动化,以便随时轻松地部署到生成环境中。 成熟的持续交付方案也展示了一个始终可部署的代码库。使用 CD 后,软件发布将成为一个没有任何紧张感的例行事件。 开发团队可以在日常开发的任何时间进行产品级的发布,而不需要详细的发布方案或者特殊的后期测试。

CD 集中依赖于部署流水线,团队通过流水线自动化测试和部署过程。此流水线是一个自动化系统, 可以针对构建执行一组渐进的测试套件。CD 具有高度的自动化,并且在一些云计算环境中也易于配置。

在流水线的每个阶段,如果构建无法通过关键测试会向团队发出警报。否则,将继续进入下一个测试, 并在连续通过测试后自动进入下一个阶段。流水线的最后一个部分会将构建部署到和生产环境等效的环境中。 这是一个整体的过程,因为构建、部署和环境都是一起执行和测试的,它能让构建在实际的生产环境可部署和可验证。

AWS 上提供了可靠的当前 CI/CD 的展示,亚马逊是云计算的提供商之一,提供出色的 CI/CD 流水线环境和实验过程, 有众多开发资源可供选择,您可以将它们在一个易于配置和监控的流水线中组合起来。

许多人认为持续交付的吸引力主要在于,它自动化了从提交代码到仓库,再到测试和发布产品过程的所有步骤。 这是构建和测试过程细致的自动化,但是如何发布以及发布什么仍然是需要人工操作,持续部署可以改变这一点。

持续部署(CD)

持续部署扩展了持续交付,以便软件构建在通过所有测试时自动部署。在这样的流程中, 不需要人为决定何时及如何投入生产环境。CI/CD 系统的最后一步将在构建后的组件/包退出流水线时自动部署。 此类自动部署可以配置为快速向客户分发组件、功能模块或修复补丁,并准确说明当前提供的内容。

采用持续部署的组织可以将新功能快速传递给用户,得到用户对于新版本的快速反馈,并且可以迅速处理任何明显的缺陷。 用户对无用或者误解需求的功能的快速反馈有助于团队规划投入,避免将精力集中于不容易产生回报的地方。

随着 DevOps 的发展,新的用来实现 CI/CD 流水线的自动化工具也在不断涌现。这些工具通常能与各种开发工具配合, 包括像 GitHub 这样的代码仓库和 Jira 这样的 bug 跟踪工具。此外,随着 SaaS 这种交付方式变得更受欢迎, 许多工具都可以在现代开发人员运行应用程序的云环境中运行,例如 GCP 和 AWS。

最受欢迎的自动化工具是 Jenkins(以前的 Hudson), 这是一个由数百名贡献者和商业公司 Cloudbees 支持的开源项目。 Cloudbees 甚至聘请了 Jenkins 的创始人,并提供了一些 Jenkins 培训项目和附加组件。 除了开源项目之外,还有一些更现代化的商业产品例如 CircleCI,Codeship 和 Shippable。 这些产品各有优缺点,我鼓励开发人员在开发流程中一一尝试它们,以了解它们在您的环境中的工作方式, 以及它们如何与您的工具、云平台、容器系统等协作。

反弹shell原理与实现

什么是反弹shell?

  反弹shell(reverse shell),就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端的角色反转。

为什么要反弹shell?

通常用于被控端因防火墙受限、权限不足、端口被占用等情形。

举例:假设我们攻击了一台机器,打开了该机器的一个端口,攻击者在自己的机器去连接目标机器(目标ip:目标机器端口),这是比较常规的形式,我们叫做正向连接。远程桌面、web服务、ssh、telnet等等都是正向连接。那么什么情况下正向连接不能用了呢?

有如下情况:

1.某客户机中了你的网马,但是它在局域网内,你直接连接不了。

2.目标机器的ip动态改变,你不能持续控制。

3.由于防火墙等限制,对方机器只能发送请求,不能接收请求。

4.对于病毒,木马,受害者什么时候能中招,对方的网络环境是什么样的,什么时候开关机等情况都是未知的,所以建立一个服务端让恶意程序主动连接,才是上策。

那么反弹就很好理解了,攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接。

蜜罐技术

蜜罐技术本质上是一种对攻击方进行欺骗的技术,通过布置一些作为诱饵的主机、网络服务或者信息,诱使攻击方对它们实施攻击,从而可以对攻击行为进行捕获和分析,了解攻击方所使用的工具与方法,推测攻击意图和动机,能够让防御方清晰地了解他们所面对的安全威胁,并通过技术和管理手段来增强实际系统的安全防护能力。

好比是情报收集系统。罐好像是故意让人攻击的目标,引诱黑客前来攻击。所以攻击者入侵后,你就可以知道他是如何得逞的,随时了解针对服务器发动的最新的攻击和漏洞。还可以通过窃听黑客之间的联系,收集黑客所用的种种工具,并且掌握他们的社交网络。

/dev/null 和 /dev/zero

/dev/null : 在类Unix系统中,/dev/null,或称空设备,是一个特殊的设备文件,它丢弃一切写入其中的数据(但报告写入操作成功),读取它则会立即得到一个EOF。
在程序员行话,尤其是Unix行话中,/dev/null 被称为位桶(bit bucket)或者黑洞(black hole)。空设备通常被用于丢弃不需要的输出流,或作为用于输入流的空文件。这些操作通常由重定向完成。

/dev/zero : 在类UNIX 操作系统中, /dev/zero 是一个特殊的文件,当你读它的时候,它会提供无限的空字符(NULL, ASCII NUL, 0x00)。

其中的一个典型用法是用它提供的字符流来覆盖信息,另一个常见用法是产生一个特定大小的空白文件。BSD就是通过mmap把/dev/zero映射到虚地址空间实现共享内存的。可以使用mmap将/dev/zero映射到一个虚拟的内存空间,这个操作的效果等同于使用一段匿名的内存(没有和任何文件相关)。

CMOS

CMOS是Complementary Metal Oxide Semiconductor(互补金属氧化物半导体)的缩写。它是指制造大规模集成电路芯片用的一种技术或用这种技术制造出来的芯片,是电脑主板上的一块可读写的RAM芯片。因为可读写的特性,所以在电脑主板上用来保存BIOS设置完电脑硬件参数后的数据,这个芯片仅仅是用来存放数据的。

电压控制的一种放大器件,是组成CMOS数字集成电路的基本单元

而对BIOS中各项参数的设定要通过专门的程序。BIOS设置程序一般都被厂商整合在芯片中,在开机时通过特定的按键就可进入BIOS设置程序,方便地对系统进行设置。因此BIOS设置有时也被叫做CMOS设置。

Linux(UNIX)操作系统五种IO模型

在Linux(UNIX)操作系统中,共有五种IO模型,分别是:阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动IO模型以及异步IO模型。

既然提到晚上吃鱼,那就通过钓鱼的例子来解释这五种IO模型吧。

到底什么是IO
我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢?

拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目的是把它读取到内存中。可以把这个步骤简化成把数据从硬件(硬盘)中读取到用户空间中。

其实真正的文件读取还涉及到缓存等细节,这里就不展开讲述了。关于用户空间、内核空间以及硬件等的关系如果读者不理解的话,可以通过钓鱼的例子理解。

钓鱼的时候,刚开始鱼是在鱼塘里面的,我们的钓鱼动作的最终结束标志是鱼从鱼塘中被我们钓上来,放入鱼篓中。

这里面的鱼塘就可以映射成磁盘,中间过渡的鱼钩可以映射成内核空间,最终放鱼的鱼篓可以映射成用户空间。一次完整的钓鱼(IO)操作,是鱼(文件)从鱼塘(硬盘)中转移(拷贝)到鱼篓(用户空间)的过程。

阻塞IO模型
我们钓鱼的时候,有一种方式比较惬意,比较轻松,那就是我们坐在鱼竿面前,这个过程中我们什么也不做,双手一直把着鱼竿,就静静的等着鱼儿咬钩。一旦手上感受到鱼的力道,就把鱼钓起来放入鱼篓中。然后再钓下一条鱼。

映射到Linux操作系统中,这就是一种最简单的IO模型,即阻塞IO。 阻塞 I/O 是最简单的 I/O 模型,一般表现为进程或线程等待某个条件,如果条件不满足,则一直等下去。条件满足,则进行下一步操作。

应用进程通过系统调用 recvfrom 接收数据,但由于内核还未准备好数据报,应用进程就会阻塞住,直到内核准备好数据报,recvfrom 完成数据报复制工作,应用进程才能结束阻塞状态。

这种钓鱼方式相对来说比较简单,对于钓鱼的人来说,不需要什么特制的鱼竿,拿一根够长的木棍就可以悠闲的开始钓鱼了(实现简单)。缺点就是比较耗费时间,比较适合那种对鱼的需求量小的情况(并发低,时效性要求低)。

非阻塞IO模型
我们钓鱼的时候,在等待鱼儿咬钩的过程中,我们可以做点别的事情,比如玩一把王者荣耀、看一集《延禧攻略》等等。但是,我们要时不时的去看一下鱼竿,一旦发现有鱼儿上钩了,就把鱼钓上来。

映射到Linux操作系统中,这就是非阻塞的IO模型。应用进程与内核交互,目的未达到之前,不再一味的等着,而是直接返回。然后通过轮询的方式,不停的去问内核数据准备有没有准备好。如果某一次轮询发现数据已经准备好了,那就把数据拷贝到用户空间中。

应用进程通过 recvfrom 调用不停的去和内核交互,直到内核准备好数据。如果没有准备好,内核会返回error,应用进程在得到error后,过一段时间再发送recvfrom请求。在两次发送请求的时间段,进程可以先做别的事情。

这种方式钓鱼,和阻塞IO比,所使用的工具没有什么变化,但是钓鱼的时候可以做些其他事情,增加时间的利用率。

这样确实好了一点了。鱼儿上钩之前我可以去淘宝挑两条裙子。

信号驱动IO模型
我们钓鱼的时候,为了避免自己一遍一遍的去查看鱼竿,我们可以给鱼竿安装一个报警器。当有鱼儿咬钩的时候立刻报警。然后我们再收到报警后,去把鱼钓起来。

映射到Linux操作系统中,这就是信号驱动IO。应用进程在读取文件时通知内核,如果某个 socket 的某个事件发生时,请向我发一个信号。在收到信号后,信号对应的处理函数会进行后续处理。

应用进程预先向内核注册一个信号处理函数,然后用户进程返回,并且不阻塞,当内核数据准备就绪时会发送一个信号给进程,用户进程便在信号处理函数中开始把数据拷贝的用户空间中。

这种方式钓鱼,和前几种相比,所使用的工具有了一些变化,需要有一些定制(实现复杂)。但是钓鱼的人就可以在鱼儿咬钩之前彻底做别的事儿去了。等着报警器响就行了。

嗯,这种方式最轻松啦。

IO复用模型
我们钓鱼的时候,为了保证可以最短的时间钓到最多的鱼,我们同一时间摆放多个鱼竿,同时钓鱼。然后哪个鱼竿有鱼儿咬钩了,我们就把哪个鱼竿上面的鱼钓起来。

映射到Linux操作系统中,这就是IO复用模型。多个进程的IO可以注册到同一个管道上,这个管道会统一和内核进行交互。当管道中的某一个请求需要的数据准备好之后,进程再把对应的数据拷贝到用户空间中。

IO多路转接是多了一个select函数,多个进程的IO可以注册到同一个select上,当用户进程调用该select,select会监听所有注册好的IO,如果所有被监听的IO需要的数据都没有准备好时,select调用进程会阻塞。当任意一个IO所需的数据准备好之后,select调用就会返回,然后进程在通过recvfrom来进行数据拷贝。

这里的IO复用模型,并没有向内核注册信号处理函数,所以,他并不是非阻塞的。进程在发出select后,要等到select监听的所有IO操作中至少有一个需要的数据准备好,才会有返回,并且也需要再次发送请求去进行文件的拷贝。

这种方式的钓鱼,通过增加鱼竿的方式,可以有效的提升效率。

为什么以上四种都是同步的
我们说阻塞IO模型、非阻塞IO模型、IO复用模型和信号驱动IO模型都是同步的IO模型。原因是因为,无论以上那种模型,真正的数据拷贝过程,都是同步进行的。

信号驱动难道不是异步的么? 信号驱动,内核是在数据准备好之后通知进程,然后进程再通过recvfrom操作进行数据拷贝。我们可以认为数据准备阶段是异步的,但是,数据拷贝操作是同步的。所以,整个IO过程也不能认为是异步的。

你呦把我绕懵了,你还是拿钓鱼来说吧。

我们把钓鱼过程,可以拆分为两个步骤:1、鱼咬钩(数据准备)。2、把鱼钓起来放进鱼篓里(数据拷贝)。无论以上提到的哪种钓鱼方式,在第二步,都是需要人主动去做的,并不是鱼竿自己完成的。所以,这个钓鱼过程其实还是同步进行的。

这和烧水有啥区别,你不是告诉我安装报警器的水壶是异步的吗?

同样是报警器,烧水和钓鱼的是两回事。

烧水的报警器一响,整个烧水过程就完成了。水已经是开水了。

钓鱼的报警器一响,只能说明鱼儿已经咬钩了,但是还没有真正的钓上来。

所以 ,使用带有报警器的水壶烧水,烧水过程是异步的。

而使用带有报警器的鱼竿钓鱼,钓鱼的过程还是同步的。

异步IO模型
我们钓鱼的时候,采用一种高科技钓鱼竿,即全自动钓鱼竿。可以自动感应鱼上钩,自动收竿,更厉害的可以自动把鱼放进鱼篓里。然后,通知我们鱼已经钓到了,他就继续去钓下一条鱼去了。

映射到Linux操作系统中,这就是异步IO模型。应用进程把IO请求传给内核后,完全由内核去操作文件拷贝。内核完成相关操作后,会发信号告诉应用进程本次IO已经完成。

用户进程发起aio_read操作之后,给内核传递描述符、缓冲区指针、缓冲区大小等,告诉内核当整个操作完成时,如何通知进程,然后就立刻去做其他事情了。当内核收到aio_read后,会立刻返回,然后内核开始等待数据准备,数据准备好以后,直接把数据拷贝到用户控件,然后再通知进程本次IO已经完成。

这种方式的钓鱼,无疑是最省事儿的。啥都不需要管,只需要交给鱼竿就可以了。

介绍完这些之后,我默默的删掉了之前写好的那句面试评价『对Linux的基本IO模型理解不深』,改成了『对IO体系理解的不够深入,只会使用封装好的API』。

七层网络协议

我们都知道互联网的本质是一系列的网络协议,这个协议就叫做OSI协议。按照功能不同分工不同,认为的分为七层。实际上这七层是并不存在的,也就是说没有这些概念,而我们今天提到的七层概念,只是人为的划分而已。目的只是为了让大家更好地理解这些都是用来做什么的。

从专业的角度来说,OSI就是一个开放的通信系统互联参考模型,也是一个定义的很好的协议规范。OSI模型有7层结构,每层都可以有几个子层。OSI的7层从下到上分别是7-应用层、6-表示层、5-会话层、4-传输层、3-网络层、2-数据链路层、1-物理层。

1. 七层协议详解

物理层:是参考模型的最低层。该层是网络通信的数据传输介质,由连接不同结点的电缆与设备共同构成。主要跟功能是:利用传输介质为数据链路层提供物理连接,负责处理数据传输并监控数据出错率,以便数据流的透明传输。

数据链路层:是参考模型的第二层。主要功能是:在物理层提供的服务基础上,在通信的实体间建立数据链路连接,传输以“帧”为单位的数据包,并采用差错控制与流量控制方法,使有差错的物理线路变成无差错的数据链路。

网络层:是参考模型的第三层。主要功能是:为数据在节点之间传输创建逻辑链路,通过路由选择算法为分组通过通信子网选择最适当的路径,以及实现拥塞控制、网络互连等功能。

传输层:是参考模型的第四层。主要功能是:向用户提供可靠地端到端服务,处理数据包错误、数据包次序,以及其他一些关键传输问题。传输层向高层屏蔽了下层数据通信的细节。因此,它是计算机通信体系结构中关键的一层。

会话层:是参考模型的第五层。主要功能是:负责维扩两个结点之间的传输连接,以便确保点到点传输不中断,以及管理数据交换等功能。

表示层:是参考模型的第六层。主要功能是:用于处理在两个通信系统中交换信息的表示方法,主要包括数据格式变换、数据加密与解密、数据压缩与恢复等功能。

应用层:是参考模型的最高层。主要功能是:为应用软件提供了很多服务,比如文件服务器、数据库服务、电子邮件与其他网络软件服务。

  1. OSI历史

忘记告诉大家,这个协议是从下到上倒推出来的。

我们来回顾一下这段有趣的历史吧~

OSI模型最初是因为美国人的两台机器之间有进行通信的需求。

需求1:两个硬件之间如何进行通信,具体就是一台发比特流,另一台能够收到。于是就有了物理层:主要是定义设备标准,如网线的额接口类型、管线的接口类型、各种传输介质的传输速率等。它的主要租用是传输比特流,就是从1/0转化为电流强弱来进行传输,到达目的之后再转化为1/0,也就是我们常说的数模转换。这一层的数据是比特。

需求2:现在通过电线我能发数据流了,但是我还是希望能通过无线电波,通过其他介质来进行传输。然后我还要保证传输过去的比特流是正确的,需要由纠正错误的功能。

数据链路层:定义了如何让格式化数据进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。

需求3:现在我能发正确的比特流数据到另一台计算机了,但是当我发大量数据的时候,可能需要很长时间,例如:一个视频格式的,网络会中断好多次,实际上,即使有了物理层和数据链路层,网络还是经常中断,只是中断的时间是毫秒级别的。

那么,我还需要保证传输大量文件时的准确性。于是,我要对发出去的数据进行封装。就像发快递一样,一个个发送。

于是,发明了传输层(传输层在OSI模型中,是在网络层面上)。

比如TCP,是用于发送大量数据的,我发出去一万个包,另一台电脑就需要告诉我是否接收到一万个包,如果缺少3个包,就告诉我是第1001/234/8888个包丢了,那我再发一次。这样,就能保证对方把这个视频完整接收了。

例如UDP,适用于发送少量数据的。我发20个包出去,一般不会丢包,所以 ,我不管你收到多少,在多人互动游戏中,也经常受到UDP协议,因为一般都是简单的额信息,而且有广播的需求。如果用TCP,效率就会很低,因为它会不停地告诉主机我收到20个包,或者18个包,再发我两个!如果同时有1万台计算机都这样做,那么用TCP反而会降低效率,还不如用UDP,主机发出去就算了,丢几个包就卡一下,算了,下次再发包更新。

TCP协议是会绑定IP和端口的协议,下面会介绍IP协议。

需求4:传输层是解决了打包的问题。但是如果我有多台计算机,怎么能找到我要发的那台?或者A要给F发信息,中间要经过B/C/D/E,但是中间还有好多节点,如K/J/Z/Y.我怎么选择最佳路径?这就是路由要做的事情。

于是,发明了网络层,也就是路由器,交换那些具有寻址功能的设备所实现的功能。这一层定义的是IP复制,通过IP地址寻址,所以产生了协议。

需求5:现在已经能够给指定计算机发送正确的封装过的信息了,但是用户级别的体验并不是很好?难道我每次都要调用TCP去打包,然后调用IP协议去找路由,自己去发?当然不行,所以我们要建立一个自动收发包,自动寻址的功能。

于是发明了会话层。会话层的作用就是建立和管理应用程序之间的通信。

需求6:现在我能保证应用程序自动收发包和寻址了,但是我要用Linux给window发包,两个系统语法不一致,就像安装包一样,EXE不能在Linux下用,shell在window也也是不能直接运行的。

于是需要表示层,帮我们解决不同系统之间的通信语法问题。

需求7:现在所有必要条件都准备好了,我们可以写个Android程序,web程序去实现需求吧。

补充:不知道有没有小伙伴熟悉Socket,这不是一个协议,而是一个通信模型。其实它最初是伯克利加州分校软件研究所,简称BSD发明的,主要是一台电脑两个进程之间进行通信,然后把它用到两台电脑的进程间通信。所以,可以把它简单理解为进程间通信,不是什么高级的东西,主要是这么做的:A发包:发请求包给某个已经绑定的端口;收到B的允许后,正式开始发送,发送完了,高速B要断开连接;收到断开允许后,马上断开,然后发送已经断开信息给B。

B收包:绑定端口和IP,然后在这个端口监听接收到A的请求,发给A,并做好接收准备,主要就是清理缓存等待接收新数据;然后正式接收,接收到断开请求,并允许断开,确认断开后,继续监听其他请求。

换句话说,socket就是I/O操作,socket并不仅限于网络通信。在网络通信中,它涵盖了网络层、传输层、会话层、表示层、应用层。

  1. OSI七层协议中每一层的特征

第一层:物理层

机械性能:接口的形状,尺寸的大小,引脚的数目和排列方式等;

电气性能:接口规定信号的电压、电流、阻抗、波形、速率好平衡特性等;

工程规范:接口引脚的意义、特性、标准。

工作方式:确定数据位流的传输方式,如:半双工、全双工等。

物理层协议:美国电子工业协会(EIA)的RS232/RS422/RS423等;

国际电报电话咨询委员会(CCITT)的X.25/X.21等;

物理层的数据单位是位(BIT),典型设备时集线器HUB。

这主要是和硬件有关,与软件关系不大。

第二层:链路层

链路层屏蔽传输介质的物理特征,使数据可靠传送。

内容包括介质访问控制、连接控制、顺序控制、流量控制、差错控制和仲裁协议等。

链路层协议有:协议有面向字符的通讯协议(PPP)和面向位的通讯协议(HDLC)。

仲裁协议:CSMA/CD(Carrier Sense Multiple Access with Collision Detection)、Token Bus、Token Ring

链路层数据单位是帧,实现对MAC地址的访问,典型设备是交换机SWITCH。

第三层:网络层

网络层管理连接方式和路由选择。

连接方式:虚电路和数据报服务。

虚电路是面向连接的,数据通讯一次路由,通过会话建立的一条通路。数据报是非连接的,每个数据报都有路由能力。网络层的数据单位是包,使用的是IP地址,典型设备时路由器Router。

这一层可以进行流量控制,但流量控制更多的是使用第二层或第四层。

第四层:传输层

提供端到端的服务,可以实现流量控制、负载均衡。

传输层信息包括端口、控制字和校验和。

传输层协议主要是TCP和UDP。

传输层位于OSI的第四层,这层使用的设备时主机本身。

第五层:会话层

会话层主要内容时通过 绘画进行身份验证、绘画管理和确定通讯方式。一旦建立连接,会话层的任务就是管理会话。

第六层:表示层

表示层主要是解释通讯数据的意义,如代码转换、格式变换等,使不同的终端可以表示。

还包括加密与解密、压缩与解压等。

第七层:应用层

应用层应该是直接面向用户的程序或服务,包括系统程序和用户程序,比如www、FTP、DNS、POP3和SMTP等都是应用层服务。

数据再发送时是数据从应用层至物理层的一个大包的过程,接收时是数据从物理层至应用层的一个解包过程。

从功能角度可以分为三组:1/2层解决网络通信问题,3/4层解决传输问题,5/6/7层处理对应用进程的访问。

从控制角度可分为二组:1/2/3层是通信子网,4/5/6/7是主机控制层。

今天之所以会分享一下这种文章,是因为有小伙伴问小编能不能解释一下网络7层协议之间的关系,所以就整理了这么一篇文章,感觉有用的小伙伴记得关注、转发或收藏哦~如果觉得还有什么疑惑,还请在留言区留言,小编看到或者其他小伙伴看到也会及时给出回复的。

单工,半双工,全双工区别

  1. 单工
    单工就是指A只能发信号,而B只能接收信号,通信是单向的,就象灯塔之于航船——灯塔发出光信号而航船只能接收信号以确保自己行驶在正确的航线上。
  2. 半双工
    指一个时间段内只有一个动作发生,举个简单例子,一天窄窄的马路,同时只能有一辆车通过,当目前有两量车对开,这种情况下就只能一辆先过,等到头儿后另一辆再开,这个例子就形象的说明了半双工的原理。早期的对讲机、以及早期集线器等设备都是实行半双工的产品。随着技术的不断进步,半双工会逐渐退出历史舞台。
  3. 全双工
    Full-Duplex Transmissions
    交换机在发送数据的同时也能够接收数据,两者同步进行,这好像我们平时打电话一样,说话的同时也能够听到对方的声音。目前的交换机都支持全双工。

项目架构中引入MQ的优劣(假想接口操作为写库)

  1. 优势,主要有3方面:
    • 解耦:如果A服务的一个接口需要调用B、C、D、E…..系统的对应接口,将数据推送给其它系统,如果采用接口调用,这需要在A的接口中同步(或异步线程)调用其它系统接口。
      如果后续其中某一个系统不需要这个数据了,则需要修改A服务的接口;而且A服务需要考虑如果数据没有推送到其它系统或个别系统的接口调用超时等情况,需要采取什么措施进行弥补,系统之间耦合性很高。采用MQ,A服务只需要将数据成功推送给MQ后,就不用关心谁去消费它,降低系统之间的耦合性。
    • 异步:场景同上,假设A本身接口调用时间50ms,B、C、D、E…接口调用时间为200ms、240ms、200ms、100ms….那么A接口调用响应时间至少为790ms,响应时间要比本接口响应时间高很多,如果这些接口本身不需要同步调用,即A服务不需要关心其它系统的接口调用结果,此时将数据成功推送到MQ之后,A服务该接口就可以直接返回,可以降低系统接口的响应时间,提高系统的响应能力。
    • 削峰:假设A服务某接口平时每秒并发为500,系统承受最大并发为1000,但是在特定时间,系统的每秒并发在2000,系统承受不了这么多的并发,很容易造成系统瘫痪。如果采用MQ进行请求排队,设定系统每秒处理消息数,可以降低系统瘫痪的可能性。
  2. 劣势,主要有3方面:
    • 系统可用性降低:原来系统只有A、B、C、D、E….系统,只需要保证他们的可用性就行了,但是现在引入了MQ后,又需要确保MQ的高可用,否则系统就不能正常提供服务。
    • 系统复杂性提高:原来的系统之间直接进行接口调用就行了,现在引入了MQ之后,需要学习使用MQ的API,还需要额外部署MQ实例,还要考虑MQ的高可用、如何防止消息的重复消费、如何保证消息的正确投递和保证消费以及消息传递的顺序性……
    • 一致性问题:以前A服务直接调用其它系统的接口,可以拿到同步结果,知道其它系统的处理结果,此时整体系统的数据是一致的。引入MQ之后,A服务成功推送数据到MQ,但是不知道其它系统是否处理了、即使处理了但是也不知道是否成功,如果没有处理或者没有处理成功,那此时的数据和没有引入MQ之前的数据出现了不一致。

现在主流的MQ之间区别

特性 ActiveMQ RabbitMQ RocketMQ Kafka
单机吞吐量 万级 万级 10万级,RocketMQ也是可以支撑高吞吐的一种MQ 10万级别,这是kafka最大的优点,就是吞吐量高。
topic数量对吞吐量的影响 topic可以达到几百,几千个的级别,吞吐量会有较小幅度的下降;这是RocketMQ的一大优势,在同等机器下,可以支撑大量的topic topic从几十个到几百个的时候,吞吐量会大幅度下降;所以在同等机器下,kafka尽量保证topic数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源
时效性 ms级 微秒级,这是rabbitmq的一大特点,延迟是最低的 ms级 延迟在ms级以内
可用性 高,基于主从架构实现高可用性 高,基于主从架构实现高可用性 非常高,分布式架构 非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
消息可靠性 有较低的概率丢失数据 经过参数优化配置,可以做到0丢失 经过参数优化配置,可以做到0丢失
功能支持 MQ领域的功能极其完 基于erlang开发,所以并发能力很强,性能极其好,延时很低,功能较为完善 MQ功能较为完善,还是分布式的,扩展性好 早期版本功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准
优劣势总结 非常成熟,功能强大,在业内大量的公司以及项目中都有应用;偶尔会有较低概率丢失消息;而且现在社区以及国内应用都越来越少,官方社区现在对ActiveMQ 5.x维护越来越少,几个月才发布一个版本;而且确实主要是基于解耦和异步来用的,较少在大规模吞吐的场景中使用 erlang语言开发,性能极其好,延时很低;吞吐量到万级,MQ功能比较完备;而且开源提供的管理界面非常棒,用起来很好用;社区相对比较活跃,几乎每个月都发布几个版本分;在国内一些互联网公司近几年用rabbitmq也比较多一些;但是问题也是显而易见的,RabbitMQ确实吞吐量会低一些,这是因为他做的实现机制比较重。而且erlang开发,国内有几个公司有实力做erlang源码级别的研究和定制?如果说你没这个实力的话,确实偶尔会有一些问题,你很难去看懂源码,你公司对这个东西的掌控很弱,基本职能依赖于开源社区的快速维护和修复bug。而且rabbitmq集群动态扩展会很麻烦,不过这个我觉得还好。其实主要是erlang语言本身带来的问题。很难读源码,很难定制和掌控。 接口简单易用,而且毕竟在阿里大规模应用过,有阿里品牌保障;日处理消息上百亿之多,可以做到大规模吞吐,性能也非常好,分布式扩展也很方便,社区维护还可以,可靠性和可用性都是ok的,还可以支撑大规模的topic数量,支持复杂MQ业务场景;而且一个很大的优势在于,阿里出品都是java系的,我们可以自己阅读源码,定制自己公司的MQ,可以掌控;社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准JMS规范走的有些系统要迁移需要修改大量代码;还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ挺好的 kafka的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展;同时kafka最好是支撑较少的topic数量即可,保证其超高吞吐量;而且kafka唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略;这个特性天然适合大数据实时计算以及日志收集

综上进行,个人倾向:
  一般的业务系统在选择MQ的时候,早期选用的大多数都是ActiveMQ,但是其社区不够活跃,随之大家开始使用RabbitMQ,虽然RabbitMQ是开源的,社区活跃度也高,但是因为采用erlang语言开发,对于java工程师深入研究还是带来了不小的阻碍。最近这几年国内的公司大多数都开始尝试使用RocketMQ,据了解阿里双11内部的消息队列就是基于RocketMQ优化的,经历过大规模并发测试。而kafka基本都是用于大数据领域的实时计算、日志采集等场景。
  所以小公司,技术研究能力较为一般的,采用RabbitMQ也是不错的选择,社区支持和文档都不错,国内也有不少大规模使用的案例;而对于中大型公司,架构人员以及研发人员都有着不弱实力,尝试使用RocketMQ是更好的选择。针对于大数据等场景,基本不用考虑,直接采用Kakfa。

什么是幂等性(Idempotence)?

“幂等”这个词原是数学领域中的概念,指的是某些操作或函数能够被执行多次,但每次得到的结果都是不变的。我来举几个简单的例子说明一下。比如在乘法运算中,让数字乘以 1 就是一个幂等操作,因为不管你执行多少次这样的运算,结果都是相同的。再比如,取整函数(floor 和 ceiling)是幂等函数,那么运行 1 次 floor(3.4) 和 100 次 floor(3.4),结果是一样的,都是 3。相反地,让一个数加 1 这个操作就不是幂等的,因为执行一次和执行多次的结果必然不同。在计算机领域中,幂等性的含义稍微有一些不同:在命令式编程语言(比如 C)中,若一个子程序是幂等的,那它必然不能修改系统状态。这样不管运行这个子程序多少次,与该子程序关联的那部分系统状态保持不变。在函数式编程语言(比如 Scala 或 Haskell)中,很多纯函数(pure function)天然就是幂等的,它们不执行任何的 side effect。

批处理和流处理

大数据是收集、整理、处理大容量数据集,并从中获得见解所需的非传统战略和技术的总称。虽然处理数据所需的计算能力或存储容量早已超过一台计算机的上限,但这种计算类型的普遍性、规模,以及价值在最近几年才经历了大规模扩展。

本文将介绍大数据系统一个最基本的组件:处理框架。处理框架负责对系统中的数据进行计算,例如处理从非易失存储中读取的数据,或处理刚刚摄入到系统中的数据。数据的计算则是指从大量单一数据点中提取信息和见解的过程。

下文将介绍这些框架:

仅批处理框架:

Apache Hadoop

仅流处理框架:

Apache Storm

Apache Samza

混合框架:

Apache Spark

Apache Flink

批处理系统

批处理在大数据世界有着悠久的历史。批处理主要操作大容量静态数据集,并在计算过程完成后返回结果。

批处理模式中使用的数据集通常符合下列特征…

  • 有界:批处理数据集代表数据的有限集合

  • 持久:数据通常始终存储在某种类型的持久存储位置中

  • 大量:批处理操作通常是处理极为海量数据集的唯一方法

批处理非常适合需要访问全套记录才能完成的计算工作。例如在计算总数和平均数时,必须将数据集作为一个整体加以处理,而不能将其视作多条记录的集合。这些操作要求在计算进行过程中数据维持自己的状态。

需要处理大量数据的任务通常最适合用批处理操作进行处理。无论直接从持久存储设备处理数据集,或首先将数据集载入内存,批处理系统在设计过程中就充分考虑了数据的量,可提供充足的处理资源。由于批处理在应对大量持久数据方面的表现极为出色,因此经常被用于对历史数据进行分析。

大量数据的处理需要付出大量时间,因此批处理不适合对处理时间要求较高的场合。
Apache Hadoop
Apache Hadoop是一种专用于批处理的处理框架。Hadoop是首个在开源社区获得极大关注的大数据框架。基于谷歌有关海量数据处理所发表的多篇论文与经验的Hadoop重新实现了相关算法和组件堆栈,让大规模批处理技术变得更易用。

新版Hadoop包含多个组件,即多个层,通过配合使用可处理批数据:

HDFS:HDFS是一种分布式文件系统层,可对集群节点间的存储和复制进行协调。HDFS确保了无法避免的节点故障发生后数据依然可用,可将其用作数据来源,可用于存储中间态的处理结果,并可存储计算的最终结果。

YARN:YARN是Yet Another Resource Negotiator(另一个资源管理器)的缩写,可充当Hadoop堆栈的集群协调组件。该组件负责协调并管理底层资源和调度作业的运行。通过充当集群资源的接口,YARN使得用户能在Hadoop集群中使用比以往的迭代方式运行更多类型的工作负载。

MapReduce:MapReduce是Hadoop的原生批处理引擎。

批处理模式
Hadoop的处理功能来自MapReduce引擎。MapReduce的处理技术符合使用键值对的map、shuffle、reduce算法要求。基本处理过程包括:

从HDFS文件系统读取数据集

将数据集拆分成小块并分配给所有可用节点

针对每个节点上的数据子集进行计算(计算的中间态结果会重新写入HDFS)

重新分配中间态结果并按照键进行分组

通过对每个节点计算的结果进行汇总和组合对每个键的值进行“Reducing”

将计算而来的最终结果重新写入 HDFS

优势和局限
由于这种方法严重依赖持久存储,每个任务需要多次执行读取和写入操作,因此速度相对较慢。但另一方面由于磁盘空间通常是服务器上最丰富的资源,这意味着MapReduce可以处理非常海量的数据集。同时也意味着相比其他类似技术,Hadoop的MapReduce通常可以在廉价硬件上运行,因为该技术并不需要将一切都存储在内存中。MapReduce具备极高的缩放潜力,生产环境中曾经出现过包含数万个节点的应用。

MapReduce的学习曲线较为陡峭,虽然Hadoop生态系统的其他周边技术可以大幅降低这一问题的影响,但通过Hadoop集群快速实现某些应用时依然需要注意这个问题。

围绕Hadoop已经形成了辽阔的生态系统,Hadoop集群本身也经常被用作其他软件的组成部件。很多其他处理框架和引擎通过与Hadoop集成也可以使用HDFS和YARN资源管理器。

总结
Apache Hadoop及其MapReduce处理引擎提供了一套久经考验的批处理模型,最适合处理对时间要求不高的非常大规模数据集。通过非常低成本的组件即可搭建完整功能的Hadoop集群,使得这一廉价且高效的处理技术可以灵活应用在很多案例中。与其他框架和引擎的兼容与集成能力使得Hadoop可以成为使用不同技术的多种工作负载处理平台的底层基础。

流处理系统

流处理系统会对随时进入系统的数据进行计算。相比批处理模式,这是一种截然不同的处理方式。流处理方式无需针对整个数据集执行操作,而是对通过系统传输的每个数据项执行操作。

流处理中的数据集是“无边界”的,这就产生了几个重要的影响:

  • 完整数据集只能代表截至目前已经进入到系统中的数据总量。

  • 工作数据集也许更相关,在特定时间只能代表某个单一数据项。

  • 处理工作是基于事件的,除非明确停止否则没有“尽头”。处理结果立刻可用,并会随着新数据的抵达继续更新。

流处理系统可以处理几乎无限量的数据,但同一时间只能处理一条(真正的流处理)或很少量(微批处理,Micro-batch Processing)数据,不同记录间只维持最少量的状态。虽然大部分系统提供了用于维持某些状态的方法,但流处理主要针对副作用更少,更加功能性的处理(Functional processing)进行优化。

功能性操作主要侧重于状态或副作用有限的离散步骤。针对同一个数据执行同一个操作会或略其他因素产生相同的结果,此类处理非常适合流处理,因为不同项的状态通常是某些困难、限制,以及某些情况下不需要的结果的结合体。因此虽然某些类型的状态管理通常是可行的,但这些框架通常在不具备状态管理机制时更简单也更高效。

此类处理非常适合某些类型的工作负载。有近实时处理需求的任务很适合使用流处理模式。分析、服务器或应用程序错误日志,以及其他基于时间的衡量指标是最适合的类型,因为对这些领域的数据变化做出响应对于业务职能来说是极为关键的。流处理很适合用来处理必须对变动或峰值做出响应,并且关注一段时间内变化趋势的数据。

Apache Storm

Apache Storm是一种侧重于极低延迟的流处理框架,也许是要求近实时处理的工作负载的最佳选择。该技术可处理非常大量的数据,通过比其他解决方案更低的延迟提供结果。

流处理模式

Storm的流处理可对框架中名为Topology(拓扑)的DAG(Directed Acyclic Graph,有向无环图)进行编排。这些拓扑描述了当数据片段进入系统后,需要对每个传入的片段执行的不同转换或步骤。

拓扑包含:

  • Stream:普通的数据流,这是一种会持续抵达系统的无边界数据。

  • Spout:位于拓扑边缘的数据流来源,例如可以是API或查询等,从这里可以产生待处理的数据。

  • Bolt:Bolt代表需要消耗流数据,对其应用操作,并将结果以流的形式进行输出的处理步骤。Bolt需要与每个Spout建立连接,随后相互连接以组成所有必要的处理。在拓扑的尾部,可以使用最终的Bolt输出作为相互连接的其他系统的输入。

Storm背后的想法是使用上述组件定义大量小型的离散操作,随后将多个组件组成所需拓扑。默认情况下Storm提供了“至少一次”的处理保证,这意味着可以确保每条消息至少可以被处理一次,但某些情况下如果遇到失败可能会处理多次。Storm无法确保可以按照特定顺序处理消息。

为了实现严格的一次处理,即有状态处理,可以使用一种名为Trident的抽象。严格来说不使用Trident的Storm通常可称之为Core Storm。Trident会对Storm的处理能力产生极大影响,会增加延迟,为处理提供状态,使用微批模式代替逐项处理的纯粹流处理模式。

为避免这些问题,通常建议Storm用户尽可能使用Core Storm。然而也要注意,Trident对内容严格的一次处理保证在某些情况下也比较有用,例如系统无法智能地处理重复消息时。如果需要在项之间维持状态,例如想要计算一个小时内有多少用户点击了某个链接,此时Trident将是你唯一的选择。尽管不能充分发挥框架与生俱来的优势,但Trident提高了Storm的灵活性。

Trident拓扑包含:

  • 流批(Stream batch):这是指流数据的微批,可通过分块提供批处理语义。

  • 操作(Operation):是指可以对数据执行的批处理过程。

    优势和局限

目前来说Storm可能是近实时处理领域的最佳解决方案。该技术可以用极低延迟处理数据,可用于希望获得最低延迟的工作负载。如果处理速度直接影响用户体验,例如需要将处理结果直接提供给访客打开的网站页面,此时Storm将会是一个很好的选择。

Storm与Trident配合使得用户可以用微批代替纯粹的流处理。虽然借此用户可以获得更大灵活性打造更符合要求的工具,但同时这种做法会削弱该技术相比其他解决方案最大的优势。话虽如此,但多一种流处理方式总是好的。

Core Storm无法保证消息的处理顺序。Core Storm为消息提供了“至少一次”的处理保证,这意味着可以保证每条消息都能被处理,但也可能发生重复。Trident提供了严格的一次处理保证,可以在不同批之间提供顺序处理,但无法在一个批内部实现顺序处理。

在互操作性方面,Storm可与Hadoop的YARN资源管理器进行集成,因此可以很方便地融入现有Hadoop部署。除了支持大部分处理框架,Storm还可支持多种语言,为用户的拓扑定义提供了更多选择。

总结

对于延迟需求很高的纯粹的流处理工作负载,Storm可能是最适合的技术。该技术可以保证每条消息都被处理,可配合多种编程语言使用。由于Storm无法进行批处理,如果需要这些能力可能还需要使用其他软件。如果对严格的一次处理保证有比较高的要求,此时可考虑使用Trident。不过这种情况下其他流处理框架也许更适合。

Apache Samza

Apache Samza是一种与Apache Kafka消息系统紧密绑定的流处理框架。虽然Kafka可用于很多流处理系统,但按照设计,Samza可以更好地发挥Kafka独特的架构优势和保障。该技术可通过Kafka提供容错、缓冲,以及状态存储。

Samza可使用YARN作为资源管理器。这意味着默认情况下需要具备Hadoop集群(至少具备HDFS和YARN),但同时也意味着Samza可以直接使用YARN丰富的内建功能。

流处理模式

Samza依赖Kafka的语义定义流的处理方式。Kafka在处理数据时涉及下列概念:

  • Topic(话题):进入Kafka系统的每个数据流可称之为一个话题。话题基本上是一种可供消耗方订阅的,由相关信息组成的数据流。

  • Partition(分区):为了将一个话题分散至多个节点,Kafka会将传入的消息划分为多个分区。分区的划分将基于键(Key)进行,这样可以保证包含同一个键的每条消息可以划分至同一个分区。分区的顺序可获得保证。

  • Broker(代理):组成Kafka集群的每个节点也叫做代理。

  • Producer(生成方):任何向Kafka话题写入数据的组件可以叫做生成方。生成方可提供将话题划分为分区所需的键。

  • Consumer(消耗方):任何从Kafka读取话题的组件可叫做消耗方。消耗方需要负责维持有关自己分支的信息,这样即可在失败后知道哪些记录已经被处理过了。

由于Kafka相当于永恒不变的日志,Samza也需要处理永恒不变的数据流。这意味着任何转换创建的新数据流都可被其他组件所使用,而不会对最初的数据流产生影响。

优势和局限

乍看之下,Samza对Kafka类查询系统的依赖似乎是一种限制,然而这也可以为系统提供一些独特的保证和功能,这些内容也是其他流处理系统不具备的。

例如Kafka已经提供了可以通过低延迟方式访问的数据存储副本,此外还可以为每个数据分区提供非常易用且低成本的多订阅者模型。所有输出内容,包括中间态的结果都可写入到Kafka,并可被下游步骤独立使用。

这种对Kafka的紧密依赖在很多方面类似于MapReduce引擎对HDFS的依赖。虽然在批处理的每个计算之间对HDFS的依赖导致了一些严重的性能问题,但也避免了流处理遇到的很多其他问题。

Samza与Kafka之间紧密的关系使得处理步骤本身可以非常松散地耦合在一起。无需事先协调,即可在输出的任何步骤中增加任意数量的订阅者,对于有多个团队需要访问类似数据的组织,这一特性非常有用。多个团队可以全部订阅进入系统的数据话题,或任意订阅其他团队对数据进行过某些处理后创建的话题。这一切并不会对数据库等负载密集型基础架构造成额外的压力。

直接写入Kafka还可避免回压(Backpressure)问题。回压是指当负载峰值导致数据流入速度超过组件实时处理能力的情况,这种情况可能导致处理工作停顿并可能丢失数据。按照设计,Kafka可以将数据保存很长时间,这意味着组件可以在方便的时候继续进行处理,并可直接重启动而无需担心造成任何后果。

Samza可以使用以本地键值存储方式实现的容错检查点系统存储数据。这样Samza即可获得“至少一次”的交付保障,但面对由于数据可能多次交付造成的失败,该技术无法对汇总后状态(例如计数)提供精确恢复。

Samza提供的高级抽象使其在很多方面比Storm等系统提供的基元(Primitive)更易于配合使用。目前Samza只支持JVM语言,这意味着它在语言支持方面不如Storm灵活。

总结

对于已经具备或易于实现Hadoop和Kafka的环境,Apache Samza是流处理工作负载一个很好的选择。Samza本身很适合有多个团队需要使用(但相互之间并不一定紧密协调)不同处理阶段的多个数据流的组织。Samza可大幅简化很多流处理工作,可实现低延迟的性能。如果部署需求与当前系统不兼容,也许并不适合使用,但如果需要极低延迟的处理,或对严格的一次处理语义有较高需求,此时依然适合考虑。

混合处理系统:批处理和流处理

一些处理框架可同时处理批处理和流处理工作负载。这些框架可以用相同或相关的组件和API处理两种类型的数据,借此让不同的处理需求得以简化。

如你所见,这一特性主要是由Spark和Flink实现的,下文将介绍这两种框架。实现这样的功能重点在于两种不同处理模式如何进行统一,以及要对固定和不固定数据集之间的关系进行何种假设。

虽然侧重于某一种处理类型的项目会更好地满足具体用例的要求,但混合框架意在提供一种数据处理的通用解决方案。这种框架不仅可以提供处理数据所需的方法,而且提供了自己的集成项、库、工具,可胜任图形分析、机器学习、交互式查询等多种任务。

Apache Spark

Apache Spark是一种包含流处理能力的下一代批处理框架。与Hadoop的MapReduce引擎基于各种相同原则开发而来的Spark主要侧重于通过完善的内存计算和处理优化机制加快批处理工作负载的运行速度。

Spark可作为独立集群部署(需要相应存储层的配合),或可与Hadoop集成并取代MapReduce引擎。

批处理模式

与MapReduce不同,Spark的数据处理工作全部在内存中进行,只在一开始将数据读入内存,以及将最终结果持久存储时需要与存储层交互。所有中间态的处理结果均存储在内存中。

虽然内存中处理方式可大幅改善性能,Spark在处理与磁盘有关的任务时速度也有很大提升,因为通过提前对整个任务集进行分析可以实现更完善的整体式优化。为此Spark可创建代表所需执行的全部操作,需要操作的数据,以及操作和数据之间关系的Directed Acyclic Graph(有向无环图),即DAG,借此处理器可以对任务进行更智能的协调。

为了实现内存中批计算,Spark会使用一种名为Resilient Distributed Dataset(弹性分布式数据集),即RDD的模型来处理数据。这是一种代表数据集,只位于内存中,永恒不变的结构。针对RDD执行的操作可生成新的RDD。每个RDD可通过世系(Lineage)回溯至父级RDD,并最终回溯至磁盘上的数据。Spark可通过RDD在无需将每个操作的结果写回磁盘的前提下实现容错。

流处理模式

流处理能力是由Spark Streaming实现的。Spark本身在设计上主要面向批处理工作负载,为了弥补引擎设计和流处理工作负载特征方面的差异,Spark实现了一种叫做微批(Micro-batch)*的概念。在具体策略方面该技术可以将数据流视作一系列非常小的“批”,借此即可通过批处理引擎的原生语义进行处理。

Spark Streaming会以亚秒级增量对流进行缓冲,随后这些缓冲会作为小规模的固定数据集进行批处理。这种方式的实际效果非常好,但相比真正的流处理框架在性能方面依然存在不足。

优势和局限

使用Spark而非Hadoop MapReduce的主要原因是速度。在内存计算策略和先进的DAG调度等机制的帮助下,Spark可以用更快速度处理相同的数据集。

Spark的另一个重要优势在于多样性。该产品可作为独立集群部署,或与现有Hadoop集群集成。该产品可运行批处理和流处理,运行一个集群即可处理不同类型的任务。

除了引擎自身的能力外,围绕Spark还建立了包含各种库的生态系统,可为机器学习、交互式查询等任务提供更好的支持。相比MapReduce,Spark任务更是“众所周知”地易于编写,因此可大幅提高生产力。

为流处理系统采用批处理的方法,需要对进入系统的数据进行缓冲。缓冲机制使得该技术可以处理非常大量的传入数据,提高整体吞吐率,但等待缓冲区清空也会导致延迟增高。这意味着Spark Streaming可能不适合处理对延迟有较高要求的工作负载。

由于内存通常比磁盘空间更贵,因此相比基于磁盘的系统,Spark成本更高。然而处理速度的提升意味着可以更快速完成任务,在需要按照小时数为资源付费的环境中,这一特性通常可以抵消增加的成本。

Spark内存计算这一设计的另一个后果是,如果部署在共享的集群中可能会遇到资源不足的问题。相比Hadoop MapReduce,Spark的资源消耗更大,可能会对需要在同一时间使用集群的其他任务产生影响。从本质来看,Spark更不适合与Hadoop堆栈的其他组件共存一处。

总结

Spark是多样化工作负载处理任务的最佳选择。Spark批处理能力以更高内存占用为代价提供了无与伦比的速度优势。对于重视吞吐率而非延迟的工作负载,则比较适合使用Spark Streaming作为流处理解决方案。

Apache Flink

Apache Flink是一种可以处理批处理任务的流处理框架。该技术可将批处理数据视作具备有限边界的数据流,借此将批处理任务作为流处理的子集加以处理。为所有处理任务采取流处理为先的方法会产生一系列有趣的副作用。

这种流处理为先的方法也叫做Kappa架构,与之相对的是更加被广为人知的Lambda架构(该架构中使用批处理作为主要处理方法,使用流作为补充并提供早期未经提炼的结果)。Kappa架构中会对一切进行流处理,借此对模型进行简化,而这一切是在最近流处理引擎逐渐成熟后才可行的。

流处理模型

Flink的流处理模型在处理传入数据时会将每一项视作真正的数据流。Flink提供的DataStream API可用于处理无尽的数据流。Flink可配合使用的基本组件包括:

  • Stream(流)是指在系统中流转的,永恒不变的无边界数据集

  • Operator(操作方)是指针对数据流执行操作以产生其他数据流的功能

  • Source(源)是指数据流进入系统的入口点

  • Sink(槽)是指数据流离开Flink系统后进入到的位置,槽可以是数据库或到其他系统的连接器

为了在计算过程中遇到问题后能够恢复,流处理任务会在预定时间点创建快照。为了实现状态存储,Flink可配合多种状态后端系统使用,具体取决于所需实现的复杂度和持久性级别。

此外Flink的流处理能力还可以理解“事件时间”这一概念,这是指事件实际发生的时间,此外该功能还可以处理会话。这意味着可以通过某种有趣的方式确保执行顺序和分组。

批处理模型

Flink的批处理模型在很大程度上仅仅是对流处理模型的扩展。此时模型不再从持续流中读取数据,而是从持久存储中以流的形式读取有边界的数据集。Flink会对这些处理模型使用完全相同的运行时。

Flink可以对批处理工作负载实现一定的优化。例如由于批处理操作可通过持久存储加以支持,Flink可以不对批处理工作负载创建快照。数据依然可以恢复,但常规处理操作可以执行得更快。

另一个优化是对批处理任务进行分解,这样即可在需要的时候调用不同阶段和组件。借此Flink可以与集群的其他用户更好地共存。对任务提前进行分析使得Flink可以查看需要执行的所有操作、数据集的大小,以及下游需要执行的操作步骤,借此实现进一步的优化。
优势和局限

Flink目前是处理框架领域一个独特的技术。虽然Spark也可以执行批处理和流处理,但Spark的流处理采取的微批架构使其无法适用于很多用例。Flink流处理为先的方法可提供低延迟,高吞吐率,近乎逐项处理的能力。

Flink的很多组件是自行管理的。虽然这种做法较为罕见,但出于性能方面的原因,该技术可自行管理内存,无需依赖原生的Java垃圾回收机制。与Spark不同,待处理数据的特征发生变化后Flink无需手工优化和调整,并且该技术也可以自行处理数据分区和自动缓存等操作。

Flink会通过多种方式对工作进行分许进而优化任务。这种分析在部分程度上类似于SQL查询规划器对关系型数据库所做的优化,可针对特定任务确定最高效的实现方法。该技术还支持多阶段并行执行,同时可将受阻任务的数据集合在一起。对于迭代式任务,出于性能方面的考虑,Flink会尝试在存储数据的节点上执行相应的计算任务。此外还可进行“增量迭代”,或仅对数据中有改动的部分进行迭代。

在用户工具方面,Flink提供了基于Web的调度视图,借此可轻松管理任务并查看系统状态。用户也可以查看已提交任务的优化方案,借此了解任务最终是如何在集群中实现的。对于分析类任务,Flink提供了类似SQL的查询,图形化处理,以及机器学习库,此外还支持内存计算。

Flink能很好地与其他组件配合使用。如果配合Hadoop 堆栈使用,该技术可以很好地融入整个环境,在任何时候都只占用必要的资源。该技术可轻松地与YARN、HDFS和Kafka 集成。在兼容包的帮助下,Flink还可以运行为其他处理框架,例如Hadoop和Storm编写的任务。

目前Flink最大的局限之一在于这依然是一个非常“年幼”的项目。现实环境中该项目的大规模部署尚不如其他处理框架那么常见,对于Flink在缩放能力方面的局限目前也没有较为深入的研究。随着快速开发周期的推进和兼容包等功能的完善,当越来越多的组织开始尝试时,可能会出现越来越多的Flink部署。

总结

Flink提供了低延迟流处理,同时可支持传统的批处理任务。Flink也许最适合有极高流处理需求,并有少量批处理任务的组织。该技术可兼容原生Storm和Hadoop程序,可在YARN管理的集群上运行,因此可以很方便地进行评估。快速进展的开发工作使其值得被大家关注。

TPS 、QPS、BPS、RPS的含义

  • TPS
    Transactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数。TPS包括一条消息入和一条消息出,加上一次用户数据库访问。(业务TPS = CAPS × 每个呼叫平均TPS)

TPS是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。

一般的,评价系统性能均以每秒钟完成的技术交易的数量来衡量。系统整体处理能力取决于处理能力最低模块的TPS值。

  • QPS
    每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。

对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。

系统吞吐量几个重要参数:QPS(TPS)、并发数、响应时间

    QPSTPS):每秒钟request/事务 数量

    并发数: 系统同时处理的request/事务数

    响应时间:  一般取平均响应时间

(很多人经常会把并发数和TPS理解混淆)

在计算机网络或者是网络运营商中,一般,宽带速率的单位用bps(或b/s)表示;bps表示比特每秒即表示每秒钟传输多少位信息,是bit per second的缩写。

在实际所说的1M带宽的意思是1Mbps(是兆比特每秒Mbps不是兆字节每秒MBps)。

建议用户记住以下换算公式:
1B=8b 1B/s=8b/s(或1Bps=8bps)
1KB=1024B 1KB/s=1024B/s
1MB=1024KB 1MB/s=1024KB/s
规范提示:
实际书写规范中B应表示Byte(字节),b应表示bit(比特),但在平时的实际书写中有的把bit和Byte都混写为b ,如把Mb/s和MB/s都混写为Mb/s,导致人们在实际计算中因单位的混淆而出错。切记注意!!!

(1)关于bit(比特)/second(秒)与Byte(字节)/s(秒)的换算说明:线路单位是bps,表示bit(比特)/second(秒),注意是小写字母b;用户在网上下载时显示的速率单位往往是Byte(字节)/s(秒),注意是大写字母B。字节和比特之间的关系为1Byte=8Bits;再加上IP包头、HTTP包头等因网络传输协议增加的传输量,显示1KByte/s下载速率时,线路实际传输速率约10kbps。例如:下载显示是50KByte/s时,实际已经达到了500Kbps的速度。切记注意单位!!!

包转发率标志了交换机转发数据包能力的大小。单位一般位pps(包每秒),

一般交换机的包转发率在几十Kpps到几百Mpps不等。包转发速率是指交换机每秒可以转发多少百万个数据包(Mpps),即交换机能同时转发的数据包的数量。

  • TPS

Transactions Per Second的缩写,也就是事务数/秒。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。

  • RPS

Requests Per Second的缩写,每秒能处理的请求数目。

1、Tps即每秒处理事务数,包括了

1)用户请求服务器

2)服务器自己的内部处理

3)服务器返回给用户

这三个过程,每秒能够完成N个这三个过程,Tps也就是N;

2、Qps基本类似于Tps,但是不同的是,对于一个页面的一次访问,形成一个Tps;但一次页面请求,可能产生多次对服务器的请求,服务器对这些请求,就可计入“Qps”之中。

布隆过滤器

布隆过滤器(BloomFilter)是一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 某样东西一定不存在或者可能存在,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间,但是布隆过滤器也存在一定的缺陷:数据只能插入不能删除。
布隆过滤器的底层实现是位图。

布隆过滤器的插入与查找

布隆过滤器的插入

布隆过滤器是由一个很长的bit数组和一系列哈希函数组成的。结构如下:
在这里插入图片描述
数组的每个元素都只占1bit空间,并且每个元素只能为0或1。

布隆过滤器还拥有k个哈希函数,当一个元素加入布隆过滤器时,会使用k个哈希函数对其进行k次计算,得到k个哈希值,并且根据得到的哈希值,在数组中把对应下标的值置位1。

例:“baidu”这个值对应的三个不同的哈希函数返回三个哈希值分别为:1 、4 、7,则将其对应的下标置1,其结构就会变成下面这样:
在这里插入图片描述

布隆过滤器的查找

布隆过滤器的思想将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特位一定为1.

所以在查询某个是否存在时,若该值利用三个不同的哈希函数返回的哈希值对应的下标至少有一个为0,则说明该值一定不存在,若对应的值均为1,说明该值可能存在。

为什么说是可能存在而不是一定存在呢?
因为可能会出现不同的值利用哈希函数返回的哈希值对应的下标相同,所以说只能得出可能存在的结果,即某些哈希函数存在一定误判。

2.3 布隆过滤器产生误判的原因

当插入的元素越来越多时,当一个不在布隆过滤器中的元素,经过同样规则的哈希计算之后,得到的值在数组中查询,有可能这些位置因为其他的元素先被置1了。

所以布隆过滤器存在误判的情况,但是如果布隆过滤器判断某个元素不在布隆过滤器中,那么这个值就一定不在。

3、布隆过滤器的删除

在介绍布隆过滤器的概念时提到布隆过滤器的缺点是不支持删除,但是它不支持删除的原因是什么呢?
因为删除一个元素时可能会影响到其他元素。

举个例子:“baidu”利用三个不同的哈希函数返回的哈希值为1,4,7,“tencent”利用三个不同的哈希函数返回的哈希值为3,4,8,假设删除“baidu”这个元素,则1,4,7对应的下标置0,但是“tencent”这个元素与“baidu”对应的下标4重合,这样就会将“tencent”这个元素也删除,所以布隆过滤器不支持删除。

一种支持删除的方法:将布隆过滤器中的每个比特位扩展成一个小的计数器,插入元素时给k个计数器(k个哈希函数计算出的哈希地址)加一,删除元素时,给k个计数器减一,通过多占用几倍存储空间的代价来增加删除操作。

但是这中删除方法也存在一定缺陷:

  1. 无法确认元素是否真正在布隆过滤器中
  2. 存在计数回绕

4、布隆过滤器优点

  1. 增加和查询元素的时间复杂度为:O(K), (K为哈希函数的个数,一般比较小),与数据量大小无关

  2. 哈希函数相互之间没有关系,方便硬件并行运算

  3. 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势

  4. 在能够承受一定的误判时,布隆过滤器比其他数据结构有这很大的空间优势

  5. 数据量很大时,布隆过滤器可以表示全集,其他数据结构不能

  6. 使用同一组散列函数的布隆过滤器可以进行交、并、差运算

    5、布隆过滤器缺陷

  7. 有误判率,即存在假阳性(False Position),即不能准确判断元素是否在集合中(补救方法:再建立一个白名单,存储可能会误判的数据)

  8. 不能获取元素本身

  9. 一般情况下不能从布隆过滤器中删除元素

  10. 如果采用计数方式删除,可能会存在计数回绕问题

    6、使用场景

  11. 网页爬虫对URL的去重,避免爬去相同的URL地址。

  12. 垃圾邮件过滤,从数十亿个垃圾邮件列表中判断某邮箱是否是杀垃圾邮箱。

  13. 解决数据库缓存击穿,黑客攻击服务器时,会构建大量不存在于缓存中的key向服务器发起请求,在数据量足够大的时候,频繁的数据库查询会导致挂机。

  14. 秒杀系统,查看用户是否重复购买。

7、海量数据应用例题

  1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法?
    思路:精确算法利用位图来实现
    近似算法利用布隆过滤器实现,将一个文件的中100亿个query放在一个布隆过滤器中,另个一个文件中的数据到布隆过滤器中去查找,若查找到则说明是这两个文件的交集。

字节bai、字、位、比特之间的关系

1位=1比特;zhi1字=2字节;1字节=8位;1字=16位。

1、位

位是计算机存储的dao最小单位,简记为b,也称为比特(bit)计算机中用二进制中的0和1来表示数据,一个0或1就代表一位。位数通常指计算机中一次能处理的数据大小;

2、比特

比特(bit)是由英文BIT音译而来,比特同时也是二进制数字中的位,是信息量的度量单位,为信息量的最小单位;

3、字节

字节,英文Byte,是计算机用于计量存储容量的一种计量单位,通常情况下一字节等于八位,字节同时也在一些计算机编程语言中表示数据类型和语言字符,在现代计算机中,一个字节等于八位;

4、字

字是表示计算机自然数据单位的术语,在某个特定计算机中,字是其用来一次性处理事务的一个固定长度的位(bit)组,在现代计算机中,一个字等于两个字节。

MySQL中数据类型字节长度

1.字符串

  • char(n): n 字节长度

  • varchar(n): 如果是 utf8 编码, 则是 3 n + 2字节; 如果是 utf8mb4 编码, 则是 4 n + 2 字节.

2.数值类型:

  • TINYINT: 1字节

  • SMALLINT: 2字节

  • MEDIUMINT: 3字节

  • INT: 4字节

  • BIGINT: 8字节

3.时间类型

  • DATE: 3字节

  • TIMESTAMP: 4字节

  • DATETIME: 8字节

4.字段属性: NULL 属性 占用一个字节. 如果一个字段是 NOT NULL 的, 则没有此属性.

负载均衡算法及技术

  • 介绍

现有的负载均衡算法主要分为静态和动态两类。静态负载均衡算法以固定的概率分配任务,不考虑服务器的状态信息,如轮转算法、加权轮转算法等;动态负载均衡算法以服务器的实时负载状态信息来决定任务的分配,如最小连接法、加权最小连接法等。^ [2]^

  • 分类

1、轮询法

轮询法,就是将用户的请求轮流分配给服务器,就像是挨个数数,轮流分配。这种算法比较简单,他具有绝对均衡的优点,但是也正是因为绝对均衡它必须付出很大的代价,例如它无法保证分配任务的合理性,无法根据服务器承受能力来分配任务。

2、随机法

随机法,是随机选择一台服务器来分配任务。它保证了请求的分散性达到了均衡的目的。同时它是没有状态的不需要维持上次的选择状态和均衡因子[5]。但是随着任务量的增大,它的效果趋向轮询后也会具有轮询算法的部分缺点。

3、最小连接法

最小连接法,将任务分配给此时具有最小连接数的节点,因此它是动态负载均衡算法。一个节点收到一个任务后连接数就会加1,当节点故障时就将节点权值设置为0,不再给节点分配任务。

最小连接法适用于各个节点处理的性能相似时。任务分发单元会将任务平滑分配给服务器。但当服务器性能差距较大时,就无法达到预期的效果。因为此时连接数并不能准确表明处理能力,连接数小而自身性能很差的服务器可能不及连接数大而自身性能极好的服务器。所以在这个时候就会导致任务无法准确的分配到剩余处理能力强的机器上。^ [2]^

  • 均衡技术

常见的软件负载均衡技术有以下几种:

1、基于DNS的负载均衡

由于在DNS服务器中,可以为多个不同的地址配置相同的名字,最终查询这个名字的客户机将在解析这个名

字时得到其中一个地址,所以这种代理方式是通过DNS服务中的随机名字解析域名和IP来实现负载均衡。

2、反向代理负载均衡(如Apache+JK2+Tomcat这种组合)

该种代理方式与普通的代理方式不同,标准代理方式是客户使用代理访问多个外部Web服务器,之所以被称为反向代理模式是因为这种代理方式是多个客户使用它访问内部Web服务器,而非访问外部服务器。

3、基于NAT(Network Address Translation)的负载均衡技术(如Linux VirtualServer,简称LVS)

该技术通过一个地址转换网关将每个外部连接均匀转换为不同的内部服务器地址,因此外部网络中的计算机就各自与自己转换得到的地址上的服务器进行通信,从而达到负载均衡的目的。其中网络地址转换网关位于外部地址和内部地址之间,不仅可以实现当外部客户机访问转换网关的某一外部地址时可以转发到某一映射的内部的地址上,还可使内部地址的计算机能访问外部网络。

一致性哈希算法

一致性哈希算法是1997年在论文Consistenthashingandrandomtrees中被提出,在分布式系统中应用非常广泛。一致性哈希是一种哈希算法,简单地说在移除或者添加一个服务器时,此算法能够尽可能小地改变已存在的服务请求与处理请求服务器之间的映射关系,尽可能满足单调性的要求。在普通分布式集群中,服务请求与处理请求服务器之间可以一一对应,也就是说固定服务请求与处理服务器之间的映射关系,某个请求由固定的服务器去处理。这种方式无法对整个系统进行负载均衡,可能会造成某些服务器过于繁忙以至于无法处理新来的请求。而另一些服务器则过于空闲,整体系统的资源利用率低,并且当分布式集群中的某个服务器宕机,会直接导致某些服务请求无法处理 。

进一步的改进可以利用hash算法对服务请求与处理服务器之间的关系进行映射,以达到动态分配的目的。通过hash算法对服务请求进行转换,转换后的结果对服务器节点值进行取模运算,取模后的值就是服务请求对应的请求处理服务器。这种方法可以应对节点失效的情况,当某个分布式集群节点宕机,服务请求可以通过hash算法重新分配到其他可用的服务器上。避免了无法处理请求的状况出现 。

但这种方法的缺陷也很明显,如果服务器中保存有服务请求对应的数据,那么如果重新计算请求的hash值,会造成大量的请求被重定位到不同的服务器而造成请求所要使用的数据失效,这种情况在分布式系统中是非常糟糕的。一个设计良好的分布式系统应该具有良好的单调性,即服务器的添加与移除不会造成大量的哈希重定位,而一致性哈希恰好可以解决这个问题。

一致性哈希算法将整个哈希值空间映射成一个虚拟的圆环,整个哈希空间的取值范围为0~ 232-1。整个空间按顺时针方向组织。0~ 232-1在零点中方向重合。接下来使用如下算法对服务请求进行映射,将服务请求使用哈希算法算出对应的hash值,然后根据hash值的位置沿圆环顺时针查找,第一台遇到的服务器就是所对应的处理请求服务器。当增加一台新的服务器,受影响的数据仅仅是新添加的服务器到其环空间中前一台的服务器(也就是顺着逆时针方向遇到的第一台服务器)之间的数据,其他都不会受到影响。综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

特点:

可扩展性。一致性哈希算法保证了增加或减少服务器时,数据存储的改变最少,相比传统哈希算法大大节省了数据移动的开销。

更好地适应数据的快速增长。采用一致性哈希算法分布数据,当数据不断增长时,部分虚拟节点中可能包含很多数据、造成数据在虚拟节点上分布不均衡,此时可以将包含数据多的虚拟节点分裂,这种分裂仅仅是将原有的虚拟节点一分为二、不需要对全部的数据进行重新哈希和划分。虚拟节点分裂后,如果物理服务器的负载仍然不均衡,只需在服务器之间调整部分虚拟节点的存储分布。这样可以随数据的增长而动态的扩展物理服务器的数量,且代价远比传统哈希算法重新分布所有数据要小很多。

CSV格式

1. CSV的全称是叫Comma Separated Value
2. CSV的MIME类型是text/csv
3 CSV文件中的每一行数据,作为一行记录,也就是一个条目(99%的情况,排除有些换行数据,下面会提到)
4. CSV文件的每一行数据后面跟着(回车+换行符)即CRLF,但有些资料中也提到了单个CR或者LF均可,但标准rfc文档中用到的是CR+LF
5. 文件第一行可以是标题行,这个用到的不多
6. 每行数据中,每个字段之间均必须用半角逗号comma进行分隔,这也是为什么叫Comma Separated的来由,如果有标题行,那么标题之间也使用逗号分隔
7 每行的最后一个字段后应该只有CRLF,不应该再有逗号
8. 最后一行后面可以不加CRLF
9. 在逗号分隔开的每个字段中,前面的空白和后面的空白会被忽略,但单个字段内部的空白会被保留,例如, aaa, bbb bbb ,ccc 我们看到有三个字段,其中第二个字段前面,中间,后面均有空白,但CSV解析器应该只保留中间的空白,即bbb bbb,类似于Java中的trim方法
10. 如果某个字段中间有回车换行之类的字符,可以用双引号来引用,例如:

[plain] view plain copy

  1. “aaa”,”b CRLF

  2. bb”,”ccc” CRLF

  3. zzz,yyy,xxx

    那么可以判断出第二个字段之间内部存在一个回车换行符,由于使用双引号分隔,他们b 和 bb 被链接成一个字段
    11. 字段本身推荐使用双引号来引用,但MS的excel默认是不会对字段加” “的
    12. 转义字符逗号(,),当字段中存在逗号是,是必须要将这个字段用””引用起来的
    13. 转移字符双引号(“),当字段中存在双引号时,必须连续用两个双引号来进行转义

CAP 理论

CAP 理论指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性:在分布式环境中,一致性是指数据在多个副本之间是否能够保持一致的特性,等同于所有节点访问同一份最新的数据副本。在一致性的需求下,当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。

  • 可用性:每次请求都能获取到正确的响应,但是不保证获取的数据为最新数据。

  • 分区容错性:分布式系统在遇到任何网络分区故障的时候,仍然需要能够保证对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障。

一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

BASE 理论

BASE 是 Basically Available(基本可用)、Soft-state(软状态) 和 Eventually Consistent(最终一致性) 三个短语的缩写。

  • 基本可用:在分布式系统出现故障,允许损失部分可用性(服务降级、页面降级)。

  • 软状态:允许分布式系统出现中间状态。而且中间状态不影响系统的可用性。这里的中间状态是指不同的 data replication(数据备份节点)之间的数据更新可以出现延时的最终一致性。

  • 最终一致性:data replications 经过一段时间达到一致性。

BASE 理论是对 CAP 中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。

本作品采用《CC 协议》,转载必须注明作者和本文链接
你还差得远呐!
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!