zoukankan      html  css  js  c++  java
  • 学点虚拟化知识

    虚拟化技术是业务发展到一定阶段,互联网企业必然会使用的技术。

    互联网业务是7*24小时运行的,系统稳定性是生命线。企业为了保障业务稳定性会使用大量服务器,如何有效的提高机器的使用率,让好钢用在刀刃上,对于上层业务无侵入性的虚拟化技术能帮很大忙。

    线上应用各有各的特点:

    • Java应用通常对于CPU要求不高,对于内存会比较高,写IO可能也不会很高,除非业务日志开到debug级别疯狂的写,这在线上是不大可能的。最后对磁盘容量要求很低。

    • 跑数据库的软件,一般CPU也不会很高,对于内存和IO要求会很高,IO要求要远高于Java应用。内存需求一般是由于数据库引擎会尽量将常用数据缓存在内容中提高性能,所以有时候把整张表都放在内存中也是可能,这就要求尽量高的内存。IO更不必说,主要是可能会有大量写,毕竟数据库就是一个保存状态的实体,不可避免的要有大量的状态需要保存。

    • 实时流式计算类,Storm,Spark啥的,通常由于其处理数据的场景会导致吞吐量较大,CPU必然会消耗较大。

    • 离线计算类,Hadoop, 数仓,BI,都是数据处理类,此类应用使用的高峰期有可能是半夜才刚开始。

    以上几种典型应用,可以想象一下,如果同类型的应用都放在同一个集群上,是一种比较大的浪费,web应用的使用是随着人走的,人睡觉了,系统的低峰期就来了,半夜CPU都是闲置的,电还是一样用着;而全是Hadoop的集群半夜才开始吭哧吭哧的处理数据分析的业务;一种很自然的想法就是在集群中去混部各种业务,让优势互补,让机器一直保持在有事干的状态。

    混部当然也有一些问题,例如同一台物理机上A应用被B应用突来的高峰所影响,CPU周期被抢光,莫名其妙的负载升高。混部有时也不是一开始就能规划好的,最好能动态调整,这样就能通过虚拟化技术来做。

    提高硬件使用率的主要思路就是让一个物理服务器上跑多个程序,程序之间需要一种隔离机制来保证大体上互不影响,这里有个悖论,因为我们的目的是提高资源利用率,那么最好让应用互相争抢资源,然而为了稳定性又需要一定程度的资源隔离。

    两种隔离思路

    一 鸠占鹊巢,接管操作系统

    由于计算机历史悠久的分层设计思路,可以想到让程序隔离必然要在操作系统层与应用层之间有一种机制,让应用认为自己在一个独立的操作系统中,而操作系统又要支持让应用互相隔离。那么就要引入一层中间层,这层中间层可以模拟操作系统环境来启动应用,并把应用对操作系统的API调用翻译过来传达给下层实际的操作系统,这就是Xen,KVM的设计思路。

    这样的做法会比较重,因为相当于将操作系统重新封装了一遍。至于为什么要翻译一遍,这是由于虚拟机的操作系统可能是linux的各种方言版本,也有可能是windows,而实际下层提供操作系统服务的宿主系统一般都是同一个linux版本,所以上层虚拟机的各种cpu指令需要通过虚拟层翻译过来传给下层实际的操作系统,这里还会涉及到比较复杂的上层是32位系统,下层是64位系统,连指令集都不一样,这些都会有性能损耗。这就是纯软件模拟的问题, 下图可以解释没有硬件支持的CPU虚拟化时操作系统与程序的关系:

    为了安全,一些特权级指令只允许操作系统发出,普通的应用程序是不允许调用的。但要做到虚拟化,则必然需要将虚拟化软件作为操作系统的底层,让其运行在ring0的模式,而把操作系统运行在ring1模式,这明显会有很多挑战。

    针对这个问题,Intel后期为支持虚拟化增加了VT-x,为CPU的工作模式增加了VMX root operation和VMX non-root operation两种模式。当客户操作系统出现特权指令时提供了机制能退出到根模式,由虚拟机监视器(VMM)来处理。

    二 操作系统支持,隔离进程空间

    Linux认识到了虚拟化的意义,提供了另外一种虚拟化的方式 - LXC(Linux Containers)。 此种思路是操作系统为程序提供虚拟执行空间,可以理解为一种容器,操作系统为要运行在容器中的应用程序提供所需的CPU,内存,网络等底层资源支持,当然,此种方式还能灵活的更改绑定的CPU个数,并能进行CPU超配,提高资源利用率。

    这种模式所有容器内的进程都共享同一个操作系统内核,所以限制也在这里,容器内的进程需要是个linux程序,windows程序用的windows操作系统API在这里是不存在的。

    这里还要提一下Docker,其实看了前面对于LXC的介绍就知道,Docker的进程隔离思路与LXC是一样的,所以Docker早期也是基于LXC开发的。Docker的理念与OO设计中的单一职责一样,容器只支持一个进程,拒绝变成瑞士军刀。

    关于Docker,此处为占位符,下次看看它的设计。虚拟化技术仍在快速发展,应用程序员在写代码时完全不知道另外一批偏硬件,系统开发的程序员做了些什么,各种小小的分工,打造了如今的计算机体系,消费者们也得到了想要的(网络游戏,打车,外卖,搜索)。


    文章来自微信平台「麦芽面包」
    微信公众号「darkjune_think」转载请注明。
    如果觉得有趣,微信扫一扫关注公众号。

  • 相关阅读:
    More Effective C++: 02操作符
    More Effective C++: 01基础议题
    GCD学习(七) dispatch_apply
    GCD学习(六) dispatch_async 和dispatch_sync
    GCD学习(五) dispatch_barrier_async
    GCD 学习(四) dispatch_group
    关于 block的一些浅识
    异常日志记录 DDLog
    Effective Objective-C [下]
    Effective Objective-C [上]
  • 原文地址:https://www.cnblogs.com/zhukunrong/p/5427801.html
Copyright © 2011-2022 走看看