[Android Pro] 開發一流Android SDK

來源:互聯網
上載者:User

標籤:tools   朋友   tis   頻繁   protobuf   ogr   邏輯   重載   先來   

cp from : 53558011

本篇文章已授權公眾號 guolin_blog (郭霖)獨家發布

自從前段時間離職後,因為個人的事情一直沒有選擇再工作,也導致原有的文章並沒有按時產出.最近個人的事情整理的也差不多了,恰好有不少朋友來問有關SDK開發方面的事情,在此就做個簡單的梳理,希望能協助各位.

目前更多開發人員熱衷於應用開發,極少數的開發人員才有機會從事SDK開發工作,而市面上關於SDK開發介紹的文章少之又少,以至於讓大家覺得SDK開發是相對比較難而且非常無聊的工作,今天我們就來簡單的聊聊SDK開發的哪點事.

關於SDK的解釋什麼是SDK

在開始本文之前,首先來聊聊SDK是個啥玩意.

SDK是Software Development Kit的縮寫,譯為”軟體開發套件”,通常是為輔助開發某類軟體而編寫的特定軟體包,框架組合等,SDK一般包含相關文檔,範例和工具.

SDK可以分為系統SDK和應用SDK.所謂的系統SDK是為特定的軟體包,軟體架構,硬體平台,作業系統等簡曆應用時所使用的開發工具集合.而應用SDK則是基於系統SDK開發的獨立於具體業務而具有特定功能的集合.

比如在進行Android 應用開發時,我們使用Google提供的系統SDK(Android SDK),而我們經常使用的友盟SDK,極光SDK則是基於系統SDK開發的.

明確SDK的概念之後,再來聊一聊這三個概念:Library,API,Framework

什麼是Library

Library即我們所說的庫,通常是一組或者幾組類的集合,通常是應用中某些功能的具體實現或者對系統已有功能的增強或補充.對Android開發人員而言,最常見的莫過於是Support Library,另外就是我們經常使用各種網路請求庫(OkHttp,Volley),資料庫操作,圖片載入庫(Glide,ImageLoader)等.

什麼是Framework

Framework即我們所說的架構,通常是系統或者應用的骨架,很多時候,它表現為一組抽象的構建及構件執行個體間互動的方法.因此,可以認為,Framework規定了應用的體繫結構,闡明了整體設計,寫作構件之間的依賴關係以及控制流程程.注意自處的Framework並不完全等同於你所熟知的Android Framework架構,可以認為Android Framework中體現了Framework的思想,並進行了實現.

什麼是API

API是Application Programming Interface,又稱為應用編程介面,是軟體系統不同組成部分銜接的約定。更加通俗的說就API就是我們常見和編寫的方法或函數.

小結

明確了上面提到的概念之後,現在就可以來描述這四者之間的關聯: 
SDK主要包含Framework,API及Library的三部分.Framework定義了SDK整體的可重用設計,規定了SDK各功能模組的職責以及依賴關係.其中個功能模組體現為Library.模組之間的內部通訊及SDK外部通訊(SDK對外提供服務的介面)則通過API進行.

另外完整的SDK還應該包含大量的樣本和其他工具.比如在Android SDK的tools目錄下提供了大量的輔助開發工具.

對我們而言,大部分情況下是為某種具體的業務需求開發對應的SDK,以便作為第三正提供給其他需求方使用.比如百度推送的SDK主要實現訊息推送功能,需求方只需要整合百度推送的SDK便可以使自己應用具備推送功能.

到現在已經介紹了SDK的主要構成,接下來我們重點來介紹SDK的實現目標以及在SDK架構中的一些核心點.

淺談SDK實現目標

上面介紹了開發中常見的概念,現在來談談SDK的實現目標.任何應用都應具備:簡潔易用,穩定,高效,輕量,SDK作為一種特定應用當然也不例外.

簡潔易用

按照”奧卡姆剃鬚刀”理論,一個好的產品對第三方使用者使用而言應該是簡潔易用,不用改讓使用者花費太長時間學習的.這對SDK同樣適用—SDK不應該對宿主應用有過多的代碼侵入,也不應該有複雜頻繁的接入工作.比如當開發人員需要使用SDK的服務時,只需要在緣由的代碼中新增一行即可.常見的SDK初始化如下:

