《分布式与云计算课程笔记》——第三章、进程

目录

一、线程

1、 多线程服务器的介绍

2、线程的实现方式

3、在客户端如何使用线程

4、多线程服务器构造:Master/slave模型   Dispatcher/worker model

二、虚拟化

1、虚拟化的好处:

2、什么是虚拟化,即虚拟化和抽象的关系

 三、客户端

四、服务器端


一、线程

1、 多线程服务器的介绍

最开始回顾处理器、进程、线程之间的联系/区别,主要关注的是上下文,即上下文切换。

  • 处理器上下文
  • 线程上下文
  • 进程上下文 

我们需要知道的是,线程上下文包含处理器上下文和一些线程状态相关的值,而进程上下文子在此基础上包含更多。因此线程对比进程会更加轻量级,上下文切换的花费更少。注意,线程的上下文切换可以实现独立于操作系统。

总结一下使用线程的好处:

  • 1. 避免不必要的阻塞:单线程进程在执行I/O时会阻塞;在多线程进程中,操作系统可以将CPU切      换到该进程中的另一个线程。
  • 2. 增加并行性:多线程进程中的线程可以安排在多核处理器上并行运行。

下面是熟知的多进程服务器和多线程服务器:

  • 多线程服务器:web服务器、java服务器
  • 多进程服务器:unix、数据库服务器

多进程服务器往往以进程池的方式出现,即池化pooling,意味着多进程服务器上下文比较大,所以进程的创建和销毁比较消耗资源,代价大。池化的好处就是节省时间,反应及时,效率高,坏处是内存开销大,因此来看,这也是为什么数据库服务器往往内存较大。

多线程服务器会给每一个用户创建并发线程,为用户服务,结束后该线程销毁,线程thread共享地址空间、共享代码段数据段,且独立于操作系统 independent of the operating system。线程的上下文切换跟操作系统是独立的,而进程是和操作系统有关的,因此进程切换需要陷入操作系统内核,相对代价比较大;线程不需要,代价小,所以相比之下多线程服务器更有优势。

2、线程的实现方式

线程有两种实现方式:

  1. 在用户空间实现线程(操作系统不支持线程)
  2. 在内核空间实现线程(由操作系统实现)

用户空间实现线程好处:

  1. 可以在操作系统不支持线程的情况下实现线程(比如unix是多进程操作系统,不支持线程,如果在unix机器上安装java服务器,实现多线程应用),对内核屏蔽
  2. 多线程切换、线程管理在用户空间实现,不需要操作系统介入,效率高
  3. 相对来说可靠性高、安全性高,可以提供更好的而理性,不会因为应用的bug导致整个系统的崩溃(比如java应用如果崩了,操作系统不会被影响)(很重要!)

第三点提到了一个很重要的内容:应用隔离。现在大多都是多用户多应用系统,所以应用不影响别的应用实际很重要,多提一嘴,虚拟机的一个非常重要的好处就是可以提供非常高的隔离性,所以现在好多云计算就是在虚拟机上跑的。

用户空间实现线程坏处:

如果使用线程进行内核操作,性能非常差。比如一个多线程应用需要进行磁盘IO(由操作系统的实现,不是用户程序能够做的,必须要陷入操作系统内核才能做磁盘IO,即调用系统调用),必然导致阻塞,因为磁盘IO对比CPU运算慢很多。多线程按理说可以进程内部切换线程,但因为底层内核不支持线程,所以不是对线程阻塞,而是对进程阻塞,导致无法做到进程内部线程切换。

由于操作系统不支持线程,带来的后果就是无法对线程进行管理,任何陷入内核的操作都会阻塞整个进程,所以效率下降。

而内核空间实现多线程管理(即操作系统是多线程操作系统)就正好和用户空间反过来,坏处就是所有线程管理由操作系统做,操作系统负担加大,效率降低。

结合两种方法的坏处和好处,所以会有一个想法:结合用户空间+内核空间=混合式,即轻量级进程 Lightweight processes can execute user-level threads.

说来有趣,这里的思想也类似于第二章分布式架构那里,集中式+分布式→混合式(标准混合式:集中式用来负责查询,分布式用来实现数据交换),但和架构不同的是,此处使用混合式导致的复杂性超过了带来的收益。

轻量级进程是由sun公司[1]  提出来的,一个标准的unix服务器[2] ,解决了进程和进程间映射造成的阻塞,但出现一个问题,就是无法切换回来,切换回来时无法通知进程,sun公司的实现结果是,通过upcall实现线程切换回去,此处为下层调用上层,严重增加了系统的复杂性。因为本身分层结构应该事先上层对下层透明,但是操作系统是完整的,所以下层调用上层技术也是可以实现的。但有趣的是在做实验时,实验性能相比于用户空间和内核空间来说是最差的,因为优化仅针对阻塞的那一种情况,但是系统跑的时候本不知道上层应用到底是什么,复杂度大且最终性能低,所以完全不能商用。

3、在客户端如何使用线程

在客户端使用线程很常见,目的就是追求并发,以及加速。

