PayPal:如何在你的公司擴展GraphQL?

GraphQL 是 REST API 的一種非常流行的替代方案,目前正在席捲開發人員的世界!去年,PayPal 將 GraphQL 引入了技術堆棧,徹底改變了開發人員思考數據、獲取數據和構建應用程序的方式。本文作者在一年前曾寫過一篇 GraphQL 最佳實踐的文章,當時受到了廣大讀者的歡迎。這篇文章同樣也是一篇精彩的總結,可以當作公司部署 GraphQL 的指南。

圖源:graphql.org

我們在PayPal構建GraphQL API時獲得了一系列最佳實踐和觀察總結,這篇文章就是其中之一。

一年前,我們寫了一篇《GraphQL:PayPal Checkout的成功案例》,內容涵蓋了我們從REST到Batch REST再到GraphQL的發展歷程。自那時以來很多事情都改變了!這篇文章涵蓋了我們在PayPal擴展GraphQL時學到的所有知識,並可作爲你在公司部署GraphQL的指南。

一年前,使用GraphQL的產品很少。雖然我們在PayPal Checkout上取得了成功,但那時還沒有相關的基礎架構、工具、培訓或支持。儘管存在這些缺陷,但GraphQL的發展仍像火箭一般一飛沖天。在撰寫本文時,我們已經有50多個不同的產品在使用GraphQL!


在短短2年內,PayPal使用GraphQL的產品從3種增加到52種。

這項新技術的應用速度很快,我們仍在努力跟上步伐。與其他技術變革一樣,企業級擴展的重點並不在於水平擴展,或爲服務器/雲計算投入大量資金。擴展人員、工具鏈和流程是最具挑戰性的

瞭解自己

在部署GraphQL之前,重要的是要深入瞭解你所在的公司,理解你們的身份,你們在做些什麼,以及你們的長處與不足。

在PayPal,我們的產品使用JavaScript構建。前端採用React,後端則是Node.js。技術棧中還有數百個Java REST服務和一些C++ SOAP之類的服務。

PayPal是最早使用Node的公司之一,並通過NodeDay之類的活動,以及與The Node Firm和NodeSource的合作,在業界打響了Node的品牌。

2014年,PayPal的首個NodeDay。

2013–2015年,PayPal遷移到了Node。Node改變了整個公司,改善了我們製造和運輸產品的方式。過去,一項簡單的內容更改需要數週時間才能部署爲單個單體C++應用。如今,開發人員只需要幾分鐘時間就可以實驗、迭代和推出新的產品功能。

https://vimeo.com/82577994

這不是一夜之間發生的轉變,也不是偶然的結果。在Node融入PayPal之前,Bill Scott提出了使用LeanUX構建產品的願景,其中迭代和學習是核心要素。在LeanUX中,UI數據是實驗性、一次性的。如果實驗效果不佳,那就不斷迭代!Node.js是其成功的關鍵所在。

Kraken.js

2014年,我們推出了Kraken,這是Express上的一組庫,旨在通過可配置的中間件、默認安全設置、一個dust.js渲染器和內容本地化來爲你的應用“提供一些幫助”。自那以來,Kraken的大部分武器都消失了。我們仍使用可配置的中間件和默認安全設置,但與Web應用程序相關的所有內容自2014年以來發生了很多變化。現在,團隊正在構建客戶端React應用,應用程序是部署到CDN的靜態文件包,而不是在服務器集羣中運行的代碼。

對於API而言,我們使用BFF Schema。儘管它們都是專用的,並且允許開發人員迭代,但是它們緊密耦合在一起,並且不能很好地複用。結果是我們有很多團隊在反覆迭代和構建相同的事物!構建BFF API也不是一件容易的事。它們往往包含許多編排邏輯,其中你需要從5、10、15個不同的服務中獲取數據,規範化這些響應,丟棄其中95%的響應,然後將數據映射、過濾、分類爲所需的樣子🙄。編寫這樣的代碼並不能充分提升開發人員的效率。這種緊密的耦合和缺乏複用對我們來說是一個問題。

GraphQL可以提供幫助嗎?答案是肯定的!

在上一篇文章中,我們記錄了從REST到Batch REST再到GraphQL的旅程。我們發現它做到了兩全其美——開發人員可以快速迭代,API和UI鬆散耦合,並且代碼複用也增加了。

推薦你的公司進行類似的練習。在跳上GraphQL這趟高速列車之前,花些時間瞭解你的過去,回顧自己的發展歷程,評估自己的優缺點,並考察GraphQL可能帶來的幫助。

重設期望

開發人員經驗>性能

在查閱生產就緒的項目清單之前,我們應該重新設定期望值。當你初次接觸GraphQL時,能想到的好處往往是:通過網絡傳輸的數據變少了,從而可以實現更快、性能更強的應用。

大型公司會將GraphQL置於現有的REST服務之上。結果是,你的GraphQL查詢速度將受限於最慢的REST服務。GraphQL允許你在一次往返中獲取所需的一切。如果客戶端和服務器之間存在空閒,則可以減少往返並降低延遲。但這並不是所有情況下都能做到的。一段時間後,你將意識到開發人員經驗靈活性的好處遠比性能更重要。

GraphQL對人類很友好❤

GraphQL對人類很友好。使用GraphQL時,開發人員考慮的是字段,而不是端點、域或複雜的連接。開發人員可以遍歷數據圖(graph)來選出用戶的名字、60x60的個人資料照片、主要送貨地址和信用卡信息,而不必調用6-10種不同的服務。新員工都喜歡它。如果你知道JSON是什麼樣子,那麼只要去掉雙引號和逗號就能查詢GraphQL API了。你的UI開發人員喜歡它,因爲它以產品爲中心,具有聲明性,並有豐富的工具集支持,可以減少集成摩擦並提高信心。

當你將GraphQL推薦給公司的領導者和團隊時,請重點談論開發人員經驗生產力靈活性。否則你可能會讓他們失望。

位於技術棧邊緣的GraphQL

在PayPal,我們的核心服務由獨立的後端團隊開發,產品團隊則構建BFF API,以從這些基礎核心服務中編排數據。最初,我們認爲“GraphQL應該無處不在”!我們認爲過度獲取和獲取不足的問題將會消失,你可以知道哪些用例使用哪些字段,並能一直追溯回數據庫。架構師喜歡這個想法。但我們無法讓整個公司停止將開發流程遷移到GraphQL上。

經過大量的實驗和反思,我們發現GraphQL在我們技術棧的邊緣最能發光發熱。GraphQL以產品爲中心,應該受到產品團隊的影響(或經他們開發)。GraphQL Schema應該由產品團隊先設計再開發。它們不應該由後端開發人員孤立地設計。GraphQL可以很好地處理編排工作。因此GraphQL最適合你的技術棧邊緣位置,並且可以與REST協同工作。

我們的朋友(也是前PayPal員工)Trevor Livingston在Expedia使用GraphQL時也有類似的觀察結果。

GraphQL的收益會隨着你在技術棧中的應用深度增加而遞減。我不認爲它是微服務的通解。它的甜點在API的邊緣表層領域。

在你的公司中引入GraphQL

好了,是時候實現這一目標了!這部分內容是你的公司引入GraphQL時要做的準備工作清單。

首先,你需要爲產品團隊奠定一個基礎。GraphQL這項技術新奇且令人興奮,有許多開放式問題和見解。幾乎沒有什麼是一成不變的。你有很多選擇!

  • 你的API開發人員和消費者是什麼樣的?
  • 誰負責主要工作?他們瞭解哪些語言?
  • 他們現在是如何構建API的?它們是專用的還是通用的?
  • 你要使用現有的框架和工具嗎?具體是哪些?
  • 你需要添加公司專屬的內容嗎?比如身份驗證、授權、複查、斷路器、自定義HTTP狀態代碼和錯誤處理?
  • 你將如何執行標準?
  • 你將如何處理錯誤?

奠定基礎

在PayPal,爲BFF API和UI做出貢獻的產品團隊已經讓GraphQL流行了。我們爲GraphQL API使用Node.js。與其他許多公司一樣,我們使用Apollo的開源庫和工具。Apollo有專門的團隊來構建和維護這些工具,因此它們在文檔編制方面是一流的。我們使用apollo-server,並分散應用在了PayPal專屬的的生產就緒環境中,如日誌記錄和檢測、身份驗證、錯誤處理和速率限制等用途。

如果你有任何獨特的要求,請創建可與開源庫(如Apollo)共用的模塊和插件。不要創建深層抽象或向開發人員隱藏複雜性。要保持簡單,什麼問題都能靠谷歌查詢出來!

請記住,GraphQL仍然是一個API。你要確保有足夠的日誌記錄、複查、斷路器模式、速率限制和查詢複雜性檢查。

擴展知識

確保架構師和API設計人員都瞭解GraphQL,以幫助你擴展設計審查流程並執行標準。他們很可能已經用了很多年來設計REST API。GraphQL是不同的。起初你可能會遇到阻力,但要克服它。你需要花時間與他們一起找出差異,並讓他們挑戰自我,換一種API設計方式:

沒有版本控制,使用數據圖來代替ID以創建關係,沒有HATEOAS鏈接。當架構師也瞭解這一技術後,這會給GraphQL的推廣帶來支持。

接下來要思考,如何在公司內推廣GraphQL的學習?GraphQL正在快速變化。你創建的任何培訓材料都將過時並需要維護成本。所以請依靠外部資源,並向Moon Moon這樣的培訓公司尋求幫助,獲取優秀的GraphQL課程!

制定標準

架構師入門之後,你需要設定一些設計標準,創建一份文檔並在所有地方都引用它,使用諸如graphql-schema-linter之類的工具來強制命名約定。

例如:

  • 所有字段都必須有描述或註釋;
  • 類型名稱,LikeThis。字段名稱,likeThis。枚舉值,LIKE_THIS;
  • 儘可能使用枚舉;
  • 棄用的字段必須有原因;
  • 沒有集合或列表後綴(如:使用cards,而不是cardList);
  • 優先使用具有突變的輸入類型。

然後你需要針對分頁做出選擇。在你的Schema中顯示列表的首選方式是什麼?基於遊標的分頁(Cursor-based pagination)嗎?

你將如何發現錯誤?在撰寫本文時,GraphQL的錯誤處理還不成體系,有很多選項可供選擇:

  • 使用默認errors數組;
  • 使用自定義屬性擴展errors;
  • Schema中的errors字段;
  • Union類型。

在PayPal,我們使用自定義屬性擴展errors。它仍然符合規範,並允許我們在需要時向errors添加錯誤分類和其他元數據,這些我們很喜歡。我們認爲其他選項是不可行的,會導致錯誤被忽略。

身份認證/授權

你將如何保護自己的Schema?

首先,我們保護了整個Schema,然後意識到我們擁有許多不同權限、不同類型的用戶。然後我們創建了一個高階auth函數,可以用來包裝一個解析器。最後,我們意識到創建自定義auth指令是保護Schema的最佳方法。

Custom @auth directive

在上面的示例中,如果一個查詢包含user字段,則必須登錄該user,並且creditCards需要額外兩項權限。因爲這是一條指令,所以它在Schema中可見,而不是深埋在代碼中。API設計人員和架構師可能不太瞭解JavaScript,但也可以在審查時提供幫助。

通過出色的工具鏈釋放潛能

以前我們寫過《GraphQL:檢測API並釋放潛能》,解釋了GraphQL與REST相比有何獨特優勢:你可以更好地瞭解API的使用方式,並在客戶集成你的API的過程中爲他們帶來額外的信心,同時避免重大更改的影響。

首先,你可以將延遲、錯誤和使用情況數據通過管道傳輸到公司的製圖工具。下面是一個Grafana儀表板示例:

每解析器/字段的延遲示例

來自Marc-Andre Giroux的討論

因爲你知道哪些客戶請求哪些字段,所以你可以在棄用某些字段時主動通知他們。在PayPal,我們發現產品團隊變得積極主動,小規模交付更改後,更有可能提升遷移速度。大型程序和具有複雜計劃流程的大型遷移可能會令人望而生畏,並破壞開發人員的工作流程。

我們推薦的其他工具包括:

graphql-playground,用於測試開發模式下的查詢;
https://github.com/prisma-labs/graphql-playground

graphql-schema-linter,用於強制執行Schema命名約定;
https://github.com/cjoudrey/graphql-schema-linter

eslint-plugin-graphql,用於linting客戶端查詢;
https://github.com/apollographql/eslint-plugin-graphql

graphql-doctor,用於PR狀態檢查。
https://github.com/cap-collectif/graphql-doctor

購買與構建

在PayPal,我們最近開始使用Apollo Platform,產品團隊的反饋非常好!Apollo Graph Manager提供的儀器工具可顯示字段級別的深刻見解,提升對重大更改的信心,提供查詢白名單,併爲每個字段提供linting和內聯SLA計時來簡化客戶集成工作。

https://www.apollographql.com/platform/

Apollo Graph Manager不是免費的。我們可以自己構建這種工具嗎?也許可以,但不會那麼完美。我們沒有GraphQL基礎架構團隊。我們並不想等待12-18個月來構建同級別的事物,還要花精力維護它。我們現在就想兌現GraphQL的承諾!對比購買與構建的路線,購買Apollo Platform的決策明顯勝出。我們建議你也考慮一下。

投資GraphQL

如果你的公司正在使用GraphQL,則應該參與GraphQL的發展,併爲其進行投資。與其他公司建立聯繫,分享經驗並將學習成果帶回你的公司,這一點很重要。你應該加入GraphQL基金會,該基金會包括PayPal、Facebook、Twitter、AWS、Intuit和New York Times等公司成員。加入GraphQL貢獻者日之類的小組或當地聚會,或加入GraphQL工作組,還可以提交規範提案。

https://foundation.graphql.org/

第一次GraphQL貢獻者日

在企業中擴展GraphQL面臨的挑戰

GraphQL是很出色的工具,但我們要解決一些關於數據圖的組裝以及如何衡量成功的問題,才能充分享用它的好處。

許多倉庫

在2012年之前,PayPal用的是C++單體倉庫。從那時起,我們在許多領域和產品團隊中產生了數千個GitHub倉庫,構成了許多服務和應用程序層。對於使用單體倉庫的Facebook和GitHub這樣的公司來說,共享並不是什麼大問題。

GraphQL在許多倉庫中都很難用。如果沒有諸如存根遠程類型之類的自定義技巧,就無法引用或鏈接本地文件系統中不存在的遠程類型。開發人員很難發現或複用其他服務中定義的類型。

數據圖的組裝

用戶希望看到一個可以遍歷的單一內聚圖,而無需操心許多服務,無需動用許多服務來獲取所需的數據。實際上,組裝單個圖是很困難的。

一種解決方案是Schema拼接,其中網關消費底層GraphQL API的Schema向開發人員顯示單個Schema,還會將傳入的查詢委派給底層API。Marc-Andre Giroux寫了一篇出色的文章介紹了Schema拼接遇到的挑戰。通過Schema拼接,網關就有了粘合代碼,負責維護類型之間的關係,並確保子查詢正確執行。當網關所有者不知道這些類型之間的關係,並且產品團隊無法控制這一基礎架構時,粘合代碼就會出現問題。

Apollo Platform的解決方案是一種聯盟開發範式,使用自定義指令以聲明方式將類型鏈接在一起。它消除了網關中對粘合代碼的需求,合理地分離了關注點,並允許你擴展在本地開發中沒有的類型。我們可以期待一下,看看業界是否會採用它,以及聯盟將如何影響GraphQL規範。

如果構建單一數據圖是不可行的話該怎麼辦?在Paypal,我們爲快速迭代和持續學習進行了優化。許多開發人員認爲,自己沒有必要放慢腳步,與其他成員達成共識並融入更大的集體。這是我們文化的雙刃劍。如果單張圖是做不到的,我們還可以怎樣複用工作成果呢?另一個選項是GraphQL Modules和graphql-component之類的本地模塊。使用本地模塊,你可以選擇所需的類型和字段,所有代碼都在同一進程中運行,於是Schema拼接和聯盟遇到的許多問題就能解決了。但是,我們有許多相似的端點,並且服務器佔用並未減少。你可以接受嗎?

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

衡量成功

如前所述,GraphQL最亮眼的好處是開發人員經驗、生產力和靈活性。有時,性能方面可能會有一些收益,但這並不是你可以兌現的承諾。

如何衡量開發人員的經驗?如何做到客觀而不是胡亂分析一通?如何衡量開發人員的生產力?比較使用GraphQL的項目與其他項目的完成時間呢?

這仍然是我們面臨的一個挑戰。我們與開發人員交流,他們告訴我們工作輕鬆了許多,但是我們如何量化這一點呢?

喜歡這些挑戰嗎?

我們中有人會在本月的GraphQL峯會上發言。我們很樂意分享有關GraphQL的想法和討論!😊

原文鏈接
https://medium.com/paypal-engineering/scaling-graphql-at-paypal-b5b5ac098810

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章