hello~親愛的觀衆老爺們你們好~最近一直沉迷於 GraphQL 的應用實踐,正好公司黑客馬拉松臨近,就拉上了兩位小夥伴,結合實際的業務場景,把 GraphQL 做爲中間層的解決方案提上去~項目完成度還算不錯,對 GraphQL 也有了更深刻的理解,在此記下整個過程的收穫。前端
注意~這篇文章不是學習 GraphQL 語法的文章,語法學習可左轉傳送門。但如若你對 GraphQL 有必定的瞭解,想知道實踐中可能碰到什麼問題,那估計本文能給你帶來一點幫助~如下是正文:程序員
既然要用 GraphQL,那仍是要先了解它究竟是什麼:數據庫
GraphQL 既是一種用於 API 的查詢語言也是一個知足你數據查詢的運行時。 GraphQL 對你的 API 中的數據提供了一套易於理解的完整描述,使得客戶端可以準確地得到它須要的數據,並且沒有任何冗餘,也讓 API 更容易地隨着時間推移而演進,還能用於構建強大的開發者工具。後端
看起來沒什麼複雜的地方,也許你看過 GraphQL 的相關介紹,會認爲它的語法很繁雜(這我卻是不否定),但歸根到底,它就是爲了查詢而生。本質上就是丟一段東西給服務器,服務器解讀這段東西后,把對應的數據丟回來給你而已,全部的語法都爲此而服務。緩存
簡單介紹完 GraphQL,也要簡單介紹一下業務的背景~咱們組真正的後端服務是用 C++ 進行編寫的,有一層很薄的 Go 做爲網關與中間層,負責溝通頁端與 C++ 後端,同時提供解密、鑑權 等基礎服務。但因爲業務的瓶頸不在前端(也致使話語權比較小),致使 C++ 後端常常表現得不那麼「業務」,也不認爲爲前端提供服務是工做的關鍵之一。致使他們對於不少後端能作與應該作的事情視而不見。後端隱含的態度基本是:「又不是不能用~」。但這對前端的代碼質量與研發效率形成了負面的影響。服務器
站在前端的角度,如今的系統存在如下問題:網絡
因爲各類緣由,推進後端改變比較困難,那就本身從新架一套吧。新的中間層,使用 TypeScript
開發,選用了 Egg.js
爲框架,魔改了 egg-graphql
這個插件做爲 GraphQL 服務的基礎。提供實時規範的接口文檔、0 配置 Mock 服務、動態配置且熱更新等功能。框架
如下是功能與使用先後區別的一些截圖:運維
接口文檔:工具
配置後臺:
頁端使用 GraphQL 以前:
頁端使用 GraphQL 以後:
相信你們對 GraphQL 的優勢已瞭然於胸,經過上文對新的中間層的描述,也能感覺到 GraphQL 的優勢。這裏就不湊字數去詳述節省的帶寬、性能的提升及其它爲前端帶來的其餘便利。這裏主要想討論一下的是,歸根到底,咱們是但願解放生產力,那麼 GraphQL 解放了什麼?
咱們認爲:GraphQL 能減小先後端矛盾,讓彼此更專一自身!
儘管上文吐槽了一把後端同窗,但換個角度上,他們的作法無可厚非。接口單1、專一是合理的設計,冗餘的接口是由於版本與多端須要,Mock 服務更是後端無關的。不管前端仍是後端,都是站在本身的立場去思考業務,並根據自身的技術爲業務提供解決方案。可是業務是一個總體,程序員卻被分爲了先後端。兩端中間的灰色區域,儘管能提升某一端的研發能力,但對另外一端而言,倒是至關麻煩的。那麼:
All problems in computer science can be solved by another level of indirection.
既然灰色區域難於處理,那就再抽象一層!GraphQL 應運而生~它整合與提供了大量的功能,其中包括但不限於:文檔服務、Mock 服務、單一入口、去冗餘、數據聚合等功能。解決了先後端的矛盾,後端可專一於自身,提供穩定而健壯的服務,再也不關心前端 UI 所需數據及其意義;前端專一於頁面與交互,按需獲取對應數據,接口穩定、文檔清晰。
我的認爲,GraphQL 根本的優勢是:讓各端更專一自身,更有效地解耦彼此。
既然有光,那麼確定會有影子,如下是勸退使用 GraphQL 的時間(笑)。因爲我是一個至關怕麻煩又容易放棄的人,每當我碰到表現比現存系統更差或實現起來至關麻煩的時候,就會不自覺地思考新的技術是否適用於當前場景。如下是實踐過程的一些思考(已經明確的缺點:如緩存、n+1 的問題等在此再也不詳述):
GraphQL 很好,它清晰的標識了每一個字段的類型與含義,以此爲基礎擴展出文檔服務、Mock 服務、去冗餘等功能。但成也蕭何敗蕭何,做爲中間層,通常是比較輕薄的,通常只是校驗與動態轉發內容便可,然而 GraphQL 其實至關重的。這致使了後端改字段的時候,不單後端要發版,中間層也須要發版。爲解決這個問題,咱們千方百計對 GraphQL 服務進行動態配置及熱更新,儘管實現了這一功能,但裏面使用的都是 JavaScript 的黑魔法,如何遷移到其餘語言(如 Go,公司在 Go 語言運用上已經比較成熟),說實話,我真不知道。而對於合併請求優化性能而言,GraphQL 也不是惟一的解決方案,Http2 同樣能解決問題~
若是不將 GraphQL 做爲中間層轉發的技術,而做爲 BFF(Backend For Frontend)中請求的主要查詢語言,則會碰到一個比較尷尬的場景。在 BFF 中,前端掌握了服務器,那麼接口的質量其實前端是能把握的。此時 GraphQL 只是一種選擇,它並無解決太多的問題,但它的學習與接入成本又不低。多少有點高不成低不就的感受。
此處的接入成本,不單指編寫 GraphQL 相關代碼的成本,還包括如何接入到公司現行系統的成本。因爲 GraphQL 獲取數據的方式,存在瞬間請求大量數據的可能,很容易拖垮數據庫,然而請求的人卻對此一無所知。這有點像當初郵件系統剛出的時候,用戶往郵件中扔視頻文件同樣,儘管是無心的行爲,卻對系統形成極大的傷害。同時,誰去接也是一個值得商榷的問題。說到底,這是「爽」前端的技術,後端同窗對此興趣乏乏。然而接入須要相關的開發與運維能力,前端同窗不必定有足夠的能力去接,畢竟不是每一位同窗都是全棧。其餘的問題還有 rpc 接入、權限控制等等。在方案落地以前,這些都須要仔細進行評估,不能盲目「追新」。
綜上所述,GraphQL 能夠爲咱們帶來不少便利,但它的接成本並不低。我的認爲,GraphQL 並非從根本上解決某個問題,而是在先後端之間幾個齷齪的地方進行了改進。在考慮是否使用 GraphQL 以前應進行多方面的考量。它比較適合如下的場景:
最後感謝 @Scott 相關的指導,儘管你給的建議每一條都用了其餘方式去實現(笑)~但無疑是開闊了咱們的眼界。
以上是我的的一點淺見,感謝各位看官大人看到這裏。知易行難,但願本文對你有所幫助~謝謝!