技术的发展可以分为两种:把已有技术发挥到极致,和发明创造革命性的技术。
20年前,1998年,互联网浪潮之前,程序都是跑在物理服务器上。彼时如果说用户数太多,或是服务器挂了,也没太好的办法。多是提早准备两台服务器待命,一旦一台不够或者出问题了,备机赶紧上。
10年前,2008年,虚拟机技术已经发展的非常成熟。一台主机可以运行多个虚拟机,一旦一台服务器宕机或者需要扩容,只需用已有的镜像迅速启动一台「一模一样」的虚拟机即可。
在此不得不提一嘴亚马逊AWS的EC2服务。EC2又名云计算主机,是AWS提供的在线虚拟主机服务,用户可以根据需求启动不同配置不同数量的EC2实例。用户可以把任意EC2实例转换为一个AMI镜像,从而在这个AMI镜像基础上启动更多EC2实例。
AMI全称亚马逊机器镜像,是EC2虚拟机的快照。用户不仅可以在AWS上制作镜像自己使用,也可以把深度定制的镜像在aws marketplace上分享、销售出去。
利用对EC2和AMI灵活的使用,部署在AWS上的程序可以很轻松的实现程序的自我修复、动态扩容等。程序部署变的简单而高效。
容器
如果说EC2把虚拟机技术发挥到了极致,那么容器化就是新一代革命性创新。
虚拟机最大的优点,就在于当它运行在宿主操作系统上时,因为硬件是完全虚拟化的,虚拟机里的程序可以很好的和宿主机以及其他虚拟机里的运行环境隔离开来。每一个虚拟机里的环境,都是一个「被隔离的沙盒」,沙盒之间不会互相影响。如此即保证了虚拟机之间的独立性,也保证了程序运行的安全性。
虚拟机的缺点也很明显。虚拟机需要在宿主操作系统上,模拟出虚拟化的硬件,再安装一套操作系统,最终程序运行在虚拟机里的操作系统里。如果虚拟机的操作系统和宿主操作系统一样,那么这中间就存在着大量的资源浪费(硬件、软件虚拟化)。
那么有没有一种技术,即可以发挥虚拟机的优势,又可以兼顾它的劣势呢?它就是容器技术。
容器技术主要源于Linux操作系统的两个特性:namespace和cgroups。Linux namespace允许在Linux中创建一个沙盒,使程序完全隔离地运行在这个沙盒中;Linux cgroup则对计算机资源进行隔离,控制和分离程序运行时的资源使用。同时,因为程序在运行时,仍然是基于同一套Linux内核,也就不存在虚拟硬件和虚拟操作系统一说了。少了这两层,系统资源得到了最大化利用。
这些容器化相关的技术,让运行在容器中的程序,有一种「运行在独立主机里」的飘飘然感觉。在他们眼里,目录是「/」,权限是「root」 ,只有自己在运行,似乎可以任意妄为。这就是容器化技术想要达到的「虚拟化」目的,进程被放到了孤立的「黑客帝国」里。
至此,也就容易理解为什么容器化要比虚拟机更高效——本质上「容器」里的程序就是运行在宿主机上的进程。同样的配置,运行多个进程当然比运行多个虚拟机容易多了!
得益于容器技术,微服务在近年来大出风头。把后端的服务,在SOA的基础上继续细化,程序变成了一个个小小的单元,互相之间的直接调用,变成了网络通讯。大型的程序,不同业务由不同的微服务支撑,同一个业务,多个层次也是由多个微服务提供。大大小小的容器运行一大堆。
未来
从实体服务器,到虚拟机,再到容器,计算资源被越来越高效的利用起来。如何才能进一步优化资源利用?
无服务器技术(serverless)。
可以想象,容器化把资源和环境隔离开,让程序进程能够独立运行,但这种程序在运行时仍然需要先构建自己的基础依赖库。如Docker image里在程序层级之下,定义了复杂的依赖库。如果我们可以在容器化的基础上,继续抽象、重用这些依赖层,容器里的程序体积将进一步缩小。如果做到除所有依赖都可以共享,不同的只有运行时的业务逻辑和资源占用,那时将达到资源的终极利用。
无服务器(serverless)正是出于这样一种设计,云平台(AWS,Azure,Google Cloud)把底层极端抽象,只暴露几个必要的接口。编码时只需根据公用接口编写自己的业务逻辑,以程序的最小单元——函数来进行部署。运行时,单个函数运行在自己独立的容器里,完成调用。
微服务的实施,一方面是技术层面的划分,另一方面也是对业务的细分。为了提高效率,技术最终要逐渐从业务中剥离出来,技术归技术,业务归业务。抽象出来的技术,变成一个个通用微服务,提供现成接口,产品的开发将只需要关注业务逻辑,利用serverless把这些接口用「业务」粘在一起即可。
手机上有一个APP叫做IFTTT,全名if this then that,它提供一个平台,用户可以授权多个其他APP的服务,比如Email,短信,天气,Facebook。选择两个服务组成一个「食谱」,其中一个是「this」,另一个是「that」,一旦「this」发生,就会触发「that」。比如可以设定一个「如果下雨,发短信给自己」,「如果在Instagram赞了一张图片,就下载它」等等。
IFTTT提供的就是对技术的剥离,把一个个服务的「事件」和「操作」抽象出来。普通用户不需要很多技术背景,就可以把任意两个服务按照自己的实际需求连接起来。
AWS现在就在尝试做同样的事情。AWS提供的服务越来越多,越来越专,在这些服务之外,它也有serverless的解决方案AWS Lambda。每一个Lambda可以设定一个触发器,可以是直接的API请求,也可以是来自其他AWS服务,如S3、SQS等。Lambda本身,则是一段极简的逻辑,用于把数据从一个地方流到另一个地方。
比如我想做一个视频直播软件,除了该有的UI和UX,后端的关键用例不多,一个是发起者上传视频内容流,其次是转码、存储,最后是终端用户接受不同码率的视频。AWS提供Kinesis负责数据流,Elastic Transcoder负责转码,S3负责存储,其他那些粘合这些服务的地方,只需要加上简单的Lambda服务就好了。
End
1998到2018的20年,服务器形式上从有到「无」,抽象上从大到小,到现在的「无服务器」,是计算机科学硬件和软件的快速发展产物。不论是硬件资源,还是软件开发上,程序都在变得愈加高效。