public class Ad{    @TargetApi(9)    public synchronized static void init(Context context, SdkParams params) {        //省略多行代碼    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

當我們需要使用該SDK的服務時,通過一行代碼便可啟用Ad.init(this,params)

要保證較少的代碼侵入主要在對外提供服務時充分考慮到使用者的使用情境來設計出優良的API.一個優良的API在定義的時候應該滿足絕大數開發人員所預期的方式—語義上要求通俗易懂,使用上要求簡單可靠.

一個優良的API首先是簡單可靠的.在正常使用的情況下體現為穩定可靠的執行,在異常情況下體現為及時的告知使用者使用錯誤.初次之外,遵循一致的明明規則,並是所有的API呈現出一致的風格對開發而言無疑是個好訊息.

穩定

站在SDK使用者角度來看,我們期望第三方的SDK服務應該是穩定高效的,體現在提供穩定可靠的服務,在不影響宿主穩定性的前提下足夠的高效,這就要求我們SDK設計者在設計並實現SDK時要儘可能的做到以下幾點:

  • 對外提供穩定的API.SDK的API一旦確定,如無非常嚴重情況不可更改.作為提供服務方,發生API變更所帶來的變更成本非常大.
  • 對外提供穩定的業務.在穩定的API後,必須要有穩定的業務來支撐.
  • SDK運行時的穩定,作為服務提供者,我們必須確保SDK自身啟動並執行穩定,並且保證接入方不會因為我們的SDK產生不穩定的情況.
  • 版本穩定更新.和面向普通使用者的應用相比,SDK版本的迭代是非常緩慢的.並且需要儘可能的對開發人員屏蔽迭代過程,以免給開發人員帶來不必要的適配開銷.
高效

無論是普通的應用開發還是SDK開發,都應該考慮到效能問題,SDK設計者應該著重考慮以下問題:

  • 更少的記憶體佔用.在不使用多進程的情況下,SDK服務和宿主程式運行在同一進程中,這種情況下必須要求限制SDK記憶體的佔用,不能因為說因為我們SDK佔用太多的記憶體資源,導致應用的存活時間變短.
  • 更少的記憶體抖動.在佔用更少記憶體的前提下,SDK設計者必須刻意的減少反覆GC造成的記憶體抖動問題.
  • 更少的電量消耗.儘管很多時候無法對電量消耗做一個很好的權衡,但是仍然有一些可以參考的做法,比如減少使用耗電模組的時間.比如在使用定位服務時,不要求非常高的精度下優先使用網路定位而不是GPS定位.
  • 更少的流量消耗.
SDK整體架構設計

SDK的架構實現決定了SDK後續的維護難度,因此有必要在此對SDK整體架構中的一些點做些簡單的說明.

模組化開發

根據單一職責將系統拆分為不同的小模組,每個模組保持相對獨立。

模組之間通過協議或介面通訊,以減少相互之間的依賴耦合.模組內部按照設計的幾大原則進行實現,以保證模組本身可以靈活實現

對於現代開發而言,模組化是常用的手段,從宏觀角度來看,模組是系統最小的組成單元.

組件化開發

組件開發同樣是個老生常提的概念,但從我個人的感受來說,組件是對邏輯的封裝,並具備單個可移植性.比如可以把日誌記錄做成一個組件,之後它可以被輕鬆在應用在不同的項目中.對於android 開發人員而言,Android 提供的每個UI 控制項同樣也是組件,比如Button,TextView等.

在明確了組件這一概念之後,組件化開發也就不難理解:所謂的組件化就是將整個項目劃分成多個模組,幾個模組或者單個模組作為一個組件,開發過程中我們可以對每個組件進行並行開發,最後發布時通過依賴將組件合并成完整的應用.

那為什麼要使用組件化呢? 
隨著android的逐漸成熟,現在的app業務越來越複雜,與此同時,android工程也變得日益龐大,程式碼數十幾萬已經是常態,此時有幾個問題便會凸顯出來:

