第 3 章 — 建立連接發(fā)布日期: 8/20/2004 | 更新日期: 8/20/2004 ![]()
智能客戶(hù)端體系結構與設計指南 David Hill, Brenton Webster, Edward A. Jezierski, Srinath Vasireddy and Mohammad Al-Sabt, Microsoft Corporation; Blaine Wastell, Ascentium Corporation; Jonathan Rasmusson and Paul Gale, ThoughtWorks; and Paul Slater, Wadeware LLC 相關(guān)鏈接 Microsoft® patterns & practices 庫 http://www.microsoft.com/resources/practices/default.mspx Application Architecture for .NET: Designing Applications and Services http://msdn.microsoft.com/library/en-us/dnbda/html/distapp.asp 摘要:本章介紹了應用程序可用來(lái)連接和使用網(wǎng)絡(luò )資源以及客戶(hù)計算機上組件或進(jìn)程的許多方法,并且討論了每種方法的優(yōu)點(diǎn)和缺點(diǎn)。 ![]() 本頁(yè)內容
按照定義,智能客戶(hù)端需要連接到其他資源并與這些資源進(jìn)行通訊,并且構成分布式應用程序的一部分。這些資源可以是客戶(hù)端進(jìn)程或組件,也可以是網(wǎng)絡(luò )資源,如 Web 服務(wù)。 本章分析智能客戶(hù)端與其他資源之間的通訊的性質(zhì)。本章將考察可用來(lái)連接和使用其他進(jìn)程、組件或遠程服務(wù)中的資源的不同技術(shù),并且討論如何對它們進(jìn)行取舍。最后,本章將分析如何最好地設計您的智能客戶(hù)端以連接到資源。 松耦合系統和緊耦合系統客戶(hù)端應用程序可以用不同的方式連接和使用其他進(jìn)程(包括本地進(jìn)程和網(wǎng)絡(luò )進(jìn)程)中的組件和服務(wù)。按照服務(wù)與客戶(hù)端之間存在多少耦合性對不同的方法進(jìn)行分類(lèi)是很有用的。 耦合性是指組件(在分布式系統中)互相依賴(lài)的程度??蛻?hù)端與它們同其進(jìn)行通訊的服務(wù)之間耦合的性質(zhì)可能影響智能客戶(hù)端設計的許多方面,包括互操作性、脫機功能、網(wǎng)絡(luò )通訊性能、部署以及維護注意事項。 緊耦合系統通常提供直接的對象到對象通訊,并且客戶(hù)端上的對象對遠程對象具有詳細的了解。這種緊耦合性可以防止對客戶(hù)端或服務(wù)器進(jìn)行單獨更新。因為緊耦合系統涉及直接的對象到對象通訊,所以對象通常比在松耦合系統中更為頻繁地交互,這樣,如果兩個(gè)對象位于不同的計算機上并且由網(wǎng)絡(luò )連接分隔,則可能導致性能和延遲問(wèn)題。 松耦合系統通常是基于消息的系統,此時(shí)客戶(hù)端和遠程服務(wù)并不知道對方是如何實(shí)現的??蛻?hù)端和服務(wù)之間的通訊由消息的架構支配。只要消息符合協(xié)商的架構,則客戶(hù)端或服務(wù)的實(shí)現就可以根據需要進(jìn)行更改,而不必擔心會(huì )破壞對方。 松耦合通訊機制提供了緊耦合機制所沒(méi)有的許多優(yōu)點(diǎn),并且它們有助于降低客戶(hù)端和遠程服務(wù)之間的依賴(lài)性。但是,緊耦合性通??梢蕴峁┬阅芎锰?,便于在客戶(hù)端和服務(wù)之間進(jìn)行更為緊密的集成(這在存在安全性和事務(wù)處理要求時(shí),可能是必需的)。 所有與遠程服務(wù)或組件通訊的分布式客戶(hù)端都具有某種程度的耦合性。您需要了解各種松耦合方法和緊耦合方法具有的不同特征,以便為您的應用程序選擇合適程度的耦合性。 通訊選項當您設計智能客戶(hù)端應用程序時(shí),您可以從多種將其連接到其他資源的方法中進(jìn)行選擇,這些方法包括:
.NET Enterprise Services您可以使用 .NET Enterprise Services 提供對托管代碼組件和應用程序的 COM+ 服務(wù)基礎結構的訪(fǎng)問(wèn)。.NET 組件依賴(lài) COM+ 為其提供許多組件服務(wù),如:
使用 COM+ 服務(wù)的 .NET 組件稱(chēng)為服務(wù)組件。因為您的服務(wù)組件以 COM+應用程序為宿主,所以它們必須可供該應用程序訪(fǎng)問(wèn)。這就為服務(wù)組件帶來(lái)了一些注冊和配置要求:
如果程序集包含被配置為進(jìn)程外應用程序的服務(wù)組件,則應該將相應的程序集放到全局程序集緩存中。如果程序集包含被配置為進(jìn)程內庫的服務(wù)組件,則不必將其放到全局程序集緩存中,除非它們位于與應用程序不同的目錄中。如果您以這種方式部署同一版本服務(wù)組件的多個(gè)副本,則 COM+ 目錄包含該組件的所有實(shí)例的全局配置;您無(wú)法逐個(gè)副本地對它們進(jìn)行配置。 下面的代碼示例顯示了一個(gè)需要事務(wù)的組件,并且提供了一種在該事務(wù)內向數據庫中寫(xiě)入數據的方法。 using System.EnterpriseServices; [Transaction( TransactionOption.Required )] public class CustomerAccount : ServicedComponent { [AutoComplete] public bool UpdateCustomerName( int customerID, string customerName ) { // Updates the database, no need to call SetComplete. // Calls SetComplete automatically if no exception is thrown. } } 服務(wù)組件通??梢栽谑状芜\行時(shí)動(dòng)態(tài)注冊。這種類(lèi)型的注冊稱(chēng)為惰性注冊。當托管代碼應用程序首次嘗試創(chuàng )建服務(wù)組件的實(shí)例時(shí),公共語(yǔ)言運行庫 (CLR) 將注冊程序集和類(lèi)型庫,并且配置 COM+ 目錄。對于特定版本的程序集,注冊只發(fā)生一次。通過(guò)惰性注冊,您可以使用 Xcopy 部署來(lái)部署服務(wù)組件,并且無(wú)須顯式注冊服務(wù)組件就可以在開(kāi)發(fā)周期中使用它們。 惰性注冊是注冊服務(wù)組件的最容易的方法,但它只在運行這些服務(wù)組件的進(jìn)程具有管理特權時(shí)才有效。而且,任何被標記為 COM+ 服務(wù)器應用程序的程序集都要求顯式注冊;對于調用托管服務(wù)組件的非托管客戶(hù)端而言,動(dòng)態(tài)注冊不起作用。如果使用服務(wù)組件的進(jìn)程不具有動(dòng)態(tài)注冊所需的特權,則您需要使用 .NET 框架隨附的 Regsvcs.exe 工具顯式注冊包含該服務(wù)組件的程序集。 惰性注冊和 Regsvcs.exe 都需要客戶(hù)計算機上的管理權限,因此如果您的應用程序包含服務(wù)組件,則無(wú)法使用非接觸式部署來(lái)部署它。有關(guān)詳細信息,請參閱第 7 章:部署和更新智能客戶(hù)端。 可以用多種不同的方式托管和訪(fǎng)問(wèn)服務(wù)組件。它們可以由 ASP.NET應用程序托管并通過(guò) HTTP 訪(fǎng)問(wèn),或者可以通過(guò) SOAP 或 DCOM(默認設置)訪(fǎng)問(wèn)它們。但是,如果 COM+ 服務(wù)需要與調用一起流動(dòng)(例如,如果您需要用戶(hù)的標識或分布式事務(wù)從您的應用程序流動(dòng)到服務(wù)組件),則 DCOM 是唯一可行的解決方案。 注 如果您使用 DCOM 與 COM+ 應用程序通訊,則需要將 interop 程序集部署到客戶(hù)計算機,就像您部署傳統 COM 組件那樣。 Enterprise Services 具有許多您可以在智能客戶(hù)端應用程序中使用的強大組件功能。然而,您通常只應該在單個(gè)進(jìn)程內、在單臺客戶(hù)計算機上或者在服務(wù)器上的服務(wù)邊界內使用這些功能。由于 Enterprise Services 所具有的緊耦合性質(zhì),它們通常不是在智能客戶(hù)端應用程序和位于遠程系統上的服務(wù)之間進(jìn)行通訊的最佳選擇。如果您的智能客戶(hù)端應用程序需要在本地使用 COM+ 服務(wù)(例如,事務(wù)支持、對象池或基于角色的安全性),請使用 Enterprise Services。 有關(guān) Enterprise Services 的詳細信息,請參閱 .NET Framework Developer‘s Guide 中的“Writing Serviced Components”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconwritingservicedcomponents.asp?frame=true。 .NET remoting.NET remoting 提供了靈活且可擴展的遠程過(guò)程調用 (RPC) 機制,.NET 組件可以通過(guò)該機制進(jìn)行通訊。通過(guò) .NET remoting,您可以使用多種通訊協(xié)議(如 HTTP 或 TCP)、數據編碼選項(包括 XML、SOAP 和二進(jìn)制編碼)和各種對象激活模型。它可以提供在對象之間進(jìn)行通訊的快速而有效的手段。 .NET remoting 使您可以通過(guò)使用顯示為遠程對象的代理對象,像調用本地對象一樣調用遠程對象。.NET remoting 基礎結構通過(guò)屬性和方法調用處理客戶(hù)端代碼和遠程對象之間的交互,在此期間對在它們之間傳遞的數據進(jìn)行編碼,并且管理遠程目標對象的創(chuàng )建和刪除。 .NET remoting 基礎結構要求客戶(hù)端具有關(guān)于遠程對象的公共方法和屬性的詳細知識,以便提供客戶(hù)端代理。確??蛻?hù)端具有該知識的一種方法是向客戶(hù)端分發(fā)該遠程對象的完整實(shí)現。然而,更為有效的方法是將公共方法和屬性包括到接口定義中,并且將這些接口編譯為它們自己的程序集。然后,客戶(hù)端可以使用接口程序集來(lái)提供適當的代理,而遠程對象可以使用接口程序集來(lái)實(shí)現必要的功能。而且,使用該技術(shù)時(shí),您無(wú)須將完整的遠程對象重新分發(fā)到客戶(hù)端,就能夠更新這些遠程對象的實(shí)現。 您可以用多種方法來(lái)管理遠程對象的生存期??梢园凑招枰獎?chuàng )建對象以滿(mǎn)足單個(gè)請求,或者可以通過(guò)使用租用機制更細致地控制它們的生存期 — 此時(shí),客戶(hù)端維護對遠程對象的租用,并且只要客戶(hù)端希望使用遠程對象,就必須使遠程對象保持活動(dòng)。.NET remoting 還可以保證對于所有客戶(hù)端,只存在一個(gè)對象實(shí)例。您可以根據您對狀態(tài)管理和可伸縮性的要求,選擇應用程序的生存期。 .NET remoting 的可擴展基礎結構使您可以創(chuàng )建自定義信道和接收器。自定義信道使您可以定義通過(guò)網(wǎng)絡(luò )傳輸數據的方式。例如,您可以定義自定義信道以實(shí)現自定義有線(xiàn)協(xié)議。自定義接收器使您可以截獲在對象之間發(fā)送的數據,并對其執行操作。例如,您可以定義自定義接收器在傳輸前后對數據進(jìn)行加密或壓縮。 .NET remoting 具有用于在對象之間進(jìn)行通訊的強大且可擴展的機制。但是,由于它的緊耦合性質(zhì),在某些情形下它可能并不適合。.NET remoting 在客戶(hù)端和服務(wù)器都需要 .NET 實(shí)現的對象;因此,對于要求在不同環(huán)境之間具有互操作性的情形,它并不適合。對于在客戶(hù)端和服務(wù)器之間采用緊耦合 RPC 風(fēng)格交互并不適當的情形,.NET remoting 也是不適合的。默認情況下,.NET remoting 不會(huì )提供任何內置的加密機制或用于在對象之間傳遞用戶(hù)標識或事務(wù)的機制。對于這些情形,應該使用 Enterprise Services。 但是,對于在客戶(hù)計算機上或服務(wù)邊界內不同進(jìn)程中的對象之間的通訊而言,以及對于不同應用程序域中的對象而言,.NET remoting 都是一種很好的選擇。 有關(guān)使用 .NET remoting 的詳細信息,請參閱“An Introduction to Microsoft .NET remoting Framework”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/dndotnet/html/introremoting.asp?frame=true。 有關(guān)對 Web 服務(wù)和遠程處理進(jìn)行取舍的信息,請參閱“ASP.NET Web Services or Remoting: How to Choose”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/dnbda/html/bdadotnetarch16.asp?frame=true。 消息隊列借助于 Microsoft Windows 消息隊列,您可以很容易地通過(guò)發(fā)送和接收消息,快速而可靠地與應用程序通訊。消息處理為您提供了有保證的消息傳遞以及執行許多業(yè)務(wù)過(guò)程的可靠方式。消息隊列提供了一種您可以在智能客戶(hù)端應用程序內使用的松耦合通訊機制。消息隊列具有下列功能:
使用消息隊列的應用程序可以通過(guò)使用 System.Messaging 命名空間中的類(lèi)來(lái)發(fā)送消息以及從隊列中讀取消息。Message 類(lèi)用于封裝要發(fā)送到隊列的消息,而 MessageQueue 類(lèi)提供了對特定隊列及其屬性的訪(fǎng)問(wèn)。 您需要在任何使用消息隊列的計算機上安裝和配置它。Windows 桌面操作系統和 Microsoft Windows CE .NET 都可以使用消息隊列,從而使您可以在移動(dòng)設備(如 Pocket PC 設備)上使用它。 要與提供基于消息的訪(fǎng)問(wèn)的服務(wù)交互,消息隊列是一種很好的選擇。您可以使用消息隊列與其他裝有消息隊列的系統通訊。盡管您可以使用連接工具包與其他消息處理系統(如 IBM 的 MQSeries)通訊,但與其他系統之間的互操作性是有限的。 有關(guān)使用消息隊列的詳細信息,請參閱 Microsoft Platform SDK 文檔資料中的“Message Queuing (MSMQ)”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/msmq/msmq_overview_4ilh.asp?frame=true。 有關(guān) MSMQ-MQSeries 跨接編程的信息,請參閱“Programming Considerations Using MSMQ-MQSeries Bridge Extensions”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/his/htm/_sna_programming_considerations_using_msmq_mqseries_bridge_extensions_appl.asp。 Web 服務(wù)Web 服務(wù)是具有下列功能的應用程序組件:
Web 服務(wù)的基于 SOAP 的 XML 消息可以具有顯式(結構化和類(lèi)型化)部分或寬松定義部分(使用任意 XML)。這意味著(zhù) Web 服務(wù)既可以是松耦合的,也可以是緊耦合的,并且可用于實(shí)現基于消息或 RPC 風(fēng)格的系統,具體取決于環(huán)境的準確性要求。 您可以使用 Web 服務(wù)在異類(lèi)環(huán)境中的組織內部以及組織之間生成模塊化的應用程序。這些應用程序可以與種類(lèi)繁多的實(shí)現、平臺和設備互操作。任何能夠通過(guò) HTTP 發(fā)送 XML 的系統都可以使用 Web 服務(wù)。因為 Web 服務(wù)是基于標準的,所以用不同語(yǔ)言編寫(xiě)以及位于不同平臺上的系統可以相互使用對方的服務(wù)。這通常被稱(chēng)為面向服務(wù)的體系結構。 用于 Web 服務(wù)的主要標準是 HTTP、SOAP、UDDI 和 WSDL。Web 服務(wù)與傳輸協(xié)議無(wú)關(guān)。但是,HTTP 是最常見(jiàn)的用于傳輸 SOAP 消息的機制。因此,Web 服務(wù)非常適合于橫跨網(wǎng)絡(luò )和企業(yè)防火墻的應用程序,如需要通過(guò) Internet 與服務(wù)通訊的智能客戶(hù)端。 許多 Web 服務(wù)標準正在出現,以擴展 Web 服務(wù)的功能。Microsoft Web Services Enhancements (WSE) 2.0 支持正在出現的 Web 服務(wù)標準,如 WS-Security、WS-SecureConversation、WS-Trust、WS-Policy、WS-Addressing、WS-Referrals、WS-Attachments 和 Direct Internet Message Encapsulation (DIME)。WSE 提供了編程模型,以實(shí)現它所支持的各種規范。有關(guān)詳細信息,請參閱“Web Service Enhancements (WSE)”,網(wǎng)址為:http://msdn.microsoft.com/webservices/building/wse/default.aspx。 有關(guān) SOAP 的詳細信息,請參閱“Understanding SOAP”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/dnsoap/html/understandsoap.asp。 有關(guān) WS-Security 的詳細信息,請參閱“Web Services Security Specifications Index Page”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/dnglobspec/html/wssecurspecindex.asp。 Web 服務(wù)通訊可以是粗粒度的、獨立的和無(wú)狀態(tài)的。但是,與其他形式的通訊相比,Web 服務(wù)通常是非常詳細的。 Web 服務(wù)是生成大多數智能客戶(hù)端應用程序的最佳方法。高度的互操作性使 Web 服務(wù)能夠與各種各樣的應用程序通訊。使用廣泛采用的標準意味著(zhù)它們通常只須進(jìn)行最低限度的額外配置(與要求打開(kāi)專(zhuān)用端口的其他技術(shù)比較),就可以通過(guò)網(wǎng)絡(luò )基礎結構和防火墻,Microsoft Visual Studio® 開(kāi)發(fā)系統中對于 Web 服務(wù)的強大支持意味著(zhù)您可以在單個(gè)開(kāi)發(fā)環(huán)境中使用它們。 在性能極高的應用程序中,Web 服務(wù)可能并不適當,因為它們太詳細,并且與其他消息處理技術(shù)(如 .NET remoting 和消息隊列)相比,它們包含相當繁重的消息有效負載。 有關(guān)使用和生成 Web 服務(wù)的詳細信息,請參閱 .NET Framework Developer‘s Guide 中的“XML Web Services Created Using ASP.NET and XML Web Service Clients”,網(wǎng)址為:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconaspnetbuildingwebservicesaspnetwebserviceclients.asp?frame=true。 選擇通訊選項不同的通訊選項適用于不同的場(chǎng)合。表 3.1 概括了用于建立連接的不同選項。 表 3.1 智能客戶(hù)端選項
如表 3.1 所示,在某些情況下,Enterprise Services、NET remoting 和消息隊列可能是用于在智能客戶(hù)端和連接的資源之間進(jìn)行通訊的適當技術(shù)。但是,在大多數情況下,Web 服務(wù)是用于將智能客戶(hù)端應用程序連接到服務(wù)的最佳機制。 圍繞 Web 服務(wù)通訊生成的體系結構可以在連接的環(huán)境和脫機環(huán)境中很好地工作,并且支持能夠自我描述且獨立的粗粒度、無(wú)狀態(tài)消息。對于 Internet 協(xié)議的依賴(lài)使得客戶(hù)端能夠廣泛分發(fā)給 Internet 上的每個(gè)人。 設計連接的智能客戶(hù)端應用程序當您設計您的智能客戶(hù)端時(shí),您應該考慮一些建議,包括:
使用粗粒度的、封裝的消息分布式網(wǎng)絡(luò )調用是代價(jià)高昂的操作。您不應該使用與設計本地接口相同的細粒度方法來(lái)設計您的外部接口。要避免消息之間存在消息依賴(lài)性,比較好的做法是將接口方法生成為獨立函數。這樣做可以使您不必編寫(xiě)復雜的跟蹤協(xié)調代碼來(lái)處理依賴(lài)于其他消息成功完成的消息的失敗。 避免分布式 ACID 事務(wù)分布式 ACID(原子、一致、獨立、持久)事務(wù)是資源密集型的,伴隨大量網(wǎng)絡(luò )通信以及掛起本地事務(wù)上的大量相互依賴(lài)的系統鎖。如果您的智能客戶(hù)端或服務(wù)正在等待答復,并且在收到該答復之前無(wú)法繼續工作,則分布式 ACID 事務(wù)可能阻止業(yè)務(wù)過(guò)程。 如果您的智能客戶(hù)端可能不加警告就切換到脫機模式,則分布式 ACID 事務(wù)的問(wèn)題將會(huì )惡化。在此情況下,客戶(hù)端可能對數據加鎖,并且在可以在服務(wù)器釋放該鎖之前進(jìn)入脫機模式。 如果您無(wú)法通過(guò)將接口分解為單獨的不連續消息來(lái)避免消息依賴(lài)性,則您具有許多處理事務(wù)的選項,并且還可以避免分布式 ACID 事務(wù):
避免在網(wǎng)絡(luò )中發(fā)送數據集數據集可能太大、太詳細,因而無(wú)法用作在多個(gè)層之間發(fā)送數據的通訊有效負載機制。取而代之,您應該使用數據傳輸對象 (DTO) 來(lái)減少發(fā)送到外部接口的消息有效負載。對于數據更改,您應該考慮只發(fā)送已更改的數據,而不是發(fā)送整個(gè)數據集。 有關(guān) DTO 的詳細信息,請參閱第 2 章:處理數據。 將大型數據集分解如果您試圖同時(shí)顯示大型數據集的所有內容,則它們可能在客戶(hù)端導致性能問(wèn)題。因此,您應該將它們分解為較小的數據集。以這種方式分解數據稱(chēng)為分頁(yè)。例如,與顯示電話(huà)目錄的全部?jì)热莶煌?,您可以選擇一次顯示一頁(yè)(例如,每屏按字母順序顯示 20 個(gè)記錄)。如果您將客戶(hù)端設計為使用分頁(yè),則應該確保對用戶(hù)界面進(jìn)行相應的設計,以便使用戶(hù)可以容易地在各個(gè)頁(yè)之間導航。 這一分解大型數據集的概念還適用于通過(guò)網(wǎng)絡(luò )與服務(wù)器進(jìn)行的通訊。如果您可以將數據分解為可管理的數據塊,則您隨后可以按照需要加載所需的數據,這種技術(shù)稱(chēng)為惰性加載。在電話(huà)目錄示例中,只有當前操作需要的數據將被加載,從而減小了對應用程序和網(wǎng)絡(luò )的影響,并且可能使二者的響應更為迅速。 要改善用戶(hù)體驗,可以在對即將到來(lái)的用戶(hù)請求進(jìn)行預測的基礎上,使用附加線(xiàn)程執行后臺處理以及與服務(wù)之間的通訊。 盡管對惰性加載的支持可能是智能客戶(hù)端應用程序設計的重要方面,但您應該記住應用程序的脫機要求。通過(guò)網(wǎng)絡(luò )傳輸的惰性加載數據可能會(huì )妨礙應用程序像您希望的那樣脫機工作。 將您的 Web 服務(wù)和程序集版本化當您將新版本的智能客戶(hù)端軟件發(fā)布到客戶(hù)端或者對該軟件進(jìn)行升級時(shí),應該創(chuàng )建新版本的程序集。如果您使用版本化的程序集,并且如果您將服務(wù)器服務(wù)設計為支持向后兼容接口,則可以支持多個(gè)版本的客戶(hù)端軟件。在發(fā)布新版本的 Web 服務(wù)時(shí),您應該通過(guò)規范的命名約定來(lái)區分它們??梢愿淖兏鱾€(gè)版本的命名空間,以便它們包含日期信息,從而能夠清楚正在與哪個(gè)版本的 Web 服務(wù)客戶(hù)端通訊。 有關(guān)處理多個(gè)版本的程序集的詳細信息,請參閱第 7 章:部署和更新智能客戶(hù)端。 小結智能客戶(hù)端需要訪(fǎng)問(wèn)資源(包括本地資源和遠程資源)才能正常工作。要成功地設計可靠的并且能夠迅速響應用戶(hù)操作的智能客戶(hù)端,您如何處理這一通訊可能非常關(guān)鍵。諸如性能、安全性和靈活性之類(lèi)的要求會(huì )影響到哪種連接選擇適合于您的環(huán)境。使用本章中的指導,您應該能夠確定哪些形式的連接適合于您的智能客戶(hù)端,然后相應地設計您的智能客戶(hù)端以及它們與之進(jìn)行通訊的資源。 |
聯(lián)系客服