繼全面採用Node.js以後,PayPal分享大幅度踩坑GraphQL心得 - Mark Stuart

banq發表於2019-10-31

這篇文章涵蓋了我們在PayPal擴充套件GraphQL時學到的所有知識,並將作為在您的公司中部署GraphQL的指南。
一年前,我們撰寫了“ GraphQL:PayPal Checkout的成功案例 ”,其中涵蓋了我們從REST到批處理REST到GraphQL的歷程。從那以後很多事情改變了!這篇文章是我們在PayPal 構建GraphQL API時獲得的一系列最佳實踐和觀察的一部分。
一年前,使用GraphQL的產品很少。雖然我們在PayPal Checkout上取得了成功,但沒有基礎架構,工具,培訓或支援。儘管存在這些差距,但GraphQL仍然像火箭一樣起飛。在撰寫本文時,我們有50個使用GraphQL的不同產品!
採用速度很快,像其他技術變革一樣,企業級擴充套件與水平擴充套件或為伺服器或雲端計算支付大量資金無關。擴充套件人員,工具和流程是最具挑戰性的。

向內看
在部署GraphQL之前,重要的是要深入瞭解自己的公司,並反思自己是誰,幹什麼的以及優點和缺點是什麼。
在PayPal,我們的產品使用JavaScript構建。後端使用Node.js對前端進行響應。堆疊中還有數百個Java REST服務和一些類似於C ++ SOAP的服務。
PayPal是最早使用Node的公司之一,並透過NodeDay之類的活動以及與Node FirmNodeSource的合作幫助啟動了“企業中的Node”品牌。
PayPal在2013–2015年期間遷移到了Node。它改變了整個公司,並改善了我們製造和運輸產品的方式。一個C ++單體應用程式簡單的內容更改將需要數週時間才能部署。現在,開發人員可以在幾分鐘內進行試驗,迭代和推出新產品功能。
那不是一夜之間發生的,不是偶然的。在Node加入PayPal之前,Bill Scott提出了使用LeanUX構建產品的願景,其中迭代和學習是關鍵。在LeanUX中,UI位是實驗性的並且是一次性的。如果實驗效果不佳,請不斷進行迭代!Node.js是成功的關鍵。
2014年,我們推出了Kraken,這是Express之上的一組庫,旨在透過可配置的中介軟體,安全性預設設定,dust.js渲染器和內容本地化為您的應用“提供一些幫助”。現在,團隊正在構建客戶端React應用程式,而應用程式是部署到CDN的靜態檔案包,而不是在伺服器群中執行的程式碼。
對於API,我們使用BFF(backend-for-frontend)模式。儘管它們非常專業,並且允許開發人員進行迭代,但是它們緊密耦合並且不能很好地重用。結果是我們有很多團隊反覆迭代和構建相同的事物!構建BFF API也不是一件容易的事。通常,它們包含許多編排邏輯,在這些邏輯中,您需要從5、10、15個不同的服務中獲取資料,對這些響應進行規範化,丟棄95%的響應,然後將資料對映,過濾和分類為所需的資料。編寫此程式碼並不能很好地利用我們的開發人員的時間。這種緊密的耦合和缺乏重複使用對我們來說是一個問題。

GraphQL可以提供幫助嗎?是!

開發人員經驗>效能
在跳入生產就緒專案清單之前,我們應該重新設定期望值。當您初次接觸GraphQL時,通常會想到主要的好處是透過網路傳輸較少的資料,從而可以實現更快,更高效能的應用程式。
大型公司將GraphQL置於現有REST服務之上。結果是您的GraphQL查詢將僅與最慢的REST服務一樣快。GraphQL允許您在一次往返中獲取所需的一切。如果客戶端和伺服器之間存在空閒,則可以減少往返行程並減少延遲。但是,這並不是您可以為每個人做出的承諾。
一段時間後,您將意識到開發人員 經驗和靈活性的好處遠比效能引人注目。
GraphQL對人類友好。使用GraphQL,開發人員可以根據欄位而不是端點,域或複雜聯接來考慮。開發人員可以遍歷該圖以選擇使用者的名字,60x60的個人資料照片,主要送貨地址和信用卡,而不必呼叫6-10種不同的服務。新員工都喜歡它。如果您知道JSON是什麼樣子,請刪除雙引號和逗號,然後就可以查詢GraphQL API。您的UI開發人員喜歡它,因為它以產品為中心,具有宣告性,並具有豐富的工具集,可減少整合摩擦並提高信心。
當您將GraphQL推薦給公司的領導者和團隊時,請關注開發人員的經驗,生產力和靈活性。否則,您可能會讓他們失望。

