天天看點

深入解讀阿裡雲SDK體系

前言

在今天,OpenAPI 的應用已經越來越廣泛,尤其是開放服務和雲計算領域中。作為“內建”或者“被內建”的主要實作方案,今天的應用研發中,很少沒有涉及到 OpenAPI 的使用的。那麼對于一個開發者而言,使用 OpenAPI 的主要方式自然是 SDK,如果一個 OpenAPI 服務沒有提供對應語言的 SDK,那麼使用它之前的第一件事情便是寫一個對應的 SDK。

深入解讀阿裡雲SDK體系

為 OpenAPI 編寫 SDK 通常而言并不是一件困難的事情,無外乎是熟悉 OpenAPI 的參數,封裝成 Client 對象後,調用底層 HTTP 庫,進行發送和處理傳回資料,與前端的 AJAX 調用沒什麼兩樣。是以通常情況下要完成一個 SDK 的編寫,并不是什麼難點。但是,如果作為一個雲計算廠商,提供令客戶滿意的 SDK 并不是一件容易的事情,因為在雲計算廠商下,我們面臨着更複雜的情況:

-雲計算廠商的産品線多,每一個産品線的 SDK 不一定能被别的産品線所重用。

-雲計算廠商的客戶分布廣泛,我們的客戶使用任何程式設計語言的可能都存在。

以阿裡雲的産品為例,它一共有上百個産品,如果我們要支援到 10 門程式設計語言的客戶,那就不是一個 SDK 的事情了,它是上千個 SDK 的事情。任何事情一旦上規模,它都不再是簡單的事情。

SDK 研發的挑戰

在雲計算廠商的 SDK 研發中,我們的挑戰主要有如下這些:

-由于涉及到的程式設計語言衆多,能支援到的語言數量有限,即使支援了某門語言,并不一定完全地照顧到了該語言下的開發者習慣。

-來自衆多産品線的挑戰,語言數乘以産品數,這是一個規模化帶來的挑戰。支撐這麼大規模的 SDK,所需要的人力成本不低。

-即使支援到更多的語言,更多的産品,那麼随之而來的維護成本也是一個巨大的成本。

-為了保障維護的過程不帶來返工問題,品質保障的工作也少不了,同時支援多語言、多産品的品質保障,是不小的挑戰。

-SDK 的工作不僅僅是代碼本身,涉及相關的文檔、代碼示例等,對應的支援工作亦是不小的工作量。

最終,這些工作都是一脈相承的,是以一緻性是最大的挑戰,如何保障語言間、産品間、文檔等一緻,是雲廠商 SDK 研發中最大的挑戰。

多語言的挑戰

在過去,一些開放平台主要會公布一些 OpenAPI 的文檔,必要的簽名算法,以及 1 - 2 門主流程式設計語言的 SDK。其餘的程式設計語言下的 SDK 通常是交給使用者或者生态環境下的其他開發者來完成。但從阿裡雲的工單曆史裡,我們發現大量的 OpenAPI 的使用問題,及社交網站上的吐槽,這迫使我們重新審視如何為開發者提供更好的 SDK。

當一個開放服務越知名,它的使用者量及使用者種類就會越多。比如早年的FaceBook、Twitter、微網誌等社交網站的OpenAPI,通過OpenAPI催生了大量的第三方的應用,是以可以說 OpenAPI是刺激生态成熟的關鍵因素。但作為平台方的程式設計語言技術棧仍然是有限的,不太可能非常好的支援好所有程式設計語言的開發者。

深入解讀阿裡雲SDK體系

不同的程式設計語言給平台方及開發者帶來的困難主要展現在如下兩個層面上:

1.開發者不一定能正确實作平台方給定的簽名算法等用戶端要求

2.即使是平台方正确實作了用戶端的要求,但編碼風格并不符合程式設計習慣。

對應的主要表現如下:

1.用戶端要求

一般而言,平台方制定了 OpenAPI 的接入方式,開發者需要按照文檔所描述的算法,來進行用戶端的編寫。以 ECS 的接入文檔為例:

https://help.aliyun.com/document_detail/25488.html

,這裡最複雜的莫過于簽名算法的部分。

按照道理,每個開發者都有一定實作簽名算法的能力,但事實是大部分的開發者都是工具、庫、架構的使用者,日常的工作也大部分以接觸業務為主,一些涉及底層的點并不是特别擅長。這部分工作就像一道門檻,将編碼能力稍弱的開發者擋在門外。即使有部分開發者能夠正确實作這些用戶端要求,但實作得也不一定完整或準确,是以我們經常收到一些簽名算法不準确的工單。

但作為平台方,也不太可能支撐到所有的程式設計語言,總是有部分疏漏存在,這是雲計算廠商在SDK支撐上的痛點所在。因為這種複雜性,我們盡量推薦開發者使用官方維護的SDK或者成熟的三方SDK,盡量避免自己從頭嘗試簽名算法來完成一個自己的SDK的研發。

2.程式設計社群習慣

雲廠商在面對多程式設計語言的另一個挑戰在于,即使作為平台方,非常熟悉用戶端所需要的實作細節,能把 SDK 的内在部分準确實作,但依然很難保障 SDK 的其他部分是符合目前程式設計語言的編碼風格和開發者習慣的。

深入解讀阿裡雲SDK體系

比如我們曾經面臨很多吐槽說我們 Python SDK 寫得極像 Java 代碼(因為确實是 Java 的同學編寫的)。作為平台方,誠然在公司的範圍内,有來自不同語言棧的程式員可以支援到不同語言 SDK 的編寫,但仍然是有限的。作為 OpenAPI 的平台方其實更多的工作是要關注 OpenAPI 的參數、文檔,以及網關的穩定性,大多數情況是某個語言的開發者兼職提供了另一門語言的 SDK。

除了上面的問題外,還有人員層面的挑戰。OpenAPI 的重頭工作是平台及背後業務的實作,從曆史來看,專職負責 SDK 及相關工作的團隊是非常少的,直到雲計算被廣泛應用(AWS 和 Azure 有人數不低的 SDKs & Tools 團隊)。相比于社交網絡的開放平台,雲計算廠商的 OpenAPI 則跟客戶的資源,甚至說錢緊密相關,是以專門的團隊是有必要的。

一個優質的 SDK,一定是要非常熟悉該門程式設計語言,也非常熟悉業務的開發者,結合程式設計語言及業務之間的最佳實踐,才能産出。我們的現狀是熟悉業務的同學,不一定對開源社群熟悉,主要的工作方式是尋找團隊中比較擅長某門程式設計語言的人來完成該語言的 SDK,是以整體要覆寫到較多程式設計語言的話,需要投入的人力是不小的成本。

多産品的挑戰

除了多種程式設計語言帶來的挑戰外,與普通的開放平台相比,雲廠商的情況要複雜得多,因為它的産品線非常之多。如果光看産品數量的話,阿裡雲有上百個雲産品,如果同時支援8-9門程式設計語言,這個 SDK 的數量就非常龐大了,它是一個至少上千的數量級。幸運的是,網關發揮了很大的作用,每個産品不需要重複地研發自己的網關部分,統一網關能幫助雲産品解決大量的通用問題,是以網關會将上百個産品收斂為幾種網關産品。

深入解讀阿裡雲SDK體系

每種網關下的 OpenAPI 都有自己獨特的部分,需要特殊處理。更比較遺憾的是,因為曆史原因,這些 OpenAPI 都不是 RESTful 風格的,在社群應用最廣泛的 Swagger 工具體系在這裡根本無法應用起來。是以我們不得不為每種網關去研發它對應的核心 SDK,也就是說,我們為了支援不同的網關,不得不重複地進行一些基礎的研發。

可維護性的挑戰

接着說維護的挑戰。

即使社群來了一個某程式設計語言的大牛,根據我們的文檔編寫了一個非常符合該開發者社群習慣的 SDK,使用者用起來都覺得不錯。但是,某天 OpenAPI 發生了一些改變後,會發生些什麼?

作為 OpenAPI 平台方,需要修改 OpenAPI 後端實作,然後再修改文檔;開發者發現文檔發生改變了,再根據文檔,對之前編寫的 SDK 進行更新。暫且不說 OpenAPI 的更新會不會帶來相容性的問題,也不說 SDK 更新後是否帶來相容性問題,隻說這樣的維護方式,它是非常低效的。

深入解讀阿裡雲SDK體系

這裡的痛點在于 OpenAPI 沒有徹底的開放。雲廠商通過文檔的形式開放的 OpenAPI,并不是一個結構化的資料,導緻 SDK 的維護工作成為一個人工的工作。即使大牛的代碼寫得再好,常年累月地義務手工維護,總有失去耐心的一天。

品質的挑戰

延續維護的話題,一旦涉及 OpenAPI 的改動,或者 SDK 的改動,我們需要考慮的事情是改動是否會導緻客戶更新後,程式無法運作,或者在某個時候突然出現 Bug。在前文我們提到“官方”或者“成熟” SDK 的說法,并不是說不鼓勵開發者去嘗試自己編寫 SDK,而是在企業應用中,我們對品質是有更高的要求的。我們不僅僅是編寫完主要的代碼,就可以提供給客戶使用了,我們需要確定提供的 SDK 是有品質保障的,能在生産環境正常運作的,而不是一個隻能跑 demo 的玩具。

保障 SDK 的品質有兩個層面,一個是基本的 SDK 的功能;一個是涉及到 OpenAPI 自身業務邏輯的保障。