例子:web浏览器、RPC调用。Web浏览器如果访问某一个html文件,就是一个标准的并发过程,有多个线程同时下载fetch多个文件,所以浏览器打开页面时一个完整的页面是并发出来的。

在服务端使用线程,目的:提高系统可扩展性和性能,并发线程越多可以响应更多用户请求。 

4、多线程服务器构造:Master/slave模型   Dispatcher/worker model

并行parallel:一般在共享内存机器上实现多个线程/进程。可以通过在共享内存中设置同步变量,通过进程/线程操作同步变量来实现同步,更简单。

并发Concurrency:完全分布式系统,不考虑共享内存。开发并发程序最大的难点:(只要涉及交互)进程/线程同步(比如进程ABC需要共同做什么,A先完成,要等B、C) ,相比并行,并发的相当麻烦,需要通过通讯(阻塞)。如果设计不好会阻塞很久,效率难提升;同步由程序员实现。

重点来了,这里介绍一个现代企业应用中对用得最广泛的多线程服务器构造,这种模式是分布式系统里用的最多的,完美的绕开了并发的问题,云计算中MapReduce用的也是这种方式。

Dispacher只做一件事:在服务器监听端口监听用户请求,一旦监听到用户请求,dispatch生成一个新的线程去完成用户请求,然后返回继续监听。每一个用户的请求都是由一个独立的线程去响应。所以效率非常高,因为用户请求响应很快,而不是做完一个响应一个排队等待,并发响应。比如一个16核的机器,就可以同时响应16个用户。因此完全并发,不存在同步问题,即不需要同步,也不需要通讯。

好处:线程之间没有通讯,唯一的通讯就是dispatch创建的时候和返回结果的时候,效率非常高。现在服务器一般来讲都是采用类似这样的结构。

二、虚拟化

这一章最重要的是虚拟化,也是云计算的基础,书上内容比较少,因此把云计算虚拟化的提到前面补充一下 ,一般来讲云计算都是虚拟化的。

1、虚拟化的好处:

虚拟化的目的:

  • 1、希望通过虚拟化让软件不留意硬件的变化(因为硬件的更新变化比软件快很多)
  • 2、可移植性 portability
  • 3、隔离性 Isolation

虚拟化最早是IBM提出来的,目的仅是第一个,随着虚拟化的发展,后来2 3 的好处就出现了

Portability:可携带性;和硬件无关。现在的应用系统都是一个依赖一个,依赖很多东西。操作系统、数据库、数据、依赖包。如何提高:用虚拟机。虚拟机实际以虚拟文件的形式存在,所有的东西全部放在虚拟文件,换句话说原来装的这么多东西实际是一个重叠的虚拟文件,所以只把虚拟文件拷贝过去,网络传播都可以,再一run就行。代价是:本来一个很小的应用,但虚拟文件都是即G的,毕竟所有的东西都在里面。

Isolation:隔离性:两个应用有交叉的越多隔离性越不好。完全互不相干隔离型好。

举例:分析Windows应用和linux应用哪个隔离性更好:

Windows是一个很内核的系统,整个图形界面都属于内核系统的一部分,整个windows的内核很庞大,所有的界面都属于内核的一部分。应用都要有图形化界面,所以应用会大量进性内核操作。一个程序出问题整个机子全部死机了。

Linux内核很小,用户界面不属于内核,所以应用隔离性很好。

虚拟机的隔离性就很好:应用在虚拟机上是完全单独的(操作系统到,,,都是单独的),另一个应用也是,完全无关。甚至有的硬件也是无关的,不同应用使用不同段的内存,两个之间互相不重叠,比Linux隔离性更好。因为Linux不同用户空间在内存上可能没有隔离,所以可能内存溢出,或者相互影响,读写东西。虚拟机有最高的安全隔离性

复杂的环境下只能Check off 权衡:

标准虚拟机:VMWare或者开源的openstack,都是完整的虚拟机,实现从头到尾的隔离。但谷歌开源的docker(现在很多应用都是在docker上开发的,和openstack用户数差不多),docker是轻量级的,区别是在于openstack是在openstack上装操作系统,而docker是在linux系统上装docker。所以两者是反过来的,docker会调用linux的某些API,所以隔离性不如overstack好,但轻量级得多。最小的docker的应用可能只有几K,overstack都是几百M到G。所以具体看选择,愿意牺牲什么愿意提升什么,即Check off。

2、什么是虚拟化,即虚拟化和抽象的关系

虚拟化:

  • 虚拟化最重要的特征:mimick 模仿
  • 例如需要在电脑开发安卓应用:Android studio
  • 虚拟化是模仿,把A看成B,比如虚拟机

抽象

  • 即抽象一个接口出来,掩盖下层具体实现,即从A B C中提取共性,抽象一个接口出来,例如抽象数据库、文件系统抽象一个接口用来数据存取。
  • 抽取相似的本质,掩盖不同。

这里有一个很重要的概念:虚拟化的层级

虚拟化可以在很多层级实现,书上讲的不多,讲到云计算可以看到,比如网络虚拟化、主机虚拟化、内存虚拟化……都有,后面把云计算的虚拟化提到前面来介绍,

这里是服务器/主机虚拟化,不涉及硬件

1. 硬件虚拟化

