王瑞聪,韩 琼,张明庆,张 帆
(中国航天科工集团第二研究院 七〇六所,北京 100854)
近年来,随着虚拟化技术[1]的发展,越来越多的业务、应用被部署于虚拟机上,这样虽然可以获得灵活性与便捷性,提升物理资源的利用率,但也对虚拟机的高可用性提出更严格的要求。虚拟机依托于物理服务器,物理服务器故障是所有企业都不可避免的问题。一旦物理服务器出现故障,运行在其上的虚拟机将会出现故障,虚拟机上所有的应用服务将会中断,给企业造成巨大的经济损失[2]。因此,如何保障虚拟机上应用服务的连续性,即虚拟机的容错能力成为研究热点[3]。
在广泛的需求推动下,市场上已经涌现出许多虚拟机容错服务,主流的如Xen Remus、everRun VM、VMware FT、QEMU/KVM COLO等[4]。这些虚拟机容错功能大都以双机容错实现,即在两台物理服务器上,分别创建一个虚拟机,一个作为主虚拟机PVM(primary virtual machine)对外提供服务,另一个作为备虚拟机SVM(seco-ndary virtual machine),作为主虚拟机的有效副本,在主虚拟机宕机后,无缝接替主虚拟机继续对外提供服务。容错功能的实现是通过高速网线将主虚拟机上的内存、寄存器状态、磁盘等信息不断地传输至备份虚拟机,使备虚拟机始终同步为一个可靠可用的副本[5]。
COLO(coarse-grained lock-stepping virtual machine for non-stop service)是一种针对网络数据包的粗粒度锁步虚拟机方法,提供容错功能实现不间断服务[14]。当部署图形化操作系统的虚拟机启用COLO功能,通过远程连接操作虚拟机桌面会遇到主备虚拟机界面显示不一致的现象,这将导致主备虚拟机间同步次数增多、同步耗时增加等问题。本文针对上述问题,提出一种通过分发鼠标键盘输入,检查桌面窗口输出的方法,减少界面不一致情况以降低同步时间,提高系统性能,优化用户体验。
QEMU/KVM属于虚拟机监控器VMM(virtual machine monitor)的一种[6],可以运行在多个操作系统平台上,对国产化平台也有较好的支持。QEMU是一个快速的开源模拟器,而内核虚拟机KVM(kernel-based virtual machine)是一个基于Linux内核的虚拟化解决方案[7],其架构如图1所示。QEMU和KVM相互补充,KVM负责处理虚拟机的调度和资源管理,而QEMU则负责提供虚拟设备模拟等功能,使得在Linux系统上能够高效地创建和运行虚拟机。
图1 QEMU/KVM整体架构
QEMU/KVM提供了热迁移技术,允许将运行中的虚拟机从一个物理主机迁移到另一个物理主机,而无需中断虚拟机运行,并且用户在迁移过程中没有明显感知。热迁移技术是虚拟机容错功能的实现基础,通过连续的热迁移操作,主虚拟机的状态信息会定期复制到备份虚拟机上,这被称为双机热备[8]。在此基础上,COLO通过时刻保持备份虚拟机是一个有效且可用的副本,实现了高可用性的双机容错功能。当主虚拟机发生故障时,备份虚拟机可以无缝接替主虚拟机的工作,确保系统的持续运行[9]。本文以COLO容错机制为基础,在国产平台下研究解决COLO对于桌面同步表现不佳的问题。
使用QEMU/KVM创建虚拟机后,可以通过VNC远程连接虚拟机桌面进行访问与操作[6]。VNC(virtual network console)是一种用于远程桌面访问和控制的开源技术。VNC允许用户通过网络连接到远程计算机,以实时查看、操作远程计算机[10]。VNC有viewer与server端分别运行于本地计算机与远程计算机上,viewer端将用户在本地的输入操作反馈给远程计算机,同时远程计算机的server端将屏幕图像捕获并传输到客户端。VNC基于RFB(remote frame buffer)协议进行通信,使用基于帧的图像传输方式,只传输屏幕上发生变化的像素矩阵,从而降低了网络带宽的需求。
TigerVNC是一个开源的VNC实现,它提供了高性能、可靠的远程桌面访问和控制功能[10]。本文依托于开源的TigerVNC,设计实现同时连接两台远程计算机的功能,并实现两台计算机输入一致机制。
QEMU/KVM提供了粗粒度锁步虚拟机复制的双机容错功能COLO,以实现系统高可用性。COLO的核心设计思想是,对于虚拟机容错,只要备虚拟机可以在主虚拟机出现故障无法继续提供网络服务时能够成功接管对外网络服务即可。也就是说,只要备虚拟机和主虚拟机对于外部网络请求的响应是一致的,即使两个虚拟机的其它一些状态信息可能不一致,仍然认为备虚拟机是主虚拟机的一个有效副本[13],可以接替主虚拟机提供服务。
COLO的架构设计如图2所示,包含两个由高速网络连接起来的物理服务器:主节点和备节点。主虚拟机运行在主节点上,备虚拟机运行在备节点上,主节点通过高速网线不断地将主虚拟机的状态信息拷贝传输至备节点,备节点利用这些状态信息修改备虚拟机的状态,以此来保存一个主虚拟机的有效备份。COLO要求主备虚拟机同时运行,并响应外部网络请求。来自外部的请求被主节点接收,然后分发给主虚拟机和备虚拟机,从而使得主备虚拟机获得同样的请求。COLO接收到来自主虚拟机和备虚拟机的响应,然后在将响应输出到外部之前,先比较二者响应是否一致。只要两个响应一致,则认为备虚拟机是主虚拟机的一个有效备份,不需要进行虚拟机同步操作。一旦两个响应出现差异,则先缓存来自主虚拟机的响应,与此同时进行主备虚拟机的同步操作,待同步操作完成之后,再将响应发送出去[14]。
图2 COLO整体架构设计
COLO Proxy是COLO容错功能的核心模块,其主要功能是实现主备虚拟机响应数据包的比较,检测二者是否一致。COLO Proxy模块设计如图3所示,其中A、B、C、D、E是一些转发数据包的子模块。A负责接收网络设备中的外部请求,并将请求传输给主虚拟机与D模块。B接收colo compare模块比较后的响应,并发送给网络设备。C接收主虚拟机的响应,并将该响应发送至colo compare模块供比较使用。D模块接收A模块发来的网络请求,经过一定数据包处理,发送给备虚拟机,使备虚拟机能正确与外部请求端建立连接。同样地,备虚拟机的响应包也需要经过处理,发送至E模块,然后E模块将数据包发送至colo compare模块。colo compare接收来自主备虚拟机的响应包进行比较,一致则丢弃备虚拟机响应包,将主虚拟机响应包发送给B,不一致则暂缓输出,触发同步操作[15]。
图3 COLO Proxy模块设计
通过上述分析,可以发现COLO非常适用于类似ssh连接远程虚拟机对外提供网络服务的操作。通过引入COLO机制,可以将周期性的同步间隔由毫秒级延长至分钟级,期间通过网络响应包的不一致来触发同步,有效降低主备虚拟机的同步频率,减少虚拟机用于同步的资源开销,提升虚拟机性能[16]。
然而,当虚拟机内运行拥有图形界面的操作系统,QEMU会模拟一个显示设备,将虚拟机的图形输出保存到虚拟显存中,通过VNC连接虚拟机桌面并在图形化桌面上进行各种操作,如鼠标拖拽窗口、键盘键入字符时,备虚拟机不能实时与主虚拟机显示一致,在COLO降低同步频率的情况下,主备的屏幕显示可能会有分钟级的差异,这会造成主备虚拟机机器状态,显存数据等的不同,这时触发同步会增加同步传输的数据量,延长同步时间。除此之外,在用户使用界面进行频繁网络访问操作时,该操作的数据包发送至QEMU中的VNC server端,而不会被COLO转发至备份虚拟机内,此时备机不会进行同样的网络访问操作,主备会产生不同的网络数据包,不断地触发COLO同步操作,进而导致系统性能大大降低。
为了解决COLO在图形化操作系统的虚拟机下表现不佳的问题,可以借鉴COLO在网络数据包处理方面的方法进行改进。QEMU提供了VNC服务,允许用户通过VNC客户端远程连接到由QEMU创建的虚拟机,并通过图形界面执行各种操作。在这个基础上,可以采用类似COLO将网络请求包转发给备用虚拟机的方式来改善性能。
具体过程如下,使用VNC连接主虚拟机时,在VNC客户端中捕获对主虚拟机的输入操作(例如键盘和鼠标操作),然后将这些操作同步发送给备用虚拟机。通过这种方式,备用虚拟机的初始状态与主虚拟机保持一致。随着相同输入操作在两个虚拟机上执行,主备虚拟机的桌面显示也会保持一致。这种改进方法可以有效提升在图形化操作系统的虚拟机下COLO的性能,使得用户能够通过VNC客户端实现对主虚拟机的远程操作,并且保持主备虚拟机之间的一致性。
VNC远程连接虚拟机也是通过网络传输数据,viewer端与server端通过TCP协议传输数据,但其数据包并不经过COLO模块。COLO模块转发请求主虚拟机服务的网络包,并且捕获比较主备虚拟机内产生的各种网络数据包(目前支持捕获TCP、UDP、ICMP等),而VNC远程连接虚拟机是由QEMU处理,QEMU实现了VNC Server功能,响应远端VNC Client的连接请求,连接中传输的数据包不会经过COLO模块。一种直观的改进策略是在主节点的QEMU内将响应的VNC数据包转发给COLO模块,备节点也将VNC数据包发送至主节点COLO模块进行比较。然而VNC使用基于帧的图像传输方式,只传输屏幕上发生变化的部分,通过传输一个个像素矩阵进行屏幕更新[17],通过实验验证,相同的屏幕变化,VNC Server发送的像素矩阵的个数、大小不尽相同,同时像素矩阵的数据量过大,并且存在压缩编码处理,因此,将VNC响应数据包引入COLO比较模块并不现实。
虽然无法对主备桌面像素数据进行对比,但可以追溯桌面像素数据产生之前的过程。图形界面由桌面系统绘制,国产平台下的桌面系统使用X Window System开发实现。X Window System,又叫X Protocol、X11,是一种开源的图形用户界面系统[11]。如图4所示,X11采用客户端-服务器架构,X11服务端负责管理显示设备(如显示器)和用户输入设备(如键盘、鼠标),接收来自客户端的事件请求并将图形绘制到屏幕上[12]。
图4 X11整体架构
用户在桌面的操作经过X11客户端的处理返回X11事件,X11服务端根据窗口事件绘制显示屏幕设备。因此,可以通过引入X11事件进行主备虚拟机界面的比较。常见的窗口事件包括创建、隐藏、关闭窗口,窗口大小更改,窗口获取焦点。X11客户端对于相同的输入操作产生的X11事件是完全相同的。因此,可以在虚拟机内创建服务Xsync捕获相关X11事件,并将事件封装为数据包通过网络发送至VNC viewer端,使X11数据包经过COLO模块进行比较。通过比较主备虚拟机X11事件是否一致,可以保证主备虚拟机的图形界面保持一致。
如图5所示,基于COLO容错机制下的远程桌面同步实现主要分为两个部分。一是修改VNC viewer端,检测用户对主虚拟机的鼠标键盘输入并分发至备份虚拟机,使主备虚拟机的输入一致。二是在主备虚拟机内部通过X11捕获并对外发送相关的X11事件,使其经过COLO模块进行比较。
图5 主备虚拟机桌面同步组件框架
TigerVNC viewer在vncviewer.cxx的mainloop()函数中使用 Conn(vncServerName,sock)建立与TigerVNC server的TCP连接cc,其中包含有输入流is和输出流os用以通信。为了使备份虚拟机可以接收到主虚拟机的输入流,首先需要使用Conn(vncServerName,sock)创建两条分别与主备虚拟机相连的连接cc_primary与cc_secondary,然后在cc_primary中添加输出流os2,将备连接cc_secondary中的输出流os赋给备连接cc_primary的os2以达到输入分发。CMsgWriter.cxx中包含了viewer端向server端发送各种消息的操作,根据RFB协议格式组装数据包并通过输出流发送出去,在writeKeyEvent()、writePointerEvent()中,通过增添输出流os2可以将主虚拟机的键盘鼠标事件发送到备份虚拟机。
在虚拟机内部,使用X11的扩展库xtestlib和recordlib获得键盘鼠标控制权,捕获用户在界面上的操作与产生的X11事件。XRecordRange用于标识一组要记录的事件类型,这里设置为CreateNotify到ConfigureNotify,这其中包含了窗口的创建、关闭以及窗口大小、位置改变的事件。然后通过socket编程对外发送基于UDP的X11事件数据包。由虚拟机内部发出的网络数据包会进入COLO模块,进行检查比较。这样就填补了COLO未检测比较主备虚拟机桌面数据是否一致的不足。
实验所用设备的连接拓扑如图6所示,包括两台国产飞腾机架式服务器作为主备节点,一台国产一体式计算机作为陪测PC机。其中两台服务器物理机操作系统为open-Euler,虚拟机操作系统为银河麒麟系统(桌面版),使用QEMU创建虚拟机,陪测PC为银河麒麟系统(桌面版),详细配置见表1。两台物理服务器使用万兆网线互联,一体机与两台物理机处于同一局域网中,在一体机上使用VNC viewer连接两台物理服务器上的虚拟机。
表1 实验环境详细说明
图6 实验设备连接关系
实验首先观察主备虚拟机桌面显示是否实时一致,在主备虚拟机上执行播放视频操作,观察主备虚拟机视频播放界面是否一致。
实验使用xdotool工具模拟鼠标键盘输入,测试比较引入本文改进后与原QEMU默认开启COLO情况下的界面同步耗时情况。对于无网络服务情况,设定操作序列:打开WPS输入一段字符->关闭WPS->打开终端执行命令ls->关闭终端->打开txt文本文件输入一段字符>关闭txt文件->打开QT->关闭QT->打开影音播放器->关闭影音播放器。在每个操作后记录同步所用时间并计算平均值。模拟操作序列的脚本需要在陪测的一体式计算机上编写与执行,而不在虚拟机内执行,因为同步操作会使主备虚拟机同时执行相同的脚本文件。对于通过桌面操作访问网络的情况,实验分别模拟每隔5 s,10 s,15 s,20 s进行一次对外网络请求,记录1 min内触发同步的次数和同步耗时。
使用VNC连接访问主备虚拟机,界面如图7所示,在主虚拟机上进行视频播放时,备虚拟机保持与主虚拟机界面一致。
图7 主备虚拟机界面同步展示
在无网络服务情况下,测试无任何操作、改进前后进行界面操作情况下的主备同步时间,分别记录10组10 min内虚拟机的同步时间并取平均值。实验结果如图8所示,在不操作虚拟机时COLO默认20 s同步一次,平均每次同步耗时257 ms,改进后主备虚拟机平均同步时间由523 ms缩短为435 ms,降低了16.82%。10 min内,无操作情况下总同步时间开销为7710 ms,改进后,会偶尔发生主备虚拟机界面不一致触发的同步,主备虚拟机总同步时间由15 690 ms缩短至14 355 ms,降低了8.50%。
图8 主备虚拟机同步时间对比
在虚拟机上进行对外网络操作时,原默认情况下,只有主虚拟机发出网络数据包,备虚拟机没有对应的网络操作,此时COLO便会触发同步。改进后主备虚拟机会同时进行相同的网络操作,避免触发检查点同步。进行10组实验取平均值,结果如图9所示,在进行高频网络操作时,本文方法优化提升明显,在每隔5 s进行一次网络请求情况下,1 min内主备虚拟机的同步次数减少了69.1%,同步耗时减少了64.7%。
图9 不同网络请求间隔下的对比
本文利用QEMU中COLO的设计方法,即转发对主虚拟机的网络请求包至备虚拟机,使主备有相同的网络请求输入,比较检查主备虚拟机的网络响应包是否一致,不一致时触发同步操作。针对装有图形化操作系统的虚拟机,提出通过VNC输入分发,使主备虚拟机接收相同的鼠标键盘输入,比较检查主备虚拟机的X11事件是否一致,不一致时触发同步操作,进而保证主备虚拟机一致。实验结果表明,本文方法保证主备虚拟机图形界面实时一致,对于虚拟机同步次数有减少作用,并且有效降低同步时间。后续的工作将研究主备虚拟机界面显示快慢误差所造成的不一致情况,进一步提高虚拟机性能。