  1. 工程任何一點改動都會造成整個工程的重新編譯.記憶最深的就是早期在沒有進行組件化的時候,龐大的工程動輒需要十幾分鐘的編譯時間,一杯茶的時間就出來了,很多時候,不得不眼巴巴的等著,儘管現在可以使用facebook出品的buck以及來自阿里的feeline來加速編譯過程,單仍然不夠.
  2. 整個工程中充斥的大量重複或者冗餘的子模組,業務耦合度非常高,牽一髮而動全身.這就造成了”老人不敢改,新人無法改”,因為誰也不能預知在做修改之後,會產生什麼影響.
  3. 協作開發基本上是不可能的,天知道彼此在做什麼.代碼合并的的時候更是令人痛苦.
  4. 不方便測試.高度耦合的業務和模組導致無法下手進行測試,只能草草了事.

通過引入組件化,上面遇到的問題便可迎刃而解.在SDK當中,根據實際情況對其進行組件化,比如我們將分享功能組件化,可以輕鬆的支援多種渠道的分享,在需要更新分享功能時,可以對其進行單獨的編譯和測試.

通過組件化,我們也可以輕鬆的實現SDK的定製功能,通過編寫編譯指令碼,我們可以決定哪些組件被依賴,最終合并到完整的應用當中.比如友盟中的提供的可定製分享組件(如)的原理就是如此.

外掛程式化開發

什麼是外掛程式化開發這裡就不做介紹了,一方面外掛程式化並不是個新概念,另外就是外掛程式化到目前為止理論層次上已經非常成熟,不想15念開始研究的時候資料相對較少.

在SDK中為什麼使用外掛程式化呢?SDK不同於普通應用,不能頻繁的進行更新,以免讓開發人員覺得SDK不穩定或者讓開發人員頻繁的整合.SDK看起來變化較慢,實則變化頻繁.就以以前做的廣告SDK而言,有時候經常需要對某類機型進行資料擷取或者及時更新反作弊模組,在沒有使用外掛程式化之前,解決該問題是非常麻煩的.但是在我們利用外掛程式化之後,解決該問題就變得非常容易:我們將SDK整體劃分為兩部分:宿主和外掛程式.宿主只向開發人員提供必要的服務介面,並提供了自訂外掛程式載入器.而核心的邏輯則是存在於外掛程式中.當需要採集資料的時候,只需要由開發人員開發好資料擷取外掛程式並下發到指定裝置即可;當需要修複SDK缺陷時,同樣也只需要下發新的外掛程式包即可.

通過在SDK使用外掛程式化方案,可以有效對開發人員屏蔽手動更新的過程.宿主相對穩定,一旦確定,一般不會變動,而後續的業務變化則只需要通過更新外掛程式來支撐.

除了上面談到的利用外掛程式化解決動態更新之外,通過將整個工程分為宿主和外掛程式可以實現宿主的並行開發和分開編譯,並且能有效解決方案數65535的限制.在沒有使用外掛程式化之前,我們整個項目是由很多組件通過依賴形成的龐大工程,不得不通過

SDK初始化

和應用開發不同,很多情況下SDK沒有自身的上下文Context,而必須要藉助應用提供.SDK初始化的常見做法:Ad.init(Context context,AdParams params),我們往往推薦開發人員在應用Application組件中的onCreate()中去掉用該方法,這就意味著該初始化過程是同步的,假如SDK本身初始化時間較長,就會影響應用的啟動速度.

在這種情況下,作為SDK的設計者必須著手解決該問題.通常將SDK服務進一步劃分成核心服務和輔助服務,之後通過並行初始化和延遲初始化的手段來減少SDK初始化耗時.曾經在我所負責的廣告SDK中,有開發人員反饋我們的SDK啟動較慢,通過對整個SDK啟動流程進行分析後,我們將外掛程式載入服務和雲控服務並行初始化,而對於像Log Service則採用顏值初始化,通過該手段有效減少了初始化耗時

雲更新控制

雲控服務作為一種服務端控制用戶端的手段在SDK中開發中非常重要,現在的SDK開發可以不支援外掛程式化,但是必須要提供雲控服務,以便讓服務端能控制SDK,比如在不需要進行資料擷取的時候,可以通過雲控服務關閉SDK採集功能,在需要的時候在將其開啟.

對本身是基於外掛程式化開發的SDK而言,雲控服務更是不可或缺.

從實現的角度而言,雲控服務分為服務端主動和用戶端主動.服務端主動是指服務端會將最新的雲控開關的資訊推送到SDK,而用戶端主動則是SDK在進行操作之前會首先請求雲控資訊.對有推送開發經營的同學而言,這非常容易理解,就是像是為了實現訊息推送功能,我們可以通過用戶端輪訓也可以通過服務端保持長串連進行訊息推送一樣.

安全SDK自身安全

為了區分接入者並挑高SDK自身安全性,我們通常會為開發人員分配api key和api secret,SDK會讀取開發人員配置的api key和api secret,並用於隨後的網路通訊中.這是非常常見的做法,比如當你整合極光推送SDK的時候,它也許需要你提供api key和api secret,如果沒有則需要到官網進行申請.

核心邏輯採用C/C++

為了安全起見,資料加密類,模組演算法類都都應該採用NDK開發,將其封裝在so檔案當中.有很多開發人員不明白為什麼這樣會增強安全性.這裡我們簡單的做個說明.由於.so檔案是通過c/c++編譯出的檔案,相對於java的反編譯檔案來說,可讀性更差,另外大部分的Android開發人員並不具備較深的C/C++能力,因此一定程度上增加了被破解的能力.

通訊加密

針對實際情況對通訊協議進行加密,具體是採用對稱式加密還是非對稱式加密,則需要根據實際情況做選擇.另外,請儘可能使用https來代替http.

裝置安全

在很多情況下,比如廣告SDK中,有一些開發人員會通過虛擬機器來刷廣告,因此有必要針對此情況做判斷.一旦SDK檢測出非法請求後可以採取兩種方案,一種是SDK拒絕服務,另外一種則是正常服務,SDK會將作弊資訊上傳至伺服器,以便後端服務定向排除資料.

減少傳輸資料大小

在設計SDK和服務端通訊之間的資料協議時,需要根據實際情況考慮,但有以下幾條建議值得我們接受:

  • 如果對傳輸的資料大小有要求,建議對資料進行壓縮.
  • 可以採用json/xml/Protobuf等協議,如果它們仍然不能滿足則可以考慮自訂二進位協議.
選擇支援最低系統版本

作為SDK的設計者,面臨一個很大的問題是我們不得不考慮開發人員應用所支援的系統最小版本,但是在SDK發布之前,我們並不知道會什麼樣的開發人員使用我們提供的服務,因此為了讓SDK支援更廣泛的裝置,我們需要降低最低支援的系統版本.比如現在失眠上主流的系統版本是Android 5.0,那麼對SDK而言,起碼要支援到Android 4.0,甚至是Android 2.3.

降低最低支援版本看起來很容易,但是我們不得不做更多的工作來確保SDK能表現出一致的工作行為(通常,我們在SDK內部檢測當前系統版本來確定哪些方法可以被調用).更殘酷的真相是我們花費了很大的精力去支援2.3,但來自2.3系統版本的請求量卻連1%都不到.

許可權管理

Android中任何開發都避不開許可權申請.作為SDK的設計者,對於許可權遵循”如無必要,無需增加”,換句話說就是用不到的許可權,就不要加上去,這也是我們所謂的最小許可權原則,該原則同樣適用於普通應用開發.

在剛接觸SDK開發時,某些早期功能需要某些許可權,但是後期該功能被砍掉了,但是許可權卻忘記去掉,這就導致不必要許可權仍然存在的情況.

另外過多的許可權申請,會讓開發人員懷疑你的目的.比如一個廣告SDK的你申請照相機許可權是想幹嘛?恩,我懷疑你在偷拍我….好吧,這裡我只是開個玩笑.

另外,從android 6.0以上,google改變了許可權申請的策略,因此需要單獨對此做適配.

Log Service

無論系統大小,Log Service是基本的服務.一個良好的Log Service能夠協助我們快速的發現問題,定位缺陷,從而獲得問題的解決方案.

SDK的Log Service和其他常見的Log Service並無太大的不同,但是要保證以下幾點:

  1. Log Service能夠記錄有效資訊,在SDK要關鍵位置進行打點.
  2. Log Service上傳日誌資訊到伺服器時,要保證最大的可靠性,不能發生上傳失敗後拋棄日誌的情況.
  3. Log Service不能影響對正常的操作流程有過多的效能影響.SDK產生的日誌資訊往往是非常多的,因此必須考慮日誌IO操作所帶來的開銷.
深究API設計

API的設計在任何開發中都是非常重要的,很多時候軟體的品質好不好在API的設計可以得到體現.在普通的應用開發中,API只會在應用開發人員間流通而不會暴露給非本應用開發的其他人員,但是SDK作為一種服務,需要向開發人員暴露一部分API.通常我們將內部流通的API稱之為內部API,而開放給開發人員的稱之為SDK API.

兩者使用情境雖然不同,但是都遵循著一些通用的設計規則,這裡無法細說,只列出我認為需要重點關注的十一條原則:

方法名能夠表明其用途

方法名是理解方法含義的第一渠道.一個好的方法名首先是能夠向他人展示自身功能,這樣做的好處就是能夠減少不必要的溝通成本,對於開發人員而言,還有什麼比直接讀代碼更直觀呢.

參數的合法性檢驗

對參數進行合法性檢驗是非常重要的,請不要想當然的認為可以用運行時異常來代替.當合法性校正不通過時,針對方法許可權不同分別對應不同不同的處理策略:

  • 對於公開方法通過顯示檢查拋出異常的方式,並且使用javadoc的@throw來說明拋出異常的原因
  • 對於私人方法通過斷言的方式來檢查參數的合法
  • 檢查構造方法的參數的合法性,以使對象處在統一狀態 
    需要注意,如果檢查的代價太大,需要綜合考量,比如如果接受的是一個很大的List,此時檢查的代價可能很大
方法要明確其單一的功能

一個方法應該具有單一的功能,儘可能做更少,但是更專的事情.這也是我們常說的單一職責原則.另外一定要記住寧可提供小而美的方法也不要提供大而全的方法,經驗正面大而全的方法往往發生變動,產生風險的可能性更高,因此不如提供更小的方法以便組合使用

方法異常問題

對於需要暴露給開發人員的方法要及時的拋出可查異常來協助開發人員在編譯階段發現問題,另外,對於運行時異常,SDK設計者必須保證該類異常不會導致宿主程式出問題並且需要告知開發人員.

方法許可權控制

方法的許可權也是需要著重考慮的,SDK設計者必須同時從安全和業務的角度考慮哪些方法是可公開的,哪些是不可公開以及哪些是靜態.

避免過長參數

過長的參數會造成記憶上困難,需要謹慎對待.在無法避免過長參數的情況下,需要考慮其他的方法進行解決:

a. 通過使用Builder模式來實現 
b. 通過使用輔助類,通常採用靜態內部類的方式,具體見靜態內部類的使用 
c. 通過將多個參數封裝成類對象 
d. 通過將參數拆解成多個方法的參數

謹慎使用方法重載

重載不應該讓使用者感到疑惑,即不應該出現這種情況:同樣的參數,但是開發人員不能明確哪個方法會被執行.換言之就是不要產生歧義性.

另外需要注意,不要存在參數類型經過自動轉換就可以運行在另外一個方法的情況,我曾經在code review中看到這樣的代碼:list中的remove(Object)remove(int),請務必保證自己不會犯類似的錯誤.儘管在java當中能夠使用重載,但是我不建議使用,尤其是不要重載變長參數,在需要重載的時候寧可使用不同方法名來代替也要好的多.關於這點java中提供的ObjectOutputStream類給我們做了很好的示範:它的write對於每個基本類型都有一個變形,比如寫出字元,寫出boolean等操作,我們發現設計者,並沒有使用重載將其設計成write(Long l),write(Boolean b),而是將其設計為writeLong(l),writeBoolean().

對於建構函式,則可以通過是用靜態工廠的方式來代替重載.

謹慎使用變長參數

多數情況下不需要使用變長參數,一般方法的參數在5個以上的時候,才 建議使用變長參數.在還有其他非變長參數的情況下,我覺得變長參數放在形參列表的最後.

避免方法直接返回NUll

對於需要返回數組或這集合的方法,不要返回null.比如我們去買糕點店買麵包,麵包沒了是一種正常狀態,就不應該返回null,而是返回長度為0的數組或集合.

必要時進行保護性拷貝

當類接受來自用戶端的對象或者需要向用戶端返回對象,如果該類不能容忍進來的對象再發生變化,那麼有必要對對象進行保護性拷貝.另外要注意參數的合法性檢驗發生在保護性拷貝之後. 
需要注意的是如果需要進行保護性拷貝的對象非常大,比如list集合中存在十多萬個對象,需要權衡處理.

這十一條原則是我在團隊中推廣並要求嚴格遵守的,下面,將對這十條原則分別進行說明.

SDK開發流程

關於SDK開發流程,我會從以下三個方面寫:一時團隊中如何協同開發,二是SDK的持續整合,三是SDK多倉庫拆分和管理.

這三方面會再另外的篇章中展現(具體什麼時候寫完目前還未確定)

SDK版本管理原則SDK 版本號碼命名及修改原則

SDK版本號碼命名和我們以往的命名規則並無太大不同,通由4部分組成,格式為: 
V主要版本號子版本號碼階段版本號碼_日期版本號碼加希臘字母片本號.比如V1_1_2_161209_beta.

希臘字母片本號說明
  • Alpha版:自我裝載版,此版本表示該軟體在該階段主要是以實現功能為主,Bug相對較多,需要繼續修改,通常只在內部流通流通而不對外開放.
  • Beta版:正式發行前小眾測試版,該版本相對Alpha已經有了很大的改進,不存在嚴重的Bug,但還是存在一些缺陷,需要進一步的測試以檢查和消除Bug.
  • RC版:該版本已經相當成熟,不存在導致錯誤的Bug.與正式版相差無幾.
  • Release版:該版本意味著”最終版本”,是最終交付使用者或者公開發布的版本,也稱為標準版.需要注意的是,該版本在發布的時候回以符合R來代替Release單詞.
版本號碼修改規則
  1. 主要版本號變化:當功能模組有較大的變化或者整體架構發生變化
  2. 子版本號碼變化:當功能有一定變化
  3. 階段版本號碼變化:一般是Bug修複或者較小的變動,根據反饋,需要經常發布修訂版本.
  4. 日期版本號碼(161209):用於記錄修改項目的當前日期,每天對項目的修改都要更改日期版本號碼.
  5. 希臘字母片本號:此版本?號用於標註當前軟體處於那個開發階段,當軟體進入到另一個階段是需要修改.
API版本管理

和普通應用API版本管理不同,SDK設計者需要著重關注SDK API的管理.原則上SDK API一旦公開發布後其狀態(簽名和具體實現)應為不可變.

對於特殊情況下API的變更,需要遵守”開閉原則”,即一個類,模組,方法應該對擴充開發,對修改關閉.這就要求我們做到以下幾點:

  1. 在需要調整SDK API時,優先選擇添加新方法,而不是在原方法上修改.對於實現相同功能的新方法,儘可能的要相容原始方法.
  2. 在需要廢除某些方法時,需要在正式版發版前使用@deprecated標識,並給出替代方案和廢棄的時間(通常是SDK版本號碼)
接入文檔和API文檔版本管理

接入文檔是用來告訴SDK使用者,如何使用SDK,使用的詳細步驟和可能發生的問題,每個公司會有自己的一套規則,這個不需要做太多的解釋.

另外,接入文檔通常分為兩份:內部版和公開版.內部版通常用於內部開發人員和測試人員,資訊較為詳細,而公開版則是面向開發人員,相比內部版會省略的一些資訊.

API文檔其實就是對SDK API的更詳細說明,類似java中的api doc,可以藉助jdk的內建javadoc直接產生,當然在android studio也提供了便捷的產生方式.

無論是接入文檔還是api說明文檔,其變更一般發生在SDK版本發生變化時.當SDK發生變更時,文檔必須隨之更新,不能出現SDK更新後說明文檔不與之匹配的情況.

整合Demo版本管理

整合Demo通常是一個簡單的app,用來展示如何快速的接入SDK.其版本變更策略和SDK版本的變化保持一致.

總結

SDK開發中需要關注的點非常多,每個點都不能用三言兩語完成的,後面會在此基礎上慢慢的補充.

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。53558011文章標籤: sdk第三方FrameworkLibrary經驗個人分類: 白話Android開發所屬專欄: 第三方SDK開發隨想錄

[Android Pro] 開發一流Android SDK

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.