硬件虚拟化是在硬件上做一层软件,对硬件的访问是通过软件访问,硬件虚拟化是虚拟化中使用最多的方式。

好处:软件想要使用硬件需要驱动程序,最开始是每一次装一个硬件就要装一个驱动程序,后来windows把常见驱动程序全都放进去了,这时候装硬件可以自动识别。如果不用这些,在硬件上装一个虚拟化软件,这个软件也是把所有硬件的驱动放里面了,就一样,没有区别。好实现。但麻烦的是小厂很难实现,需要响应大部分硬件,就需要和厂商有关系,可以响应硬件最新的变化。相对来说是性能最好效率最高的虚拟化方法。所有的虚拟化都是牺牲了性能的吗,硬件虚拟化是损失最低的,能达到原来的90%以上。

现在绝大多数云平添用的都是硬件虚拟化,只有微软用的是操作系统虚拟化

2. 指令集虚拟化

不同的操作系统有不同的指令系统,假如PC的应用在手机上跑,肯定不可以,因为指令集不一样,如果没有源代码,已经安装过了,只想可以运行。只能指令集虚拟化,在指令集层,硬把一个指令翻译成另一个,但是指令集虚拟化的优点很明显,可以在没有源代码的情况下也跑起来,但效率低,而且不是百分百成功,指令集的数量都不一样,如何对的上,可能指令之间一对多,甚至无法对应。一般除非迫不得己,不进行指令集虚拟化,代价太大,效率太低。用的很少。

3. 操作系统虚拟化即虚拟机

:硬件→操作系统→虚拟机→操作系统→应用

最典型是微软,微软的虚拟机是在windows上装虚拟机,然后再装应用。

现在流行的大部分的云平台用的都是硬件虚拟,比如阿里、腾讯、亚马逊等等,基本用的都是硬件虚拟化,只有微软用的是操作系统虚拟化,因为微软的windows已经做好了,所以虚拟化可以调用底层操作系统,相对来说虚拟化比较简单。

4. 在code层次做虚拟化

比如开发应用,一般使用很多库函数,library就是替换库函数。

5. 用户空间虚拟化/应用层

最典型的例子就是java,因为java虚拟机本身也是虚拟机,java运行在用户空间。通常虚拟机都是牺牲性能,提高互操作性/兼容性,java虚拟机性能不高,毕竟是应用层实现的,但追求其跨平台性和兼容性。

除了分层以外还有一个很重要的概念,参数虚拟化Parameter virtualization vs full virtualization

硬件虚拟化,在虚拟化软件上装操作系统,有两种选择:

  • 第一种:完全虚拟化Full virtualization
  • (对windows完全透明)
  • VMware硬件虚拟化软件,然后装windows
  • 第二种:para参数虚拟化 Parameter virtualization
  • 做了优化,针对虚拟化软件做了优化,效率更高,但不完全透明

大部分硬件虚拟化厂商往往提供的都是参数虚拟化,因为效率高,对于用户来讲没有区别。

云计算基本都是采用虚拟化的,云计算本质是建立在虚拟化的基础上

 三、客户端

Client端的软件有很重要分布式透明性的问题:存储、复制、位置等等

分别是存取透明性、位置透明性、复制透明性和失败透明性

四、服务器端

并发服务器:使用dispatcher

1、分布式系统中连接server的优化后过程:动态分配端节点

2、Servers and state

服务器分为stateful有状态服务器和stateless无状态服务器:能否保存/持久化每一个客户的状态,同样javaEE的会话bean分为有状态的会话bean和无状态的会话bean。由于有状态服务器负载大,性能差,所以一般来讲能用无状态就用无状态。

Web服务器是典型的无状态服务器,因为Web服务器最初的目的是实现万维网,最开始应用是静态文本的展示,所以希望提高性能。但随着电子商务的发展,现在是电子商务应用服务器,需要状态,例如买东西的不同客户,但是改造web服务器代价很大,因为全世界web服务器已经定型了,所以用间接的方式改造:session会话,即用各种各样的方式实现数据的保存,但是要注意,不管哪种方法,数据都不在服务器上,因为服务器无状态不保存任何数据(比如cookie保存在客户端)。

3、服务器的三层架构

现在应用最广泛的方式,企业中都采用这种架构,但实现难度很大,因为涉及数据共享的问题

第一层通常负责将请求传递到适当的服务器:请求调度 request dispatching

gateway/switch是网关,负责负载均衡,即只负责server的查找,不负责具体的业务
好处:1. 透明性(用户只看到网关) 2. 负载均衡
但有成为了性能瓶颈

如何避免网关处出现性能瓶颈:

解决办法:修改了TCP协议,进一步降低switch负载,使得Server直接response返回给server,而不是再经过switch,如图所示

注意server cluster集群也是为了避免性能瓶颈。

 


 [1]Java也是sun发明的,Sun公司模式很多,所以很多东西偏理论化,JavaSpring就是MVC架构,思想很先进,但Spring发展也不好,因为很不好用,其实思想很好,但是用起来很繁琐

 [2]服务器一般都是linux/unix,个人机PC都是windows

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日光沉寂的半海21

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值