Bugsnag(注:一家雲端bug監控服務商)天天處理數以億計的錯誤信息,爲了處理這些數據,考慮優先構建一個可擴展,性能強大的後端系統,並從中學到不少有挑戰性的技術。最近,咱們推出了新版本的儀表板,這個項目要求擴展系統,來處理服務呼叫的顯著增長,這些呼叫是跟蹤用戶發佈和會話所需的。編程
儀表板的發佈在進行中,工程團隊將Bugsnag的後端功能分解成稱之爲管道(pipeline)的微服務體系。將管道擴展到支持發佈,意味着增長新的服務,並修改現有服務,也可預見到許多新的服務器和客戶端的交互。爲了處理上述架構的變化,須要採用一致性的方式來設計,實施和集成企業的服務。Bugsnag是一家多語言的公司,服務是用Java,Ruby,Go和Node.js等多語言編寫,所以企業須要一種與平臺無關的方法。後端
本文將介紹爲何咱們最終選擇了gRPC做爲Pipeline的默認通訊框架。緩存
達到REST API設計的極限安全
現有系統傳統上使用具備JSON有效載荷的REST API進行同步通訊。這種選擇是基於佔壓倒性比例的成熟度、熟悉度和工具的可用性作出的,可是隨着跨洲際工程團隊的增加,企業須要設計一致的,基於RESTful API的工具。服務器
不幸的是,這感受就像試圖將簡單的方法調用變成一個數據驅動的RESTful界面。這知足了RESTful接口的verb,header,URL標識符,資源的URL和有效載荷的神奇組合,並作了一個清潔,簡單,看起來幾乎不可能實現的功能界面。RESTful有不少規則和解釋,在大多數狀況下會致使REST ish接口,這須要花費額外的時間和精力來保持其純度。網絡
最終,考慮到RESTAPI的複雜性,咱們找到了替代方案。但願微服務儘量相互隔離,減小交互和解耦服務。它可讓企業在很短的時間內創造出一個可行的服務,並防止跳過hoops。架構
評估REST的替代方案框架
不要輕易選擇通訊框架。大型組織(如Netflix)能夠擁有超過500+個微服務的後端系統。遷移這些服務以取代不充分的服務間通訊會花費大量時間,從後勤和財務角度看這很不切實際。花時間從一開始就考慮正確的框架,能夠省去不少將來的浪費。編程語言
咱們花了大量的時間來制定評估標準和研究、選擇。Bugsnag到底長什麼樣子呢?分佈式
技術標準
在研究可用選項時,使用了一些特定的標準來評估。要考慮的事情是基於微服務架構的最有效的方法。主要目標是自由地使用通訊,消除通訊的複雜性,瞭解每項服務的責任所在。其中的一些技術問題是:
速度 - 對於大量的請求/響應API調用,須要將調用自己的延遲做爲性能和用戶響應速度的最小因素。延遲的主要組成部分是鏈接成本,傳輸成本和消息編碼/解碼時間。
基礎架構兼容性 - 框架在基礎架構中扮演的角色如何?主要是關於負載平衡和自動擴展?咱們使用託管在Google雲端平臺上的Kubernetes服務,所以須要框架來兼容這種環境。
開發工具 - 在實現框架時,提供儘量小的摩擦將會使開發人員更快捷。哪些工具能夠幫助編碼,本地測試端點,以及單元和集成測試的stubbing/mocking?當事情出錯時,咱們須要可以看到包括內容在內的請求信息。消息格式等因素也可使調試更容易依賴於工具,例如JSON消息是人可讀的,可是二進制消息將須要額外的努力來解碼。
成熟度和採用 - 對於初創公司來講,資源是有限的,須要花費在公司的核心業務上,而不是修復,測試和加強第三方框架。諸如框架的普及,大規模使用的例子,社區的活躍程度以及框架自己的成熟度等因素都是穩定性的良好指標。須要強調的是,選擇一個解決具體問題的框架,而並不是選擇最新最熱的。
多平臺支持 - 在真正的微服務思惟中,使用最適合其目的的語言編寫企業的服務,目前包括Java,Ruby,Go和Node。框架是否爲現有的語言選擇提供了一流的支持,同時提供了用其餘語言編寫新服務的選項?
代碼量 - 框架應該有助於下降工程成本。企業須要編寫和維護多少代碼才能使其工做?與業務邏輯相比,這是多少樣板代碼?
安全 - 全部的內部通訊都應該被認證和加密。咱們須要可以使用全部通訊的SSL / TLS(或等價物)。
設計上的考慮,並不是都與技術有關
服務API是最重要的接口之一,由於在開發過程當中對設置服務指望相當重要。解決服務API的設計是一項艱鉅的任務,當不一樣的團隊負責所涉及的不一樣服務時,該任務會被放大。最大限度地減小因爲預期不匹配而浪費的時間和精力,與縮短編碼時間同樣有價值。因爲Bugsnag擁有跨地區的工程團隊,所以溝通時間有限。必須經過簡化溝通,確保事情不用那麼多解釋,不然錯誤很容易產生,事情很容易被拖延。
如下是在選擇框架時的一些設計考慮因素:
強類型 - 消息是不是強類型的?若是經過服務邊界發送的消息清晰可見,那麼能夠消除因爲類型而形成的設計和運行時錯誤。
打開解釋 - 可以直接從服務API規範生成客戶端庫,減小了誤解的問題。錯誤條件 - 有一套明肯定義的錯誤代碼能夠更容易一致地交流問題。
文檔 - 服務API應該是易讀易懂的。定義服務API的格式應該儘量清楚,準確地描述端點。
版本控制 - 更改是不可避免的,這是一個很好的選擇,在某些時候,服務API將須要修改。所使用的消息傳遞格式和服務定義能夠影響修改API並將其部署到生產的容易程度。是否有明確的路徑來增長版本及其相應的庫,並推出更改?
微服務最佳實踐,爲何可擴展性是重要的
除了上面列出的標準外,還須要選擇一個易於擴展的框架。隨着微服務的發展,企業須要愈來愈多的「開箱即用」功能,發展的同時,爲系統增長了更多的複雜性。所以企業但願的功能包括:
異常處理 - 在請求級別提供一個處理異常的機制。它容許捕獲有關請求的重要上下文元數據,例如發出請求的用戶,能夠用例外報告。咱們使用Bugsnag輕鬆地監視這些異常。
智能重試 - 在特定條件下重試請求,例如僅在5xx狀態碼上。這包括支持各類退避策略,如指數退避。
服務發現配置 - 將通訊框架鏈接到流行的服務發現應用程序(如Zookeeper,Eureka或Consul)的選項能夠提供一種快速簡便的解決方案,以繞過企業的架構來請求路由。
度量、跟蹤和日誌記錄 - 可觀察性對於複雜的分佈式系統是必不可少的,可是應該當心監視的內容。在服務邊界自動收集指標和跟蹤信息能夠快速回答常見問題,例如「個人服務對請求響應緩慢嗎?」以及「請求失敗的頻率如何?」。
熔斷 - 這種模式能夠經過自動檢測問題和快速失敗來防止級聯服務故障。也能夠由長時間緩慢的請求來觸發,以提供響應降級的服務而不是不斷地超時。
緩存和批處理 - 經過使用緩存或批處理請求來加速請求。
大多數框架不會提供全部功能,但至少它們應該是可擴展的,以便在須要時添加。
什麼是gRPC和協議緩衝區?
沒有一個框架是萬能的。咱們探索的一些選項包括Facebook的Thrift,Apache Hadoop的Avro,Twitter的Finagle,甚至使用JSON模式。
咱們的需求更接近於遠程程序調用(RPC),給予所須要的細粒度控制。使用RPC的另外一個吸引力是使用接口描述語言或IDL。IDL容許以獨立於語言的格式描述服務API,將接口與任何特定的編程語言分離。他們能夠提供一系列的好處,包括服務API的一個單一的事實來源,並可能被用來生成客戶端和服務器代碼來與這些服務進行交互。IDL的例子包括Thrift,Avro,CORBA,固然還有ProtocolBuffers。
最後,明確的獲勝者是基於協議緩衝區的gRPC。
什麼是gRPC?
咱們選擇了gRPC,由於它知足了咱們的功能需求(包括將來的可擴展性),背後的活躍社區以及HTTP / 2框架的使用。
gRPC是由Google開發,設計用於傳統的RPC調用。該框架使用最新的網絡傳輸協議HTTP / 2,主要用於經過使用流的單個TCP鏈接來實現低延遲和多路複用請求。與REST over HTTP / 1.1相比,gRPC很是快速和靈活。
gRPC的性能對於設置管道來處理儀表板發佈的大量增長相當重要。此外,HTTP / 2是下一個標準化的網絡協議,能夠利用爲HTTP / 2開發的工具和技術(如Envoy代理),併爲gRPC提供一流的支持。因爲多路複用流支持,gRPC支持雙向通訊,不限於簡單的請求/響應呼叫。
什麼是Protobufs(協議緩衝區)?
Protocol Buffers或protobufs是定義和序列化結構化數據爲高效的二進制格式的一種方式,也是由Google開發的。兩者的有效結合,也是咱們選擇gRPC的主要緣由之一。
之前有許多與想修復的版本相關的問題。微服務意味着必須不斷更新,須要適應並保持向前和向後兼容的接口,protobufs對此很是有用。因爲是二進制格式,因此它們也是經過wire快速發送的小型有效載荷。
Protobuf消息使用關聯的IDL進行描述,它提供了一個緊湊的,強類型的,向後兼容的格式來定義消息和RPC服務。咱們使用最新的proto3規範,並在此處顯示protobuf消息的實際示例。
全部字段proto3都是可選的。若是未設置字段,將始終使用默認值。這與字段編號相結合提供了一個API,能夠很是抵抗打破變化。經過遵循一些簡單的規則,向前和向後兼容性能夠成爲大多數API更改的默認值。
protobuf格式還容許定義RPC服務自己。服務端點與消息結構共存,在單個protobuf文件中提供RPC服務的自包含定義。對於咱們的跨洲際的工程團隊來講,這很是有用,他們能夠從一個文件中瞭解服務如何工做,生成客戶端並開始使用它。如下是咱們的服務之一:
該框架可以生成代碼來使用protobuf文件與這些服務進行交互,這是另外一個優點,它能夠自動生成須要的全部類。這個生成的代碼負責消息建模,並提供一個存根類,其中包含與您的服務端點相關的重複方法調用。
支持多種語言,包括C ++,Java,Python,Go,Ruby,C#,Node,Android,Objective-C和PHP。可是,使用protobuf文件維護和同步生成的代碼是個問題。咱們已經可以經過使用Protobuf文件自動生成客戶端庫來解決這個問題,會在即將發佈的下一篇博客文章中分享更多的內容。
gRPC最好的特性之一是支持中間件模式,被稱爲攔截器。它容許擴展全部的gRPC實現(這對企業來講很重要),可以輕鬆訪問全部請求,從而實現本身的微服務最佳實踐。gRPC還內置了對一系列認證機制的支持,包括SSL / TLS。
gRPC社區
咱們正處於gRPC採用的開始階段,期待社區提供更多的工具和技術。很高興可以加入這個充滿活力的社區,並對將來的項目有一些想法,咱們但願看到這些項目是開放源代碼或咱們本身寫的。
gRPC工具的當前狀態
gRPC比較新,缺少可用的開發工具,特別是與經驗豐富的REST over HTTP / 1.1協議相比。搜索教程和示例時,這一點尤爲明顯,由於只有少數有用的信息。二進制格式也使消息不透明,須要努力解碼。雖然有一些選擇,例如JSON代碼轉換器能夠幫助,但預計須要作一些基礎工做,以便爲gRPC提供順暢的開發體驗。
咱們喜歡用Apiary 來記錄外部API。使用服務協議緩衝區(protobuf)文件自動生成交互式文檔的等價物,將是理想的有效的內部通訊gRPCAPI。protobuf文件的靜態分析在運行時能捕獲更多的bug。使用Checkstyle做爲Java代碼,而且把它用做相似於protobuf的文件。自定義攔截器能夠提供跟蹤,日誌記錄和錯誤監視功能。咱們但願開源咱們的Bugsnag gRPC攔截器,以自動捕獲並向Bugsnag報告錯誤。gRPC的增加和採用
在過去幾年中,gRPC的普及度大幅增加,Square,Lyft,Netflix,Docker,Cisco和CoreOS等公司大規模採用。Netflix Ribbon是基於RPC調用使用REST的微服務通訊框架的事實標準。今年,他們宣佈,因爲其多語言支持和更好的可擴展性/可組合性,他們正在向gRPC過渡。該框架最近也於2017年3月加入了CNCF基金會,支持重量級的Kubernetes和Prometheus。gRPC社區很是活躍,與開源gRPC生態系統 列出了許多gRPC激動人心的項目。
另外,gRPC有咱們認同的原則
Lyft在轉向gRPC方面作了大量的討論,這與咱們的經驗很是類似:使用Protocol Buffers和gRPC生成統一的API。值得一試。
gRPC如今還處於初期階段,存在一些明顯的磨合問題,但將來前景光明。總的來講,咱們對gRPC如何整合到後端系統很是樂觀,而且很高興見證這個框架的發展。
原文連接: