Hyperf 2.0 釋出!想象的開端!

huangzhhui發表於2020-06-22

Hyperf 從 2019 年 6 月 20 日釋出 1.0 版本至今,獲得了非常多的關注和使用者,短短的一年期間,Hyperf 飛速發展和持續迭代,同時也擁有了非常驚人的資料。

  • Github 2700 stars / Gitee 328 stars
  • 113 名 contributors
  • 1100+ Pull Requests
  • 共釋出 47 個版本
  • 92 個程式碼倉庫
  • 1438 個單元測試用例,4412 個斷言條件

這些資料是整個開源社群共同努力的結果,感謝所有支援 Hyperf 的大神的厚愛,期待未來更多的支援與合作。

在持續迭代的過程中,我們也產生了一些新的思路,我們對這些思路進行了驗證、迭代、再驗證、再迭代,並最終將這些思路的實現沉澱到了 Hyperf 中來,並於今日,以 2.0 版本正式釋出了 ???

感謝 Hyperf 團隊成員日以繼夜的努力,使這些設想成為了可能。

主要功能迭代

AOP 和註解功能底層重構

在 1.1 版本下,儘管提供了非常強大的 AOP 和註解功能,但也仍有一些限制和不足如下:

  • AOP 只能切入由 hyperf/di 元件管理的物件,無法切入其它方式建立的物件,如 new
  • 通過 DI 獲取的類實際上是由 AOP 生成的一個原始類的子類,在子類上完成了對方法的修改,以完成 AOP 的功能實現,而子類的類名與原始類是不一致的,也就導致了 get_class(), __CLASS__ 之類的方法或常量獲取的資料可能會不對;
  • 同上,異常堆疊資訊會充滿了代理類的鏈路,不容易看清楚呼叫鏈路;
  • 同上,由於是通過繼承實現的代理類,故一個 final 類是無法被切入的;
  • 同上,對一個父類進行 AOP 切入後,這個類的子類並不會被切入;
  • 通過 new 例項化的一個物件 @Inject@Value 註解無法生效;
  • 您無法在一個類的建構函式內使用通過 @Inject@Value 註解獲取的值;
  • 在 trait 內通過 @Inject@Value 註解標註的屬性無法正常運作;
  • 在 PHP 8 下無法通過類成員屬性的強型別宣告替代 @var 宣告來指定 @Inject 時的類宣告;
  • 使用註解時必須宣告對應註解的名稱空間;
  • 定義 Aspect 類時無法在註解上一併定義要切入的目標;

以上列舉了一些 1.1 下 AOP 的限制和不足,而在 2.0 版本下,我們對底層的邏輯進行了重構,上面這些問題全部都被解決掉了,其中最具想象空間的是通過新的 AOP 功能,你可以對幾乎所有的類和註解進行動態的切入了,無論是通過 new 例項化出來的物件還是通過 DI 建立出來的物件,無論是切入了這個類的父類還是更深的繼承層次,無論是 final 類還是一個普通類。

簡而言之,在新的機制下,Hyperf 會在啟動時掃描所有的掃描域,並掃描程式碼得到所有類的 AST 抽象語法樹,並從中解析所有與 AOP 相關的後設資料,根據這些後設資料來對要被代理的類進行 AST 節點資訊的修改,並注入 AOP 相關的邏輯,最終通過 PHP 的 Autoload 機制,在例項化一個類並進行自動載入時,ClassLoader 返回經過修改後的類檔案。

那麼用正向的角度來描述這個功能的變更如下:

  • AOP 可以作用於 new 關鍵詞建立的物件;
  • AOP 可以作用於 Final 類;
  • 您可以在建構函式中使用 @Inject@Value 註解標記的屬性值;
  • 代理類的類名和繼承關係與原類一致;
  • 對父類進行 AOP 切入,子類同樣生效;
  • AOP 代理類快取和註解快取可以自動識別是否需要重新生成;
  • 通過 new 關鍵詞建立的物件,@Inject@Value 註解標記的屬性值可以生效;
  • 可在 trait 中使用 @Inject@Value 註解,並作用於 use 的類;
  • PHP 8 下使用 @Inject 註解時可通過強型別宣告替代 @var 註解宣告;
  • 提供了註解全域性引入機制,以達到在使用註解時允許不引入對應的名稱空間;
  • 在定義 Aspect 時可直接在 @Aspect 註解上定義要切入的目標類和註解;
  • Aspect 增加了 priority 優先順序屬性,可定義多個 Aspect 類的優先順序;
  • 使用依賴懶載入功能時無需再註冊 Hyperf\Di\Listener\LazyLoaderBootApplicationListener 監聽器;
  • 新增 annotations.scan.class_map 配置,通過該配置可以直接將任意類替換為你指定的類;

