https://blog.csdn.net/ceshi986745/article/details/51787424
为了将咱们的应用部署到服务器上,咱们须要为其配置一个运行环境。从底层到顶层有这样的运行环境及容器:html
-
隔离硬件:虚拟机程序员
-
隔离操做系统:容器虚拟化数据库
-
隔离底层:Servlet容器编程
-
隔离依赖版本:虚拟环境浏览器
-
隔离运行环境:语言虚拟机服务器
-
隔离语言:DSL网络
实现上这是一个请求的处理过程,一个HTTP请求会先到达你的主机。若是你的主机上运行着多个虚拟机实例,那么请求就会来到这个虚拟机上。又或者是若是你是在Docker这一类容器里运行你的程序的话,那么也会先到达Docker。随后这个请求就会交由HTTP服务器来处理,如Apache、Nginx,这些HTTP服务器再将这些请求交由对应的应用或脚原本处理。随后将交由语言底层的指令来处理。 架构
不一样的环境有不一样的选择,固然也能够结合在一块儿。不过,从理论上来讲在最外层仍是应该有一个真机的,可是我想你们都有这个明确的概念,就很少解释了。编程语言
一、隔离硬件(虚拟机)
在虚拟机技术出现以前,为了运行不一样用户的应用程序,人们须要不一样的物理机才能实现这样的需求。对于Web应用程序来讲,有的用户的网站访问量少消耗的系统资源也少,有的用户的网站访问量大消耗的系统资源也多。虽然有不一样的服务器类型能够选择,然而对于多数的访问少的用户来讲他们须要支付一样的费用。这听上去至关的不合理,而且也浪费了大量的资源。而且对于系统管理员来讲,管理这些系统也不是一件容易的事。在过去硬件技术革新特别快,让操做系统运行在不一样的机器上也不是一件容易的事。工具
虚拟机(Virtual Machine)指经过软件模拟的具备完整硬件系统功能的、运行在一个彻底隔离环境中的完整计算机系统。
这是一个颇有意思的技术,它可让咱们在一个主机上同时运行几个不一样的操做系统。咱们能够为这几个操做系统使用不一样的硬件,在这之上的应用可使用不一样的技术栈来运行,而且从理论上互相不影响。其架构以下图所示:
借助于虚拟机技术,当咱们须要更多的资源的时候,建立一个新的虚拟机就好了。同时,因为这些虚拟机上运行的是一样的操做系统,而且可使用相同的配置,咱们只须要编写一些脚本就能够实现其自动化。当咱们的物联机发生问题时,咱们也能够很快将虚拟机迁移或恢复到另外的宿主机。
二、隔离操做系统(容器虚拟化)
对于大部分的开发团队来讲,直接开发基于虚拟机的自动化工具不是一件容易的事,而且他从使用成本上来讲比较高。这时候咱们就须要一些更轻量级的工具容器——它能够提供轻量级的虚拟化,以便隔离进程和资源,并且不须要提供指令解释机制以及全虚拟化的其余复杂性。而且,它从启动速度上来讲更快。
LXC
在介绍Docker以前,咱们仍是稍微提一下LXC。由于在过去我有一些使用LXC的经历,让我以为LXC很赞。
LXC,其名称来自Linux软件容器(Linux Containers)的缩写,一种操做系统层虚拟化(Operating system–level virtualization)技术,为Linux内核容器功能的一个用户空间接口。它将应用软件系统打包成一个软件容器(Container),内含应用软件自己的代码,以及所须要的操做系统核心和库。经过统一的名字空间和共用API来分配不一样软件容器的可用硬件资源,创造出应用程序的独立沙箱运行环境,使得Linux用户能够容易的建立和管理系统或应用容器。
咱们能够将之以上面说到的虚拟机做一个简单的对比,其架构图以下所示:
咱们会发现虚拟机中多了一层Hypervisor——运行在物理服务器和操做系统之间,它可让多个操做系统和应用共享一套基础物理硬件。这一层级能够协调访问服务器上的全部物理设备和虚拟机,然而因为这一层级的存在,它也将消耗更多的能量。据爱立信研究院和阿尔托大学发表的论文表示:Docker、LXC与Xen、KVM在完成相同的工做时要少消耗10%的能耗。
LXC主要是利用cgroups与namespace的功能,来向提供应用软件一个独立的操做系统运行环境。cgroups(即Control Groups)j Linux内核提供的一种能够限制、记录、隔离进程组所使用的物理资源的机制。而由namespace来责任隔离控制。
与虚拟机相比,LXC隔离性方面有所不足,这就意味着在实现可移植部署会遇到一些困难。这时候,咱们就须要Docker来提供一个抽象层,并提供一个管理机制。
Docker
Docker 是一个开源的应用容器引擎,让开发者能够打包他们的应用以及依赖包到一个可移植的容器中,而后发布到任何流行的 Linux 机器上,也能够实现虚拟化。Docker能够自动化打包和部署任何应用、建立一个轻量级私有PaaS云、搭建开发测试环境、部署可扩展的Web应用等。
构建出Docker的Container是一个颇有意思的过程。在这一个过程当中,首先咱们须要一个base images,这个基础镜像不只包含了一个基础系统,如Ubuntu、Debian。他还包含了一系列的模块,如初始化进程、SSH服务、syslog-ng等等的一些工具。由上面原内容构建了一个基础镜像,随后的修改都将于这个镜像,咱们能够用它生成新的镜像,一层层的往上叠加。而用户的进程运行在writeable的layer中。
从上图中咱们还能够发现一点: Docker容器是创建在Aufs基础上的。AUFS是一种Union File System,它能够不一样的目录挂载到同一个虚拟文件系统下。它的目的就是为了实现上图的增量递增的过程,同时又不会影响原有的目录。即以下的流程以下:
其增量的过程和咱们使用Git的过程当中有点像,除了在最开始的时候会有一个镜像层。随后咱们的修改均可以保存下来,而且当下次咱们提交修改的时候,咱们也能够在旧有的提交上运行。
所以,Docker与LXC的差距就以下如图所示:
LXC时每一个虚拟机只能是一个虚拟机,而Docker则是一系列的虚拟机。
三、隔离底层(Servlet容器)
在上面的例子里咱们已经隔离开了操做系统的因素,接着咱们还须要解决操做系统、开发环境引发的差别。早期开发Web应用时,人们使用CGI技术,它可让一个客户端,从网页浏览器向执行在网络服务器上的程序请求数据。而且CGI程序能够用任何脚本语言或者是彻底独立编程语言实现,只要这个语言能够在这个系统上运行。而这样的脚本语言在多数状况下是依赖于系统环境的,特别是针对于C++这一类的编译语言来讲,在不一样的操做系统中都须要从新编译。
而Java的Servlet则是另一种有趣的存在,它是一种独立于平台和协议的服务器端的Java应用程序,能够生成动态的Web页面。
Tomcat
在开发Java Web应用的过程当中,咱们在开始环境使用Jetty来运行咱们的服务,而在生产环境使用Tomcat来运行。他们都是Servlet容器,能够在其上面运行着同一个Servlet应用。Servlet是指由Java编写的服务器端程序,它们是为响应Web应用程序上下文中的HTTP请求而设计的。它是应用服务器中位于组件和平台之间的接口集合。
Tomcat服务器是一个免费的开放源代码的Web应用服务器。它运行时占用的系统资源小,扩展性好,支持负载平衡与邮件服务等开发应用系统经常使用的功能。除此,它仍是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。其架构以下图所示:
Servlet被部署在应用服务器中,并由容器来控制其生命周期。在运行时由Web服务器软件处理通常请求,并把Servlet调用传递给“容器”来处理。而且Tomcat也会负责对一些静态资源的处理。
四、隔离依赖版本(虚拟环境)
对于Java这一类的编译语言来讲,不存在太多语言运行带来的问题。而对于动态语言来讲就存在这样的问题,如Ruby、Python、Node.js等等,这一个问题主要集中于开发环境。固然若是你在一个服务器上运行着几个不一样的应用来讲,也会存在这样的问题。这一类的工具在Python里有VirtualEnv,在Ruby里有RVM、Rbenv,在Node.js里有NVM。
下图是使用VirtualEnv时的不一样几个应用的架构图:
以下所示,在不一样的虚拟环境里,咱们可使用不一样的依赖库。在这上面构建不一样的应用,也可使用不一样的Python版原本构建系统。一般来讲,这一类的工具主要用于本地的开发环境。
五、隔离运行环境(语言虚拟机)
最后一个要介绍的可能就是更加抽象的,可是也是更加实用的一个,JVM就是这方面的一个表明。在咱们的编程生涯里,咱们很容易就会遇到跨平台问题——即咱们在咱们的开发机器上开发的软件,在咱们的产品环境的机器上就没有办法运行。特别是当咱们使用Mac OS或者Windows机器上开发了咱们的应用,而后咱们须要在Linux系统上运行,就会遇到各类问题。而且当咱们使用了一个须要从新编译的库时,这种问题就更加麻烦。
以下图所示的是JVM的架构示意图
JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是经过在实际的计算机上仿真模拟各类计算机功能来实现的。它能够实现“编写一次,处处运行”。
换句话来讲,它在底层实现了环境隔离,它屏蔽了与具体操做系统平台相关的信息,使得Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就能够在多种平台上不加修改地运行。
基于此,只要其余编程语言的编译器能生成正确Java bytecode文件,这个语言也能实如今JVM上运行。以下图所示的是基于JVM的Jython语言的架构图:
其底层是基于JVM,而编写时则是用Python语言,而且他可使用Java的模块来编程。
常见拥有一样架构的工具,还有MySQL,以下图是所示的是MySQL的架构图:
MySQL在最顶层提供了一个名为SQL的查询语言,这个查询语言只能用于查询数据库,然而它倒是一种更高级的用法 。它不像通用目的语言那样目标范围涵盖一切软件问题,而是专门针对某一特定问题的计算机语言,即领域特定语言。
六、隔离语言(DSL)
这是一门特别有意思也特别值得期待的技术,可是实现它并非一件容易的事。
做为讨论隔离环境的一部分,咱们只看外部DSL。内部DSL与外部DSL最大的区别在于:外部DSL近似于建立了一种新的语法和语义的全新语言。以下图所示是两中DSL的一种对比:
在这样的外部DSL里,咱们有本身的语法、本身的解析器、类型检测器等等。最简单且最经常使用的DSL就是Markdown,以下图所示:
若是咱们能够将咱们的业务逻辑写成DSL,那么咱们就不须要担忧底层语言的变更过多地影响原有的业务逻辑。换句话说,这至关于建立了咱们本身的语言隔离环境,咱们不须要思考用何种语言来实用咱们的业务。