郭晓金,王 超
(重庆邮电大学通信与信息工程学院,重庆 400065)
多路径就是使用冗余的物理路径组件(适配器、电缆和交换机)在服务器与存储设备之间创建逻辑路径。如果这些组件中的一个或多个发生故障,导致路径无法使用,多路径软件就使用I/O的备用路径使应用程序仍然能够访问其数据。每个网络接口卡(在使用iSCSI的情况下)或HBA都应通过使用冗余的交换机基础结构连接起来,以便在存储结构组件发生故障时能继续访问存储。现在企业对数据的稳定性、可靠性的要求越来越高,特别是在企业级的数据业务上,需要非常高的数据传输可靠性。业界常用的方法是为数据业务提供多路径传输通道,来避免单点故障(单点故障是指网络中的某处发生故障,可能导致整个网络瘫痪)[1]。
由于多路径软件是需要和存储设备在一起配合使用的,不同的厂商基于不同的操作系统,都提供了不同的版本。本文提出一种多路径的设计方法,它基于Linux主机的设备驱动程序,用来控制对存储设备的访问,实现主机到存储设备之间的路径选择,提高主机与存储设备之间的路径可靠性与性能。在有多路径软件的情况下,多路径就可以屏蔽冗余设备、避免造成混淆,并且创建一个新的设备,由新的设备去对应多条通路。
MulPath作为内核模块被加载到Linux操作系统中。它在操作系统内部被注册成为一个虚拟设备。通过该软件,可以使应用服务器与存储系统之间选择合适的路径进行通信。如图1所示,当存储系统是多路径组网时,系统启动时MulPath通过设备的注册,发现每条路径上的设备,并将路径状态信息记录在数据结构的相应位置。对于每个设备(LUN),MulPath下发命令,查询设备当前归属于阵列的哪个控制器,并将主机到这个阵列控制器之间的路径作为优先选择路径,即主路径。如果主机到这个阵列控制器之间有多条路径,MulPath就会将I/O分担,从而在这几条路径上形成负载均衡[2]。
如图1所示,当主路径(路径1和路径2)由于某种原因出现故障后,MulPath所提供的Faiover功能能够自动将业务切换到备用路径上(路径3),避免了因单点故障而造成业务中断。当主路径的故障得以解除或修复后即能够重新正常传输I/O流时,MulPath所提供的Faiback功能会自动地将I/O传输路径从备用路径切换回主路径上[3]。
图1 Linux主机冗余存储路径组网图
MulPath由安装程序、管理工具和驱动程序组成,其中安装程序和管理工具运行在用户态,而驱动程序运行在内核态。驱动实现在内核SCSI体系上,这样比较容易实现搜集并屏蔽物理设备信息,而求方便形成虚拟设备信息。
MulPath驱动实现方框图如图2所示。
图2 MulPath驱动实现方框图
MulPath软件编译后成为驱动程序模块,它主要位于HBA卡驱动之上,对应用程序提供对阵列的访问入口而屏蔽掉具体的HBA卡和光纤通道。各种应用程序,如数据库服务程序、Web服务程序等,都将具体的对阵列的I/O请求传送给驱动程序,而驱动程序负责选择具体传送数据的路径并返回I/O结果。
本驱动程序模块需要运行在具有可识别类型的HBA卡的主机上,并且主机上安装了相应的HBA驱动程序,HBA卡通过光纤与主机阵列相联。
这类实现方法具有很好的兼容性,能够兼容多种HBA卡驱动。
当应用程序下发读LUN的命令时,例如dd if=/dev/sdb of=/dev/null,经过系统多个层次的传递,I/O数据到达驱动这一层,使用不同的HBA卡会有不同的scsi_host_template结构体,对不同的HBA卡,均有它自己的queuecommand函数指针,在此函数中对下发的I/O命令排队,并在恰当的时候将命令发送出去[4]。
由于在MulPath初始化阶段,已经将真实HBA卡对应的HOST下的LUN屏蔽,所以用户程序操作的都是虚拟HOST下的LUN,虚拟HOST(由多路径软件创建)的queuecommand(将SCSI命令包加入到等待队列中)将收到的I/O命令加入链表,并设置相应的回调函数、发送状态(如重试、超时次数等)。
由于MulPath注册使用虚拟的HBA卡,虽然用户使用dd等命令操作的是虚拟HBA卡,但是虚拟的HBA卡并不具备真实物理HBA卡真正将数据发送出去的能力。所有MulPath中,需要将利用虚拟HBA卡发送信息到对应LUN的能力转换为利用真实HBA卡发送信息。这一点就是在选路模块中,将虚拟LUN转换为“物理”LUN来实现的。
系统启动时,MulPath通过设备的注册,发现每条路径上的设备,并将路径状态信息记录在数据结构的相应位置。对于每个设备(LUN),MulPath下发命令,查询设备CurrentOwner,将此信息记录在 CurrentOwningPath中,作为优先选择路径的依据[5]。
每次发送命令时要检测使用路径的状态,MulPath对路径状态的判断是通过读取存放在RdacInfo数据结构中的路径状态变量来进行判断的,这些状态的更新主要是由定时器定时扫描路径后根据I/O状态来刷新的,因而,它们不一定能实时地反映当前路径的状态。虽然路径出现故障了,但是RdacInfo中的状态正常,仍然发送命令,发送产生的I/O错误再交给错误分析函数处理。
定时器利用异步发送命令发送对标准页的查询命令,通过返回的状态对路径状态进行检测。对于每条路径,只要对一个LUN发送成功,就继续检测下一条路径,并修改RdacInfo结构中的状态信息。
MulPath总是首先选择使用RdacInfo结构体中定义的CurrentOwningPath所描述的控制器上的路径作为首选路径,当CurrentOwningPath所描述的控制器上的所有路径都为FAILED时,才会选择下一个控制器上的路径。如果当前使用的控制器可用,则在此控制器上的所有路径进行轮循操作,分担使用每条可用路径。
通过选路模块,MulPath将最初的虚拟LUN通过查找RdacInfo数据结构转换成“物理”LUN,这个“物理”LUN有真实HBA卡的发送数据的能力,随后将数据发送出去[6]。
路径状态定时刷新通过定时器进行,定时器每1 s触发一次。路径状态包括最优、最优需要检测、最优检测中、失败、失败需要检测、失败检测中、系统特定状态7种。处理过程如图3所示。
图3 路径状态刷新流程图
若检测时路径状态处于最优,则使该路径处于最优状态时间值加1,若此时该路径的最优状态时间值大于配置文件中设置的最优检测时间IdlePathCheckingInterval,则设置该路径状态为最优需要检测。
若检测时路径状态处于最优需要检测,则设置该路径状态为最优检测中,并生成一个异步路径状态检测命令。若生成异步路径状态检测命令失败,则还原设置该路径状态为最优,并设置路径处于最优状态时间为0。
若检测时路径状态处于失败,则使该路径处于失败状态时间值加1,若此时该路径的失败状态时间值大于配置文件中设置的失败等待时间RecheckFailedPathWait-Time,则设置该路径及路径上所有设备的状态为失败需要检测[7]。
若检测时路径状态处于失败需要检测,则使该路径处于失败状态时间值加1,若此时该路径的失败状态时间值大于配置文件中设置的失败检测时间FailedPathCheckingInterval,则设置该路径及路径上所有设备的状态为失败检测中,并生成一个异步路径状态检测命令,若生成异步路径状态检测命令失败,则还原设置该路径及路径上所有设备状态为失败,并设置路径处于失败状态时间为0[8]。
若路径状态为最优检测中、失败检测中、系统特定这3种状态,则不做任何处理。
针对多路径软件主要解决路径切换和负载均衡两个问题,设计了两种组网来分别测试并选择各大存储设备厂商广泛使用的Iometer作为I/O测试的工具。
测试硬件由dell2950主机(装有SUSE10和MulPath,并配有双口4GFC_HBA扣卡),IBM的DS4700存储阵列(阵列上创建RAID5)以及若干光纤线。
如图4所示,主机到存储阵列有两条路径,分别是从主机HBA扣卡的1口和2口接到存储阵列的控制器A和控制器B上。存储阵列上创建有一个用于测试的归属于控制器A的LUN。根据MulPath的路径选择策略,路径1为优先选择路径。
图4 路径切换测试组网图
每隔10 s拔插一次路径1(拔一次后间隔10 s再插一次),观察I/O状况。测试结果如表1所示。
表1 测试1的结果
初始状态的时候,路径1是优先选择的路径,所以I/O跑在路径1上;当拔掉路径1的光纤后,MulPath的路径状态定时刷新发现路径1故障,I/O就返回到路径2上;当路径1回复后,MulPath的路径状态定时刷新发现路径1恢复,I/O就返回路径1上。
如图5所示,主机到存储阵列有两条路径,分别是从主机HBA扣卡的1口和2口全部接到存储阵列的控制器A。存储阵列上创建有一个用于测试的归属于控制器A的LUN。根据MulPath的路径选择策略,路径1和路径2都为优先选择路径。
图5 负载均衡测试组网图
每隔10 s拔插一次路径1(拔一次后间隔10 s再插一次),观察I/O状况。测试结果如表2所示。
表2 测试2的结果
本次测试中,设置I/O测试工具iometer的压力大概在1000 IOPS,由表2可知,MulPath能较好地实现负载均衡,提高了I/O的性能。
本文中提出的MulPath实现基于HBA卡的驱动,能在内核SCSI体系上很好地实现主机到存储设备之间的路径选择,提高主机与存储设备之间的路径可靠性与性能,并且有很好的兼容性,能够兼容多种HBA卡驱动。能够自动选择优选的路径,当前路径不能使用时,可使用其他冗余路径,这样就避免了系统因单点故障造成的业务中断。当有多条优选路径时,在多条路径上能够实现静态及动态负载均衡,极大地提高了I/O的性能。
[1]姜宁康,时成阁.网络存储导论[M].北京:清华大学出版社,2007.
[2]阚闯,戚玮玮.一种新结构的DM_MulPath与动态负载平衡[J].计算机应用,2008,28(2):289-291.
[3]金惠芳,陶利民,张基温.Linux下多线程技术分析及应用[J].计算机系统应用,2003(9):30-32.
[4]董峰,王树武,谭毓安.冗余存储路径在Linux的设计和实现[J].现代图书情报技术,2004(5):17-20.
[5]曹强,黄建忠.海量网络存储系统原理与设计[M].武汉:华中科技大学出版社,2010.
[6]蔡斌,谢长生,忍劲.SCSI子系统中间层多启动互联多路径I/O的存储方式的研究[J].小型微型计算机系统,2005,26(8):1420-1426.
[7]崔超.浅析存储虚拟化和数据迁移技术[J].信息与电脑:理论版.2010(6):87-88.
[8]LOBUE M T,MASON H.Surveying today’s most popular storage interfaces[J].IEEE Computer,2002,35(12):48-50.