GraphQL位於堆疊邊緣
在PayPal,我們的核心服務由獨立的後端團隊開發,我們的產品團隊構建BFF API,以從這些基礎核心服務中整理資料。最初,我們認為“ GraphQL應該無處不在”!
經過大量的實驗和反思,我們發現GraphQL在堆疊的邊緣發光最多
GraphQL以產品為中心,應該受到您的產品團隊的影響(或開發)。GraphQL模式應在設計時首先由產品團隊提供意見。後端開發人員不應孤立地設計它們。GraphQL做得很好。因此,GraphQL最適合您的堆疊邊緣,並且可以與REST協同工作。


在公司啟用GraphQL
好的,是時候實現這個了!本部分是在貴公司啟用GraphQL的清單。
首先,您需要為產品團隊奠定基礎。GraphQL新穎且令人興奮,有許多開放式問題和見解。幾乎沒有什麼是一成不變的。您有很多選擇!

  • 誰是您的API開發人員和消費者?
  • 誰來貢獻?他們知道什麼語言?
  • 他們今天如何構建API?它們是專門用途還是通用用途?
  • 您要使用現有的框架和工具嗎?哪個?
  • 您需要新增公司特定的內容嗎?身份驗證,授權,重試,斷路器,自定義HTTP狀態程式碼,錯誤處理?
  • 您將如何執行標準?
  • 您將如何處理錯誤?

建立基礎
在PayPal,GraphQL已與為BFF API和UI做出貢獻的產品團隊脫穎而出。我們為GraphQL API使用Node.js。與許多其他公司一樣,我們使用Apollo開源庫和工具Apollo擁有專門的團隊來構建和維護這些工具,因此它們在一流的文件編制方面是一流的。我們使用apollo伺服器,並在特定於PayPal的生產就緒狀態下投入使用,例如日誌記錄和檢測,身份驗證,錯誤處理和速率限制。
如果您有任何獨特的要求,請建立可與開源庫(例如Apollo)一起使用的模組和外掛。不要建立深層抽象或向開發人員隱藏複雜性。保持它可用於Google!
請記住,GraphQL仍然是一個API。您將要確保具有足夠的日誌記錄,重試,斷路器模式,速率限制查詢複雜性檢查。

擴充套件知識
確保架構師和API設計人員支援GraphQL,以幫助您擴充套件設計審查並執行標準。他們很可能已經設計了REST API多年。GraphQL是不同的。起初,您可能會遇到阻力。推動它。您需要花時間與他們一起概述差異,並挑戰它們以不同的方式進行API設計:沒有版本控制,擁抱圖表而不是使用ID建立關係,沒有HATEOAS連結。透過邀請架構師,您將不會是唯一的主題專家,它將為GraphQL帶來合法性。

制定標準
您需要設定一些設計標準。建立一個文件並在任何地方引用它。使用諸如graphql-schema-linter之類的工具來強制命名約定。
一些示例包括:

  • 所有欄位都必須有描述或註釋
  • 型別取名:LikeThis,欄位取名:LikeThis。列舉值:LIKE_THIS
  • 儘可能使用列舉
  • 棄用的欄位必須有原因
  • 沒有集合或列表字尾。(例如:使用cards,而不是cardList)
  • 偏好具有引起狀態變化的輸入型別

然後,您將需要圍繞分頁進行選擇。在架構中顯示列表的首選方式是什麼?基於遊標的分頁
您將如何發現錯誤?在撰寫本文時,我們錯誤處理還沒有弄清楚,有很多選項可供選擇:
  • 使用預設錯誤陣列
  • 使用自定義屬性擴充套件錯誤
  • 模式中的錯誤欄位
  • Union types

在PayPal,我們選擇使用自定義屬性擴充套件錯誤。我們喜歡它仍然符合規範,並允許我們在需要時向錯誤新增錯誤分類和其他後設資料。我們認為其他選項無法實現,並且允許錯誤不被注意到。我們將在以後的中型帖子中提供更多詳細資訊。