基本的 SDK 的功能指的是 OpenAPI 業務無關的那部分,比如簽名算法。這部分工作我們可以依靠單元測試及測試覆寫率工具來保障它的品質。

涉及到 OpenAPI 自身業務邏輯的部分,理論上不是用戶端要考慮的,因為 OpenAPI 的邏輯的變更及擴充性,通常與用戶端的關系不大。但仍然需要考慮的是通過內建測試的方式來做基本的保障。

對 SDK 做品質保障并不是一件比較難的事情,通用的測試方法都能做到一定的品質保障。挑戰在于同時有那麼多的程式設計語言和那麼多的産品。是以不光是産品 SDK 數量衆多,為了保障這些 SDK 的品質,所涉及的測試工作也不少。

這部分工作對于雲計算廠商而言的痛點在于 OpenAPI 的測試要在不同的程式設計語言之間重複編寫及維護,是一個量級不小的挑戰。

做好品質保障是能得到一些收益的。這裡有個小小的例子。

我們的網關在做鑒權時,通常對簽名字元串和 Access Key Secret 以某種簽名算法進行簽名,在服務端則驗證這個簽名值是否比對。我們注意到工單裡出現不少簽名錯誤的情況,這導緻我們無法判斷客戶是否是用了自己的簽名算法,還是單純的輸錯了 Access Key Secret。

總的來說,簽名及鑒權的公式如下:

f(sign_str, access_key_secret) = sign
// f 是簽名算法           

這裡面的因子有 3 個,簽名算法 f、sign_str、access_key_secret。當出現簽名不比對時,出現錯誤的原因一定是三者之一。因為簽名失敗時,服務端會傳回它得到的 sign_str ,後來我們加入了服務端 sign_str 和用戶端 sign_str 對比的方式,可以排除是 sign_str 拼接的問題。因為有足夠的測試,我們可以驗證我們的簽名算法 f 是一定正确的。是以最後有問題的是 AccessKeySecret 沒有填對。

借助測試,我們将出現簽名錯誤時的模糊提示,精确到客戶是否填入了正确的 AccessKeySecret,并改進錯誤提示,避免客戶及客服人員面對錯誤時的手足無措,進而降低工單量。

文檔/Demo

文檔和 Demo 其實仍然是可維護性的挑戰。當一個 SDK 被産出,那麼必然有相關的文檔或 Demo 來介紹它。我們面臨的一個問題是,大多數的雲産品最多隻有少量程式設計語言的 demo 介紹,無法覆寫到很多的程式設計語言,而且這些 demo 大多是通過手工來編寫的。這些 demo 被編寫出來的較短時間裡是能正常工作的,但時間一旦過去,很難保證這些 Demo 是否還能運作。

作為雲廠商,所面臨的問題就是,Demo 的完整性,Demo 的有效性。

一緻性的挑戰

最後說到一個最關鍵的問題,那就是一緻性問題。一緻性是一個涵蓋很廣的考量面,這裡關注的有如下這些:

-OpenAPI 與 SDK 之間是否參數保持一緻

在産品與産品之間,風格是否保持一緻

-相同産品的不同語言用戶端之間,行為是否保持一緻,它們的測試是否保持一緻

-OpenAPI 與文檔之間内容是否保持一緻

-SDK 與文檔之間是否保持一緻

上面這些地方隻要有一個點出現了不一緻的狀況,都可能導緻使用者在使用 SDK 調用 OpenAPI 時出現意想不到的坑。

前文提到,在多語言的情況下,為了開發者習慣,保留适合目前程式設計語言的特征是有必要的。但使用者在審視阿裡雲的所有 OpenAPI 或者 SDK 的時候,會認為它們是應該一樣的,應該是一緻的。

這裡有一個小例子。我們的客戶使用了資源編排解決方案,即 Terraform。在接入的過程中,使用者希望使用一種特殊的 Credentials 方式,但最後發現,有幾個産品的 SDK 沒有支援到這種方式,導緻接入過程受到影響。

完美的 SDK 是怎樣的?

上文提到那麼多的問題,其實歸結起來,我們希望要的是一個這樣的 SDK:

-是由某門程式設計語言的大神來負責編寫的 SDK,它能照顧到這門程式設計語言的開發者習慣。

-SDK 的内在功能特性,和制作流程是一緻的。即使在不同的程式設計語言之間,即使在不同的網關和産品之間。

-OpenAPI 的定義資料是開放的,可以通過自動化的方式生成出來 SDK,是以維護起來非常。

-一個 OpenAPI 的測試代碼可以隻編寫一次,但可以在不同語言的 SDK 下運作。

-SDK 的文檔和 Demo 能和 OpenAPI 定義之間保持同步更新。

後面的主題讨論中,我們将深入介紹解決方案,如何以合适的團隊及技術方案來迎接上述的挑戰。歡迎大家持續關注我們的分享!

繼續閱讀