支援 Coroutine Server 協程服務

在 Swoole 4.4 版本時新增了 Coroutine Server,通過該功能可以通過協程的形式來執行 Server,也就意味著可以在一個程式下同時執行多個不同協議的 Server 來提供服務,這樣的做法更加的協程,且單程式的模型對 Docker 和 Kubernetes 更加友好,通過調整 Pod 的數量即可對應到真實的程式數;
在 Hyperf 2.0 版本,我們也對 Coroutine Server 進行了支援,您可通過在 config/autoload/server.php 配置檔案中新增一個 type => Hyperf\Server\CoroutineServer::class 配置即可切換到 Coroutine Server 的執行模式去。同時一些原本要使用自定義程式來實現功能的場景,如配置中心的配置拉取、服務監控的資料提供、訊息佇列消費者的消費等,我們的提供了對應的協程模式的執行模式,最終只需要啟動一個程式即可完成所有之前需要多個程式才能完成的事情。

增加 ResponseEmitter 機制

在 1.1 版本下,我們只能在 HTTP Server 中返回由 hyperf/http-message 元件或 hyperf/http-server 元件提供的 Response 物件,但其它同樣遵循了 PSR-7 標準的 Response 卻無法正常響應,比如 Guzzle 客戶端請求後獲得的 Response 物件,在 1.1 下需要轉換為 Hyperf 的 Response 物件才能正確響應客戶端請求。而在 2.0 版本下,通過 ResponseEmitter 機制,您可以直接返回任意符合 PSR-7 標準的 Response 物件,以獲得更強的相容性。

增加 Reactive-X 元件

hyperf/reactive-x 元件提供了 Swoole/Hyperf 環境下的 ReactiveX 整合。關於 ReactiveX,微軟給的定義是,Rx 是一個函式庫,讓開發者可以利用可觀察序列和 LINQ 風格查詢操作符來編寫非同步和基於事件的程式,使用 Rx,開發者可以用 Observables 表示非同步資料流,用 LINQ 操作符查詢非同步資料流, 用 Schedulers 引數化非同步資料流的併發處理,Rx 可以這樣定義:Rx = Observables + LINQ + Schedulers。而 Reactivex.io 給的定義是,Rx 是一個使用可觀察資料流進行非同步程式設計的程式設計介面,ReactiveX 結合了觀察者模式、迭代器模式和函數語言程式設計的精華。

通過該元件,您可以在 Hyperf 中實現響應式程式設計的正規化,為您的應用提供更多的可能性。

統一 HTTP 異常

在 1.1 版本下,HTTP Server 在處理如 路由未找到(404)請求方法不允許(405) 等 HTTP 異常時,是在 Dispatcher 中提供對應的方法,並直接響應 Response 結果,如果需要自定義對應的響應結果,則需要通過 DI 來重寫 Dispatcher 類的對應方法。而在 2.0 版本下,我們對異常的處理方式進行了統一,統一丟擲 Hyperf\HttpMessage\Exception\HttpException 異常類的子類,並統一由預設提供的 Hyperf\HttpServer\Exception\Handler\HttpExceptionHandler 來處理響應的結果,這樣一來使用者便可以非常便捷的通過 ExceptionHandler 來對異常響應進行統一的處理了。

升級到 2.0 版本

從現在的 1.1 版本升級到 2.0 版本,也是一件非常輕鬆的事情,我們提供了一份詳盡的 2.0 升級指南 來指引您完成對應的升級動作,具體可查閱該升級指南;

更多

以上只是筆者本人最為期待的功能迭代,只是冰山一角,2.0 版本還包含了大量的細節更新以及新功能,具體可以查閱 版本更新記錄 獲得更多的細節資訊。

總的來說,2.0 是一個充滿了想象空間的版本,它提供了遠超原來的可能性,我們可以在 Hyperf 上、在 Swoole 上、在 PHP 上,去想、去做更多原來不曾深思過的事情。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章