从架构到代码:软件开发最新趋势解析
腳踏實地“敲代碼”,同時,不忘偶爾仰望下星空。
本文根據阿里云原生團隊資深技術專家陳立兵 (花名:雷卷)的直播整理而成,從領域驅動設計(DDD)、Reactive、Service Mesh 和代碼智能等幾個方面展開,聊一聊他眼里的軟件開發的發展趨勢。(阿里巴巴研發效能峰會即將開始,歡迎點擊文末閱讀原文了解)。
今年 4 月份的時候,InfoQ 發布了軟件架構與設計的趨勢報告。InfoQ 在技術趨勢報告中將軟件架構分為了 4 類,如下圖所示,從左到右依次是創新者(Innovators)、早期采用者(Early Adopters)、早期大眾(Early Majority)和晚期大眾(Late Majority)。在報告中可以看出,很多技術如微服務(Microservice)、領域驅動設計(Domain-driven Design)等已經非常流行,并成為如今軟件開發行業的主流了。對于早期大眾和晚期大眾部分的架構設計而言,很多部分與領域驅動設計相關,比如微服務、CQRS、事件驅動等。
在本次的分享中,也會介紹為什么領域驅動設計相關的技術會在InfoQ技術報告中占據如此重要的位置。并且也將會根據領域驅動設計展開到其他相關技術,比如 Service Mesh 等。
領域驅動設計(Domain-drivenDesign)
GitHub 上有一個 DDD 實踐指南,從下圖中可以看到領域驅動設計所解決的問題從架構設計一直到代碼層級,所以對于整個軟件研發周期來說,DDD 方法論還是比較流行的。而指導微服務劃分的一個重要理論基礎就是領域驅動設計。之前談到領域驅動設計,大部分時間總會探討如何識別限界上下文,如何使用戰術或者戰略方法等,而本次分享中則會介紹一個主流的趨勢,那就是 DDD + Reactive 。
之前的時候,領域驅動設計有分層結構、事件驅動等概念,但是也存在一個很大的問題就是將單體應用劃分成多個應用的時候,如何解決應用之間的通信問題。領域驅動設計中有限界上下文映射(BoundedContext Map)的概念,來解決兩個限界上下文之間的通信。之前 DDD 談到的解耦合方式主要是基于消息實現異步化的理論支撐,但是具體如何去做卻沒有具體的技術棧幫助大家實施。當然了,針對于每一種語言而言,具體實現可能不同,因為一些語言是純異步化支持的,可能已經內置了協程支持,因此在不同的技術棧里面會選擇不同的解決方案。本次分享中比較偏向于 Java 的技術棧,但是需要強調的是 Reactive 并不止針對 Java 。
Reactive 的好處在于使得兩個限界上下文之間的通信變成一個技術棧,這樣就可以使用Reactive 實施了。JDDD 是一個新的項目,其基于 Spring Data 實現。JDDD 也是一個開發包,其主要思想是讓開發者通過開發包以代碼的方式來呈現 DDD 要表達的思想。前面所提到的微服務則非常依賴限界上下文,借助它來確定邊界并進行劃分。此外,在 Could Native 和 FaaS 方案都會提到是面向事件驅動的,但是事件(Event)這一概念在領域驅動設計中很早的時候就已經提出來了,如果涉及到事件或者異步化相關的事情,就需要關注事件和領域驅動設計的關系了,當然目前來說,這一點已經非常成熟了。還有一點就是 DDD + CQRS , CQRS 簡單理解就是讀寫分離,比如 MySQL 數據庫使用 Master-Slave 機制使得讀數據和寫數據分開, Master 主要負責寫入, Slave 主要負責讀取,而 CQRS 也會在 DDD 中發揮很大的作用。目前來看,在整個架構設計里面,領域驅動設計是非常主流的,能夠幫助我們解決一些設計上面的問題。
Reactive
DDD 將應用劃分成多個小的限界上下文,接下來需要解決如何通信的問題了。而 Reactive 就提供了不同應用之間進行通信的指導方案,當然了 Reactive 也提供了對應的技術解決方案,比如 Async 能夠提供全異步化支持,當然這里的異步化只是說基于異步化技術。此外,還有 Observable 模式,可以說這是一個架構和設計的模式,這一模式應用很廣泛,最早是由微軟提出的,比如一個表格發生變化,其他表格也會根據這個表格發生相應的變化,這就是 Observable 觀察者模式。針對 Java 程序員而言,可以發現 Spring 在主推 Spring Reactive ,很多技術方案都是和 Reactive 相關的。此外,還有 Message 和 Event Driven,FaaS 和 CouldNative 在做通訊的時候都需要根據 Message 和 EventDriven 進行設計。
?
RSocket
在InfoQ的軟件架構和設計趨勢圖中,在早期采用者階段有一個Function Programming ,在早期大眾階段則有一個 ReactiveProgramming ,而在創新者部分則有一個 RSocket & Reactive Streams ,大家對于這個技術可能了解比較少,因此在本部分簡單介紹一下。如果大家關注 Spring 官方站點,那么可能了解 Spring 5.2 版本已經內置了 RSocket 的支持,但是并沒有很多相關文檔來介紹相關技術。前面提到, Reactive 是讓 DDD 的通訊模型有了理論基礎,所以這個 RSocket 協議就是為了實現 Reactive 理論基礎設計一個通訊模型。
如果大家了解 Reactive 語義,就會知道有一個背壓模式。當然,背壓模式與斷路保護模式類似,兩者的機制都是為了解決限流問題,因為消費方或者服務提供方因為突發流量不能支撐導致應用雪崩或者宕機。傳統模式最早使用消息隊列,是消息提供方主動將消息推送給消息消費方,此時存在的問題就是消費方消費不了,但是消息提供方還會繼續推送消息,使得消息消費方無法支撐導致系統不穩定。
后來出現了 Kafka ,其使用 Pull 模式,也就是需要多少條消息就去拉取多少條消息,因為 Kafka 支持消息堆積。但是使用Pull模式則需要設置時間間隔,此時出現的問題就是消息輪空怎么辦?也就是當發送消息時發現消息沒有就會輪空,此時就會不停地向 Broker 拉數據,這樣就會造成網絡浪費。所以在 Reactive 里面的背壓是將原來的推送模型增加了開關,當消息到達一定數量之后就不要推送了。這種主動推送機制的好處在于性能特別高,不需要去拉取,也不需要保存消息位點。總之,背壓機制能夠設置所能夠支持的最大拉取數量,如果在閾值的范圍內能夠做到性能的增高,同時也能保護消息的消費方。
在通訊方面,RSocket 有四個模型,比如 Request 和 Response、發布-訂閱模型、日志采集等。在使用 DDD 實現應用劃分之后,兩個應用之間需要進行通信,而 RSocket 就提供了四個模型,基本涵蓋了應用之間通信的場景,此外還提供了 Metadata Push ,比如所有的集群變化或者需要做限流都可以通過 MetadataPush 來實現。
RSocket 還可以做對等通訊,傳統的通訊模型都是 Client-Server 模式,但是在 RSocket下通信都是對等的,沒有 Client 和 Server 的分別,相互之間都可以進行消息發送。前面所提到的 RSocket 的設計模型和理念都是為了解決基于 Reactive 通信應用的各種問題。雖然 RSocket 這個技術方案并沒有得到很好的推廣,但是已經有很多技術社區提供支持了,比如 Spring 在 5.2 版本中就增加了對于 RSocket 的支持。因為推出的通信協議是 Reactive 的,但是背后需要涉及到數據庫操作或者其他等如果不是異步化的,就需要進行處理, Spring 在今年發布 Spring Boot 2.3 的時候就完善了對于 Reactive 的支持。舉例而言,從最前端的網關層通過 Spring 的 Web Flask 就能夠保證是 Reactive 的。
中間件、通訊模型以及 NoSQL 產品都是支持異步化操作的,能夠解決高并發問題,這些特性在很早的時候就已經添加到 Spring 里面了。此外,在開發的時候還有一點比較關鍵的就是數據庫,每個Java程序員在訪問數據庫的時候首先要設置數據庫連接池,需要考慮數據庫設計方案以及考慮哪一個連接池性能最高等問題。這是因為數據庫不屬于異步化的,需要通過創建多個連接來解決并發的問題。因此,在 Spring 的 R2DBC 里面增加了對于數據庫異步化的支持。目前Spring能夠支持數據庫的異步化了,但是還需要一段時間的等待,因為 R2DBC 和 JDBC 一樣,也是一個規范+驅動,但是基于 JDBC 的上層框架非常多,比如 Hibernate、MyBatis 等,而基于 R2DBC 的框架并不多,目前只有一個 Spring Data R2DBC 。因此,國內很多的開發者首選還是 MyBatis 。如果存在實現異步化的意向,那么基本上是從最開始接入的網關層協議一直到 NoSQL 數據庫,包括存儲文件系統,全部都實現異步化,這些目前也比較成熟了。
Service Mesh
再回到最開始 InfoQ 的軟件架構與設計趨勢,可以看到大多數與 Cloud Native 相關,比如 Serverless、Service Mesh、HTTP/2 和 gRPC 等,這些概念非常火爆,因此可以說 Service Mesh 在目前的技術趨勢中占據很高的地位。典型的 Service Mesh 架構還是基于 Istio+Envoy 的 Sidecar 經典架構。后來出現了 Dapr,它與 Isito+Envoy 架構的區別在于 Envoy 的 Sidecar 可以理解為代理,其目的在于將服務連接起來, Dapr 也會有一個 Sidecar ,這個 Sidecar 不只是做代理那么簡單,而是可以幫助開發者做非常多的事情,比如使用新的開發語言實現應用,但是 Kafka 或者 NoSQL 數據庫并沒有提供對應語言的 SDK ,或者即便提供了對應語言的 SDK ,但是這些 SDK 并不穩定,此時選擇一些新的技術就會受到一些約束。舉個例子,如果大家做一些大數據相關的工作,比如 HBase、Hadoop 等都是 Java 相關的 SDK 最穩定。而 Dapr 的 Runtime 可以很好地與外部系統交互,比如應用 gRPC 與 Dapr 的 Sidecar 通信,也可以和 Kafka 通信,將從 Kafka 中獲取的數據傳遞給 gRPC ,并且 Dapr 的 Runtime 使得開發者不需要了解通信協議背后的細節。
這樣的設計比 Isito+Envoy 架構要更好,因為如果只做代理,那么在客戶端還需要做大量的數據處理工作,而如果放到 Proxy 上來實現,就會更加復雜,此時就會變成 Dapr 的 Runtime。此外,阿里巴巴最近在做一些嘗試就是 RSocket Broker ,其基于 Reactive Mesh 實現,其與 Sidecar 結構不同,因為大多數基于基于消息或者事件驅動的都只需要發送消息即可,而 RSocket Broker 提供了應用之間的一攬子通信協議,不需要再選擇其他通信協議了。對于以上三種技術方案應該如何選擇,大家應該根據自身的實際情況進行判斷,因為技術選型沒有絕對的正確,但是目前來說是 Isito+Envoy 架構收到了大多數人的歡迎,因為這與 Kurbernates 整合比較方便,并且目前已經提供了比較完善的基礎設施。
FaaS
對于企業而言,可能核心系統只有幾個,但是總會有一些長尾的應用。如果之前沒有很好的 FaaS 方案,那么可能會做一個大而全的系統將這些小功能融合在一起,此時造成的問題就是修改代碼的困難,造成很多的麻煩,也不利于技術革新。FaaS 的好處在于可以將函數部署到邊緣,比如 CDN 邊緣或者 Edge 端。在通信部分, FaaS 主要是 Message+EventDriven 的,而目前很多的通信協議會用到 gRPC ,因為 FaaS 本身要求響應速度比較快,因此對于通信協議具有一定的要求。gRPC 的接口相對比較底層一些,在此之上還做成了 Reactive gRPC 能夠更方便大家通過 Reactive 來操縱 gRPC ,但是在寫代碼的時候可能并不知道是底層是基于 gRPC 的。在技術趨勢里面還有一個叫做 AsyncAPI ,其實在大家工作中,很多框架都支持從代碼直接生成 OpenAPI ,比如 SpringDoc 等。
目前還有一個技術趨勢是 FaaSWebAssembly ,其也是和 FaaS 結合的。眾所周知,如果 FaaS 不是高頻使用的話,會出現容器拉起時出現一定等待時間的問題,但是在某些場景下,對于等待時間存在比較嚴格的限制。那么此時如果使用傳統容器的解決方案往往難以實現,而 WebAssembly 這種技術解決方案就能夠充當函數的鉤子,能夠滿足上述需求。同時,由于 WebAssembly 也是 W3C 新推出的規范,和之前的 HTML、CSS、JS 網頁三劍客結合成為了網頁四劍客。此外,在 FaaS 部分,還有最近推出的 Deno 可以很好地支持 WebAssembly 機制。而因為很多開發同學會關心 Rust 這一編程語言,而 Deno 對于 Rust 具有良好的支持,因此很多人會選擇使用 Deno 作為 FaaS 的 Runtime 來支持 FaaS 的運行。
代碼智能
目前還有一個技術趨勢就是代碼智能,通過前面所提到的技術架構,能夠滿足企業的架構選型,那么接下來就肯定會涉及到代碼。對于代碼而言,主要有兩點,一個是代碼生成,另一點是手寫代碼。代碼生成主要是腳手架,能夠快速將代碼的框架生成,而不需要自己寫配置項等,目前這項技術已經非常成熟了。這部分的工具主要有 IntelliCode 、Codota、Kite 以及各種 Cloud IDE 等。在寫代碼的時候會遇到的問題就是技術往往變化很快,每間隔 4、5 個月就會推出新的框架或者技術,而因為開發者關注的是開發效率,所以即使有 Code AI 能力,但是在某種程度上還是會依賴 Cloud IDE 特性。因為 Cloud IDE 在跟進某些技術上面的速度比較快,它往往能夠很快知道客戶新的需求是什么。?
Code Generation +IDE
目前有很多的代碼生成工具,幫助大家解決框架生成問題。比如Scaffold,start.spring.io是可擴展的代碼框架生成器。Code Generation是Java自帶的 Annotation 機制,這一點可能大多數同學沒有關注,但是在很多的場景下也會使用到,其生成的代碼能夠做到性能更高。此外,目前很多的 IDE ,比如 JetBrains+VS Code 都有集成的工具,幫助開發者快速生成代碼框架結構。
總結
以上是生活随笔為你收集整理的从架构到代码:软件开发最新趋势解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高质量的缺陷分析:让自己少写 bug
- 下一篇: 业务代码中,太多 if else 怎么办