通過基于Go的微服務框架goa,實現對服務API的定義、審查與實現

jopen 8年前發布 | 28K 次閱讀 API 微服務 Go語言

Raphael Simon是來自于RightScale的一位高級系統架構師,他創建了一種基于Go語言的HTTP微服務框架,名為 “goa” 。這一框架允許開發者通過 領域特定語言 (DSL)定義服務的API,并且通過自動代碼生成功能創建“樣板”式的服務端和客戶端代碼以及文檔。

Raphael在他的博客 Gopher Academy 上發表了一篇介紹goa框架的帖子,他提到RightScale的工程師團隊正在將一個一體性的Ruby on Rails應用遷移為一系列基于Go語言創建的微服務應用。這次遷移工作的一個主要挑戰在于如何創建設計良好的服務API,為了支持整個微服務API的設計、審查以及實現,他們創建了一系列的工具。這一項目所產生的結果之一就是基于Go語言的框架goa的誕生,它的出現受到了在RightScale中所應用的一個基于Ruby的API開發框架 Praxis 的啟發。

InfoQ與 Simon 進行了一次訪談,他既是 RightScale 的高級系統架構師,也是goa的主要 貢獻者 之一。這次訪談主要問及了關于goa這一微服務框架的設計目標、使用方式以及未來的發展計劃。

InfoQ:歡迎你Raphael!請你為讀者說明一下“goa”是個怎樣的產品,以及創建這一架構的動力是什么。

Simon:RightScale正在向微服務風格的架構進行遷移,這項工作已經開展了一段時間了,而最近一段時間團隊開始使用Go語言編寫部分服務。總體來說,無論在開發還是運維方面,Go都證明了它是一個優秀的選擇。這門語言很容易上手,并且所創建的服務表現也很出色。

不過,采用Go語言進行開發也意味著在開發與部署階段要引入一種新的技術棧,因為直至最近,RightScale基本上都是使用Ruby進行開發的。團隊在創建與運行REST API(RightScale已經將這一使用Ruby語言打造、用于創建REST API的 Praxis框架 開源了)方面已經具備了豐富的經驗。由于目前還沒有一種現成的解決方案可以應對我們的需求,因此有理由運用這些經驗去打造基于一種Go語言的服務開發棧。

這項工作的成果就是goa的誕生,它是一個微服務的開發框架,通過它能夠以代碼的方式描述API的設計。與goa框架一同推出的還有一個goagen工具,它能夠通過設計代碼生成各種輸出,包括http服務器的封裝、代碼腳手架、文檔、客戶端,甚至是自定義的輸出。goa包還包括大量的支持性模塊,服務本身與生成的代碼都能夠利用這些模塊進行服務的實現。

InfoQ:與使用標準的Go類庫(或者使用Peter Bourgon開發的go-kit)相比,“goa”通過怎樣的方式簡化了微服務的開發?

Simon:goa框架能夠描述API的 意圖 。通過使用goa設計語言,開發者能夠定義API所暴露的資源與行為(即API的終結點)。對于每種行為的描述包括所期待的請求狀態,以及各種可能產生的響應。這種方式能夠帶來許多益處:舉例來說,它在設計階段就能夠起到很大的作用,各個團隊能夠通過Swagger UI生成Swagger的規格說明,從而提出反饋意見。這一反饋循環能夠為負責生成UI或編寫面向用戶的文檔的團隊帶來極大的便利。最大的優點在于,這一切都發生在實際編寫代碼實現之前。

這種方式的另一優點在于,一旦設計完成之后,goa就將負責生成所有樣板邏輯,包括請求的驗證以及用于描述請求狀態的自定義數據結構。這樣一來, 設計就變成了實現所必需的一部分 。這就體現出了這一方式具有很高價值的一面,否則的話,維持實現與設計之間的同步就成了非常一項非常繁瑣的流程。對于每個暴露了訪問功能的行為來說,goa能夠生成特定的請求處理邏輯的上下文,從中返回符合設計所描述的數據結構。這種做法減少了對“綁定”方式的需求,也不必手動地驗證所傳入的請求的格式。

goagen也能夠為API生成相應的客戶端,包括一個命令行工具、Go包和JavaScript的客戶端。這種方式顯而易見的好處是免去了手動進行這一過程所花的時間,除此之外,它還有助于維護多個客戶端之間的一致性,并且保持他們與API的同步。在微服務的世界中,服務的數量是持續增長的,因此保持他們之間的一致性是一種非常有價值的做法,它大大地簡化了構建整合的流程。

InfoQ:“goa”看起來為開發者提供了很多內容,包括一個運行時“引擎”、支持日志記錄、能夠對“中間件”進行自定義、還支持錯誤處理。你是否打算為基于Go的微服務架構提供一個單一的解決方案?

Simon:goa中的請求上下文是運行時引擎的核心,它引用了golang這個包的開發者所做的工作,主要是 跨接口傳遞上下文 的功能,從而實現一些強大的特性,例如設置deadline,以及在goroutine之間共享狀態信息。舉例來說,上下文信息能夠一路傳遞至負責生成外部請求的軟件模塊,因此,在整個周期中的任何階段,都能夠獲取包括deadline在內的整個請求狀態。生成的代碼將以一種特定于行為的數據結構對上下文進行封裝,通過在設計代碼中所描述的字段暴露已驗證的請求的狀態。

而其余部分的行為都是能夠進行替換的:goa的設計遵循了“提供內置支持”的模型。舉例來說,如果你對于如何進行錯誤處理并沒有非常確定的想法,那么goa將為你提供一種恰當的默認實現(在這種情況下所返回的響應將包括500狀態碼)。不過,開發者也能夠方便地覆蓋默認的錯誤處理邏輯,以實現任何自定義的邏輯,goa還提供了一種備選的錯誤處理邏輯,在響應中將不包括調用棧的信息。另一個例子是對中間件的支持:goa定義了一種專用類型的中間件,可以通過它利用豐富的上下文信息,但同時也能夠使用普通的http中間件。

目前來說,并非所有特性都能夠被輕易地替換(例如日志記錄),因為goa最初的關注點在于代碼的生成。總體目標是提供一個完整的、模塊化的微服務開發框架,因此,曾使用過go-kit或其它Go包的開發者依然能夠繼續使用它們,而同時又能夠受益于goa所提倡的基于設計的API設計方式。

InfoQ:我們很有興趣了解一下關于生成能夠調用服務API的客戶端代碼的特性。通常來說,有關代碼生成的討論總是會得到一些消極的回應,例如生成的代碼過于復雜,或是生成過程不夠透明、也無法進行自定義。你能否為我們解釋一下你選擇這種實現方式的原因?

Simon:這里的訣竅在于所生成的代碼實現的功能只是一些繁瑣的樣板代碼,這些生成代碼的結構與你“手寫”這些代碼的結果是相同的。goagen盡了最大努力以試圖遵循“盡量減少令人驚訝的部分”的原則。你甚至可以說生成的最終代碼看起來更“標準”(并且更高效)。舉例來說,它減輕了對反射的依賴,否則的話,實現相同的功能可能要寫上幾千行代碼。我們可以以客戶端的Go包為例,你恐怕很難想到它居然是自動生成的。好吧,或許有些本地變量的命名看起來有點古怪,這可能會使你查覺到真相 :)

goa的代碼生成還有一個十分重要的特點,即所生成的代碼始終處于一個不同的包中,而無需進行手動修改,從而清晰地區分了用戶代碼與生成的代碼。goagen將始終重新生成整個包,因此不可能出現用戶代碼與生成代碼相混合的情況。這里有一種例外情況,即goagen可以在編碼的起始階段生成一種一次性的腳手架代碼。

最后,goagen只會生成必要的代碼,所生成的代碼將使用goa包實現各種通用的功能,例如日志記錄、錯誤處理等等。它提供了一種優秀的方式對生成代碼的行為進行自定義,而無需進行手動修改。舉例來說,你可以實現一種自定義的服務錯誤處理邏輯,并且讓所有生成代碼自動調用這段自定義邏輯。你可以將這種生成代碼想象為一種goa包的“插件”,并暴露相應的調節器以修改它的行為。

goagen也支持插件系統,它實質上就是一種標準的Go包,其中包含了一個公開的Generate函數。由Brian Ketelsen所編寫的 gorma插件 是對這一項目最早的貢獻之一,它能夠通過API設計中所描述的類型生成 gorm 模型。整個項目最令人驚訝的部分就在于通過代碼(以及其他功能)生成所帶來的各種可能性。在我看來,這一設想已經很明顯地在Go語言中得到了很好的表現。

InfoQ:如果InfoQ的讀者有興趣加入“goa”項目,或是為其貢獻代碼,最好的途徑是什么?

Simon:在GitHub庫上的wiki中包括一份 路線圖的文檔 ,其中可以找到許多建議,但這些僅僅是建議而已。這一項目最值得贊揚的一點在于它在社區中得到了快速的應用,而且在我所沒有考慮到的方面也得到了許多代碼貢獻。goa依然是一個很新的構架,整個項目的發展方向存在于許多可能性。此外,在 gophers.slack.com 上還有一個活躍的#goa slack頻道。因此,建議大家去訪問GitHub庫、加入slack頻道,并且開始嘗試!

本項目 確實 有一個地方或許需要大家的幫助:它需要一個logo! 它的網站 頁面可能也需要動一下整形手術 ;)

InfoQ:Raphael,感謝你參加今日的訪談。對于InfoQ的讀者,你還有什么內容想同大家分享的嗎?

Simon:感謝你的邀請!我推薦所有希望創建API的讀者們去嘗試一下goa,我真的相信它能夠幫助你們更高效地打造服務。微服務風格的架構如今已經快速地成長為事實上的標準,這使得設計優秀的API這一任務顯得更為關鍵,而優秀的工具能夠起到極大的作用。隨著goa的使用率不斷增長,我對于它的發展充滿期待,并且迫不及待地想看到用戶能夠通過它實現哪些功能。

如果想了解有關goa微服務框架的更多信息,可以閱讀Gopher Academy博客上的“ goa: Untangling Microservices ”這篇帖子,并訪問 goa的GitHub庫

查看英文原文: Defining, Reviewing and Implementing Service APIs with “goa”, a Go-based Microservice Framework

</div>

來自: http://www.infoq.com/cn/news/2016/01/goa-microservice-framework

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!