标签:windows 解决方案 打印机驱动 应用程序 团队合作
Citrix UniversalPrinter Server(以下简称UPS)是一个XenApp和XenDesktop环境中的一个打印组件,它有助力提高用户在网络打印方面的体验。
首先我们来说,Citrix已经有了UPD为什么还需要推出UPS?根据前文我们的描述,Citrix UPD只是解决了基于客户端的打印问题(当然并不是完全解决,部分驱动还存在兼容问题),而对于网络打印呢?Citrix UPD并不解决网络打印所带来的问题:
1)、经常需要安装和更新打印机驱动;
2)、打印驱动程序与XenApp或RDS不兼容可能会导致服务崩溃;
3)、打印速度太慢;
4)、分支机构打印消耗的带宽过高;
5)、应用程序打开或执行很差等等。
这些传统的Windows打印机服务器所具有的问题,一直困扰着在XenApp/XenDesktop环境中使用网络打印机的用户。为了解决这些问题,以前的做法是,Citrix与其他团队合作,测试并提供稳定的打印驱动程序。但是这只是治标不治本,Citrix迫切需要一个通用的解决方案来解决这个问题。这个通用的方法将打印传送到网络打印服务器时,其基于网络打印服务器的打印机的驱动不需要在VDA上安装,而是通过VDA上的通用驱动,将打印任务发送到打印服务器,做到设备的无关性。于是Citrix基于Citrix UPD的基础之上,研发了Citrix UPS解决方案!
Citrix UPS解决方案在Citrix XenApp/XenDesktop7.6版本时推出7.6版,功能增强和稳定已经足以在生产环境中使用。该组件允许用户将打印连接到打印服务器而不安装打印机特定的专用打印驱动程序。这减少了用户或管理员在VDA上安装特定的打印机驱动程序,同时最大限度地减少打印驱动程序引发的服务崩溃或内存泄漏。
而给用户部署了Citrix UPS提供网络打印后,对用户的打印体验的提升可以有一下几点:
Windows 打印服务器没有办法对图像、字体进行缓存、高级压缩、打印优化以及QoS支持,UPS开发了对些特性的支持。
打印机存在不同的驱动,因此用户在连接打印机后,不同的厂商所提供的打印属性页是不同的,而UPS可以提供统一的打印机设置页面。
新的打印机加入公司的网络打印机序列中或连接到新部署的打印服务器时,管理员需要对现有的XenApp和XenDesktop环境进行更新打印驱动用以支持这些打印机,而UPS可以避免这些工作,实现万能驱动部署。
同时通用打印服务器还可以优化打印以提升基于分支机构的WAN流量。
Citrix的UPS使用Citrix的UPD,因此不再需要在XenApp上或XenDesktop上安装或测试任何驱动程序,而是直接使用Windows EMF格式(Citrix UPD的默认打印格式是EMF)直接将打印任务发送到网络打印服务器。
Citrix通用打印驱动程序(UPD)支持由Microsoft定义的独立于设备的公共设置。如果用户需要访问特定于打印驱动程序制造商的设备设置时(一般来说,通用的UPD支持有限),也可以使用Windows本地驱动程序配对通用打印服务器。使用此配置,用户就在通用打印服务器和本地驱动程序之间考虑一个平衡点,因为Windows本地驱动程序需要维护。所以最佳的解决方案是在保留通用打印服务器优势的同时,允许用户使用专用打印机的功能。
Citrix UPS从发布到现在,版本更新频繁,而且一瞬间从1.x到7.x,许多人之前没一直接触的,一开始接触都会犯迷糊?理清楚这个我们需要来看其版本的迭代历史:
1.0
1.0+修补程序(CTX135891,CTX135890,CTX139284,CTX136002)
7.0
7.1
7.1+修补程序(CTX139462,CTX139465,CTX139463)
7.6
7.9
其版本发布是从1.0发布之后,直接发布进入到7.0的,主要考虑是XenApp/XenDesktop版本号对齐。
Citrix UPS支持XenApp 6.5和XenApp/XenDesktop 7.x。我们现在在XenApp6.5的环境上部署Citrix UPS,我们只要选定服务器和客户端使用相同的版本即可。目前Citrix UPS7.6版本部署在XenApp 6.5上也是受支持的,只需要在XenApp 6.5上安装相应补丁即可。
Citrix UPS的架构主要由以下几个部分构成:
服务器组件:CitrixUPS的服务器组件是UP Server,UPServer用于接收打印任务,其默认安装在Windows的服务器操作系统之上。UPServer虚拟端口监视器根据检索的打印数据并通过Citrix的手段将其转发到相应的打印机。默认使用TCP端口 8080和7229。具体可以参考下图。
客户端组件:客户端组件就是UPClient,UPClient将处理用户的打印任务,它接收从Citrix UPD传送过来的EMF或XPS打印流,然后将打印任务通过网络发送给UPServer。无论是打印命令或打印数据发送都使用各自的端口(这些端口可以通过Citrix策略进行更改)。其中,UP Client通过SOAP使用HTTPS TCP 8080端口将打印命令发出。通过CGP/SSL的TCP 7229端口将打印流XPS/EMF格式的数据发送给UP Server。客户端组件被安装在XenDesktop VDA或XenApp服务器VDA上。
其架构图如下所示:
新的Citrix通用打印机驱动程序支持Windows和非Windows客户直接网络打印。非Windows的客户端就是Linux、Mac以及Unix等客户端,和UPD一样,UPS通过UPD支持的Windows客户端的XPS、EMF以及RAW等支持Windows客户端的打印,而对于Linux等非Windows客户端,也是采用PCL以及PS等来进行支持。同时,在这其中,如果要使用一些特殊的打印机以及驱动,就需要使用NPD的方式,即在打印的时候,连接的网络打印机会在VDA或XenApp本地安装打印机的原生驱动。使用这种方式的情况下,UPS通过Citrix UPS Hooking技术,截获掉本地打印机驱动生成的打印数据并将其转达给本地UpClient,由UPClient再转发给UPServer进行相应的打印操作。如上图就描述了UPS所支持的UPD以及安装的本地驱动程序结合的架构。
对于UPD的驱动来说,其通过UPD驱动的打印机提供者将打印数据传递给UPClient,而基于本地驱动程序来说,则会使用UPS的API Hook技术,将其打印数据从本地进行拦截,并传递给UPClient。
了解了大体的UPS架构之后,接下来我们再来了解下其工作原理!
UPS技术大体上的工作流程是这样的:XenApp服务器或XenDesktop虚拟桌面代理(VDA)通过HTTP和SOAP连接到打印服务器UPServer。该VDA或XenApp服务器通过Citrix策略映射和分配会话打印机,其打印的时候就不会安装原生打印机的驱动程序。所有打印机的驱动程序配置和管理都在打印服务器上。当有打印作业需要进行打印时,其打印作业被UpClient通过HTTP / SOAP和压缩传输发送到打印服务器UpServer。UPServer接收打印作业并将其转换为正确格式,然后通过UPS的端口监视器将作业发送到打印机。
首先,UPS中,UPClient在进行打印的时候,会向UPServer建立连个通讯通道,一个用于传输打印命令;一个用户传输打印数据。当客户端打印,XenApp服务器上或XenDesktop虚拟桌面上的客户端组件(UpClient)从Citrix通用打印驱动程序接收基于EMF、XPS或RAW的打印流,并将其转发到打印服务器。无论是打印命令和打印数据都是用自己的端口发送。默认情况下,打印命令通过TCP 8080发送,打印数据通过TCP 7229,但这些端口都可以通过Citrix策略来更改。Citrix策略在其中起到控制组件的作用。控制UPS的启用以及相应端口、传输带宽等。
在UPClient端,在安装VDA之后,会在服务组件里面安装一个Citrix的用于Citrix通用打印服务器的服务—XTE.exe。该服务器在配置了Citrix策略并启用通用打印服务器的情况下,如果打印作用通过Citrix UPD的打印提供者提交到UpClient之后,给XTE.exe服务就会通过和UpServer之间建立上述所说的恋歌传输通道,首先向8080端口发起打印命令的请求,待UpServer回复建立连接之后,在通过8080端口传输打印数据流到UpServer,这些都是通过XTE.exe进行。
其次,服务器组件(UpServer)检索打印数据和思杰通用打印服务器,通过相应动作之后,经过UPS虚拟端口监视器的方式将其转发到相应的打印机。在UPServer上,并不会存在Citrix的UPD组件,网络传输过来的打印数据是通过UpServer进行处理的,UpServer也不是一个打印驱动程序,而是管理打印数据以及打印机操作的服务器组件,他的职责就是根据接收的打印命令以及打印数据去找到正确的打印机,并将数据转发给正确的打印机。
在通用打印服务器上,在安装了UpServer之后,也会通过XTE.exe服务监听TCP端口:8080和7229。同时,安装了UpServer之后,其也会默认安装一个Web站点,基于开源Apache 的Web服务器,该服务器主要是通过HTTP接收打印命令和映射打印机到VDA上。然后通过SSL/CGP传输打印数据流,则主要是通过该传输协议,可以利用Citrix对HTTP的自定义协议优化针对打印传输的优秀特性,比如压缩、Qos等等。UpServer在监听到8080端口发起的请求之后,和传统的客户端/服务器模式协商机制一样,会首先进行协商,然后再通过7229端口开始传输打印数据流。在传统的Windows网络打印下,其网络传输是没有进过任何优化协议进行优化的。下图说明了XTE.exe服务在整个打印过程中的核心作用。
同过上图,我们也知道了通用打印服务器如何捕捉客户端的打印作业会话。
整个过程步骤如下图描述:
而对于上述所说的使用UPD和使用特殊驱动的区别,映射的打印机如何来区别打印机使用的是UPD还是特殊的驱动呢?这个驱动其实是我们告诉打印机去用什么样的驱动的,比如说我们在映射会话打印机的时候,优先选择使用Citrix通用打印驱动程序,然后通过查看打印机属性,如下图所示。就就指定了打印机所使用的打印机驱动程序,这个是通过Citrix的策略来实现的。
也就是说,在我们映射打印服务器上的HP、佳能等打印机时,我们可以选择这些映射过来的打印机指定他们使用Citrix的通用打印机驱动程序而不是这些打印机的原本的驱动程序。
客户端本地连接的打印机(如USB,LPT,COM)设备的打印作业将直接路由,也就是从Citrix会话到客户端设备然后到打印机。其打印路径如下:
与本地连接的打印机相比,思杰的网络打印作业就稍显不同。
首先我们来说传统Windows环境下,使用网络打印服务器的场景有哪些:
1. CitrixReceiver使用网络打印机,然后Receiver将其按照本地打印机进行映射;
1. CitrixVDA使用网络打印机,其通过SMB协议共享访问网络上的网络打印机。
其中,这两种情况下,又根据打印服务器所处的位置不同而有所区别。
在第一种情况下Citrix Receiver使用网络打印机,我们将其中的三个组件列出来:Citrix Receiver(客户端)、网络打印服务器、打印机。根据这三者所处的位置(WAN和LAN),可以分为8种情况:
序号 | Citrix Receiver | 网络打印服务器 | 打印机 |
1 | WAN | WAN | WAN |
2 | WAN | LAN | WAN |
3 | WAN | WAN | LAN |
4 | WAN | LAN | LAN |
5 | LAN | LAN | LAN |
6 | LAN | LAN | WAN |
7 | LAN | WAN | LAN |
8 | LAN | WAN | WAN |
在第二种情况下Citrix VDA使用网络打印机,也将其中的三个组件列出来:Citrix VDA(客户端)、网络打印服务器、打印机。根据这三者所处的位置(WAN和LAN),可以分为8种情况:
序号 | Citrix VDA | 网络打印服务器 | 打印机 |
1 | WAN | WAN | WAN |
2 | WAN | LAN | WAN |
3 | WAN | WAN | LAN |
4 | WAN | LAN | LAN |
5 | LAN | LAN | LAN |
6 | LAN | LAN | WAN |
7 | LAN | WAN | LAN |
8 | LAN | WAN | WAN |
这两种情况下根据所处的WAN和LAN的不同,共计16种情况,当然理论上来说。如果追究更细的路由,在LAN内部还有VLAN,也有着不同的路由。这种情况下就更多了。
在Citrix UPS模式下,只能使用到第二种情况,也就是Citrix VDA使用网络打印机的情况。
序号 | Citrix VDA | Citrix UPS | 打印机 |
1 | WAN | WAN | WAN |
2 | WAN | LAN | WAN |
3 | WAN | WAN | LAN |
4 | WAN | LAN | LAN |
5 | LAN | LAN | LAN |
6 | LAN | LAN | WAN |
7 | LAN | WAN | LAN |
8 | LAN | WAN | WAN |
而经过上述表格的归纳整理,我们可以看到,基于客户端本地直接连接打印机的打印路径图如下所示:
客户端本地通过鼠标键盘发送打印命令到数据中心的Citrix服务器上,经过Citrix打印系统的一些动作之后,将压缩后的打印数据反传送回客户端本地,再由客户端本地直连的打印机进行打印。
特别注意的是,客户端能够承载直连打印机的有Windows、Linux和Mac三种。其中Linux和Mac都有一定的局限性,其不支持EMF和XPS等打印格式,因此这上面的打印路径其实就仅仅针对于Windows的客户端。也就是说,基于Linux或Mac的客户端,打印数据要么在虚拟桌面或XenApp服务器上渲染好,要么使用直接打印语言(如PCL6、PostScript)直接将打印的原始数据发送到打印机,由打印机进行渲染然后再打印。
而在使用Citrix UPD情况下,由于UPD并不知道客户端Linux或Mac的打印机是PCL的还是PostScript(PS)的,因此都是使用PostScript即PS文件将打印数据传递过来,Linux或Mac的Citrix Receiver接收到打印数据后, 如果打印机支持PostScript,CUPS(Common UNIXPrinting System,Linux/Unix平台的首选打印系统)将打印数据直接输出到打印机;如果是 PCL 打印机, 则需在 CUPS 中通过打印机驱动将 PostScript 转化为 PCL 数据。
而针对于网络打印的路径就比较复杂了!打印路径复杂主要是打印机以及打印服务器和Citrix VDA可以处于不同的位置,而根据他们位置的不同,其打印的效率以及打印优化的速度等等都有所区别。
而对于压缩来说,相对于客户端直连打印机,打印机到网络打印机服务器之间的打印数据传输并没有经过任何优化和压缩的。如下图所示:
Citrix VDA使用网络打印机的情况:
Citrix Receiver使用网络打印机的情况:
这种情况下如果网络打印服务器在数据中心呢?这种情况下打印数据会在整个WAN来回传送三次,对于打印体验绝对是一个灾难性的,因此这种情况是我们在做设计的时候应该极力的避免的场景。
接下来我们看下网络打印的打印路径:
Citrix Receiver使用网络打印机,如下图所示:
Citrix VDA使用网络打印机,如下图所示:
简述了普通场景下的网络打印之后,我们需要回归本文的核心,Citrix的UPS,在Citrix UPS模式下其打印路径有是怎样的呢?
Citrix UPS的打印路径如下所示:
结合上述的打印路径,我们引出Citrix常见的打印方案:
1、远程或者在家办公的时候,利用远程或者家里的打印机打印数据中心的Citrix打印数据。
2、在公司内网办公室进行日常办公,利用本地客户端直连打印机处理数据中心的Citrix打印数据。
3、在公司内网办公室进行日常办公,利用网络打印机处理数据中心的Citrix打印数据。
4、在分支机构办公室进行日常办公,利用本地客户端直连打印机处理公司总部数据中心的Citrix打印数据。
5、在分支机构办公室进行日常办公,利用本地网络直连打印机处理公司总部数据中心的Citrix打印数据。
UPServer的部署
UPServer需要部署在Windows的打印服务器中,UPServer不能与XenApp服务器安装在同一台服务器上。
值得注意的是:Windows Server 2003系统不支持Citrix UPS UPServer。持外Windows Server 2008及以上系统都支持。
安装的时候可以通过CitrixXenApp/XenDesktop的安装光盘进行安装,首先启动您的XenApp / XenDesktop的7.6介质,然后单击通用打印服务器。您也可以浏览到XenApp / XenDesktop的目录下,运行UpsServer_x64.msi或UpsServer_x86.msi安装包。
而UPClient默认集成在每一台XenApp服务器或XenDesktop VDA中。因此安装了VDA就默认安装了UPClient,只需要配置Citrix策略即可启用。现在的Citrix UPS支持在XenApp 6.5以上、XenDesktop 5.5以上的版本中使用。
对于Citrix策略的配置,有以下专门针对于Citrix UPS的策略:通用打印服务器选项。
通用打印服务器有以下配置策略:
我们可以通过“通用打印服务器打印流输入带宽限制 (kbps)”来限制打印带宽。在“通用打印”中还可以设置,压缩、优化、修改HTTP/SOAP/CGP的端口等设置。这些配置都是可选的配置。
而要使得Citrix UPS正常运行起来,必须的配置以下这些策略:
1、启用通用打印服务器。该策略在启用的时候有两个选择:
已启用并回退到Windows的本机远程打印
已启用并未回退到Windows的本机远程打印
这两个选项是针对网络打印高可用的一个折中方案,即在通用打印服务可用时使用通用打印服务器,在不可用时使用Windwos传统的网络打印服务器。在7.9版本中已推出基于Citrix UPS的负载均衡功能。
2、SessionPrinter(会话打印机):添加打印服务器的地址。
3、客户端打印机重定向:启用这条策略,允许进行打印机重定向;
4、自动创建客户端打印机:启用这条策略和上条策略之后,用户将自动看到UPS的会话打印机。
5、直接连接到打印服务器:连接到的打印服务器将会使用UPS打印驱动。
这些策略配置好之后,确保我们的打印服务器也安装配置完毕,那么我们的Citrix UPS环境就配置安装完毕。用户使用Citrix网络打印机的时候,其打印机的模式处,我们就可以看到使用的是Citrix UniversalPrinter的模式,证明该打印机所使用的打印机驱动是Citrix UPD。但是注意:这和Citrix的通用打印机是有区别的。这里的Citrix UniversalPrinter模式是指:使用 Citrix 通用打印机动程序自动创建的设备打印机。该打印机是自动创建特定于设备的打印机,但使用 Citrix 通用打印机驱动程序。例如,配置的策略规则指定在每个会话开始时仍自动创建打印机 LaserJet5L;但是,会话使用 Citrix 通用打印机驱动程序将打印作业发送给打印服务器,打印服务器与真实的打印机 LaserJet5L驱动程序通信,并在打印服务器上处理打印作业。
而查看打印机的属性,也不是HP打印机的属性,而是Citrix UPD驱动所制定的的打印机的属性页面。本地设置选项等被砍掉。见下图:
策略设置的影响
如果通用打印服务器启用客户端打印机重定向和自动创建客户端打印机,客户端网络打印机可以使用通用打印机驱动程序来创建,直接链接到打印服务器。否则,就需要本地安装了本地驱动程序或客户端网络打印机的驱动程序来创建打印机。
我们还可以通过“打印机自动创建事件日志首选项”策略来查看创建打印机的问题,比如通用打印服务器可能会允许其他不受支持的打印机,如Linux的客户端不支持EMF或XPS通用打印机驱动程序的创建。
上面我们说了,在7.9版本之前,Citrix的UPS只是单机部署模式,而如果要支持HA,只能通过Windows的群集或者NetScaler设备利用复杂的处理机制来实现。但是这样配置HA的弊端在于,虽然我们在环境中的有多个通用打印服务器用于HA,但是,每个打印机策略分配只能包含一个打印机队列单一通用打印服务器上,无法实现UPS打印机连接多个Citrix UPS以及无法实现打印的负载共享。
https://www.citrix.com/blogs/2016/07/20/ups-load-balancing-in-xenapp-and-xendesktop-7-9/
随着Citrix XenApp和XenDesktop 7.9版本的推出,其附带一个全新的功能用于将现有的Citrix UPS组件:打印服务器负载均衡。除了通用打印服务器负载均衡,还增加了打印作业的可扩展性改进,以更好地服务于大规模的打印环境。
下面我们就来看看Citrix UPS如何实现负载均衡,其架构图如下图所示:
如果实现的呢?我们在之前的章节中曾经给大家介绍过Citrix的打印管理服务(Citrix Print ManagerService)。Citrix的实现方式就是通过CPMS里面增加Citrix UPS的负载均衡功能模块来实现,而对于CPMS里面增加的功能模块就是通过Citrix的策略来进行控制。因此我们也可以说是通过Citrix策略来实现基于Citrix UPS的负载均衡。
Citrix在Citrix策略里面增加了4个新的策略来实现Citrix UPS的负载均衡:两个默认的注册表项和两个包含在新版本7.9的Citrix Studio控制台中的策略中。这两个新的Citrix Studio的策略是:Universal PrintServers for load balancing和UniversalPrint Servers out-of-service threshold。而默认的注册表则是用于UPS间的Ping心跳,监测对方是否停止服务。
Universal PrintServers for load balancing:
在这个策略的列表中添加打印服务器的地址(主机名,FQDN或IP地址)。然后会有一个额外的验证机制根据这个列表去验证每个服务器可用性。同时,这些服务器上,必须具有相同的一组可用的打印机。这些打印机的名字以及型号等都需要相同。
Universal PrintServers out-of-service threshold:
这个策略用于标记通用打印服务器集群客活动的服务器。这个策略规定了当UPS无响应时的超时时间,默认为180秒,如果在180秒之内,如果UPS处于脱机或者服务不可用的状态,该策略就会在UPS集群中标记该台服务器为脱机,并在负载均衡名单之中删除该台服务器。这个时间可以根据我们自己的需要进行修改。
而两个注册表键值,赋予这个ping时间间隔缺省的最大值和最小值。我们可以手动修改这两项注册表项提供的超时行为然后进一步细致地控制打印服务器的负载均衡集群。
利用上述策略和注册表键值,每个键值的VDA将提供可用于用户的打印机连接可用的UPS的列表。利用这些列表来进行选择,从而实现负载均衡和“HA”机制。根据VDA实现的类型,其UPS的工作模式分为两种:
基于服务器系统VDA的UPS负载均衡
基于服务器系统的VDA是多用户的,当第一个用户请求登录的时候,Citrix的DDC里面的CPMS会为用户准备Citrix会话,其中,Citrix会话里面就包含了关于打印机的设置,CPMS默认的策略是第一个用户的UPS打印机所连接的UPS是随机在UPS列表中为其分配一台可用的。在Citrix DDC准备完会话文件之后,将其提交给VDA,VDA会在服务器上创建用户会话ing执行下发的策略,其中,根据打印机的策略将会为第一个用户从可用的打印服务器列表中随机选择的UPS进行分配。至于后来的用户,其分配原则是从其他可用的通用打印服务器列表中顺序地进行分配。如何来确定其他可用的服务器未进行分配呢?这是由正在运行的一套计数器跟踪(每个UPS将有活动,创建和删除连接的计数器)打印机连接到每台UPS的数量来实现的。这些计数器有助于更均匀地分布打印机连接负载,并能通过Windows内置的性能监视器界面进行查看。如果UPS失败,使得其被标记为离线,那么连接到该服务器的所有当前连接将被重新分配给其余可用的UPS。
基于桌面系统VDA的UPS负载均衡
在一个基于桌面的环境(VDI),每个用户会话对于UPS打印机的分配策略是进行随机分配。每个用户的UPS打印机从可用打印服务器的列表中随机选择的UPS。由于每个桌面VDA永远只有一个用户,一直都是单一连接,所以在保持负载的情况下随机分配即可。同时,打印机连接计数器也存在于XenDesktop的VDA中,但由于是单个用户性质,所以该计数器的作用仅仅作为参考。如果有UPS故障,那么该台UPS所有的连接将被重新分配到一个随机活动服务器中。
在上述两种情况下,一个UPS被标记为脱机的情况下将不会在出现在可用的负载均衡列表中,直到它恢复和响应ping请求。如果服务器响应了Ping请求,它会自动重新添加到可用的负载均衡UPS列表,并根据策略接受新的连接。
那么在大型的环境下我们最多可以部署多少台Citrix UPS呢?现在到最新的版本7.11中,UPS支持到16 台UPS负载均衡集群。
并且在7.9版本之前,UPS每分钟可以处理50个并发活动的打印作业。使用XenApp和XenDesktop 7.9,UPS可扩展性提高了2倍,每分钟可以处理100个并发活动的打印作业。
所以,5 台UPS每台100个并发的打印作业,每分钟共计500个并发的打印作业。如果我们需要更多的打印作业,试试部署16台UPS,那么每分钟就可以处理的并发活动的打印作业数是1600。从最简单的2台到16台,UPS负载均衡集群可以线性扩展。
本文出自 “我拿流年乱了浮生” 博客,请务必保留此出处http://tasnrh.blog.51cto.com/4141731/1859926
Citrix XenApp和XenDesktop 打印系统解析③
标签:windows 解决方案 打印机驱动 应用程序 团队合作
原文地址:http://tasnrh.blog.51cto.com/4141731/1859926