認證/授權
首先,我們保護了整個架構,然後意識到我們擁有許多具有不同特權的不同型別的使用者。然後,我們建立了一個高階auth函式,您可以使用它包裝解析器。最後,我們意識到建立自定義auth指令是保護架構的最佳方法。

透過出色的工具獲得超能力
之前,我們撰寫了《GraphQL:檢測您的API和釋放超能力》,它解釋了GraphQL與REST相比有何獨特優勢,您可以更好地瞭解API的使用方式,並在與API整合並保護客戶端的過程中為客戶提供額外的信心應對重大變化。
對於初學者,您可以將延遲,錯誤和使用情況資料透過管道傳輸到公司的監控儀表工具。
我們建議使用的其他工具包括:graphql-playground用於測試開發模式下的查詢,graphql-schema-linter用於強制執行模式命名約定,eslint-plugin-graphql用於對模式查詢客戶端查詢,graphql-doctor用於PR狀態檢查。
Apollo Graph Manager提供的儀器工具可顯示現場級別的深刻見解,對突破性變化的信心,列入白名單的查詢,並透過為每個欄位提供襯布和線上SLA計時來簡化客戶整合。
Apollo Graph Manager不是免費的。我們可以自己建造嗎?也許可以,但不會那麼完美。我們沒有GraphQL基礎架構團隊。如果我們這樣做了,我們就不想等待12-18個月來構建可比較的東西並必須對其進行維護。我們現在想兌現GraphQL的承諾!從購買與構建的決策來看,Apollo Platform是一個明確的購買。我們建議您也考慮一下。

在企業中擴充套件GraphQL面臨的挑戰
到目前為止,GraphQL很棒,但是直到我們解決了它的組裝方式和成功度的一些問題之前,它才是很棒的。
在2012年之前,PayPal是C ++ monorepo。從那時起,我們在許多領域和產品團隊中產生了數千個GitHub儲存庫,構成了服務和應用程式層。對於擁有monorepos的Facebook和GitHub這樣的公司來說,共享並不是什麼大問題。
GraphQL在許多儲存庫中都很棘手。如果沒有諸如自定義遠端型別之類的自定義技巧,就無法引用或連結本地檔案系統中不存在的遠端型別。開發人員發現或重用其他服務中定義的型別並不容易。

組裝GraphQL
使用者希望看到一個可以瀏覽的單個內聚圖,而無需考慮許多服務,而必須使用許多服務來獲取所需的資料。實際上,組裝單個圖形是困難的。
一種解決方案是模式拼接,其中閘道器使用底層GraphQL API的模式並向開發人員顯示單個模式,並將傳入的查詢委派給底層API。Marc-Andre Giroux寫了一篇出色的文章,介紹了模式縫合的挑戰。透過模式縫合,閘道器具有粘合程式碼,負責維護型別之間的關係並確保正確執行子查詢。該膠水程式碼是有問題的,當閘道器所有者不知道這些型別的,當它是不現實的產品團隊擁有這些基礎設施之間的關係。
Apollo Platform的解決方案是一種聯合開發範例,該範例使用自定義指令以宣告方式將型別連結在一起。它消除了閘道器中對粘合程式碼的需求,設定了適當的關注點分離,並允許您擴充套件在本地開發中不擁有的型別。看看公司是否會採用它以及聯盟將如何影響GraphQL規範將很有趣。
如果構建一張圖不切實際怎麼辦?在貝寶,我們為快速迭代和持續學習進行了最佳化。許多開發人員沒有動力放慢腳步,達成共識併成為更大整體的一部分。這是我們文化的雙刃劍。如果無法繪製一張圖,我們還可以如何重用工作?另一個選項是帶有GraphQL Modulesgraphql-component之類的選項的本地模組。使用本地模組,您可以選擇所需的型別和欄位,並且所有程式碼都在同一程式中執行。模式縫合和聯合的許多問題都消失了。但是,我們有大量類似的端點,並且伺服器的佔用空間並未減少。這個可以嗎?

這是我們使用GraphQL遇到的最困難的問題。

(banq注:業務聚合問題能透過GraphQL反覆組合解決嗎?)

 

相關文章