環團包圍《BBC》總部 要求以「二戰狀態」報導氣候變遷

摘錄自2019年10月11日自由時報報導

關注氣候變遷議題的環保團體「反抗滅絕」(Extinction Rebellion)11包圍英國《BBC》倫敦總部的消息,呼籲該公共媒體將氣候變遷視為如「二戰」般的緊急狀態報導,並向社會大眾說實話。

環團發言人麥卡錫(Donnachadh McCarthy)表示:「我們聚集於此是因為《BBC》拒絕宣布『氣候緊急狀態』,且他們不斷將『高碳排放』的生活正常化、合理化,像他們的節目《頂級跑車秀》(Top Gear)就是一例。」

《BBC》發言人則表示她目前無法評論總部的安全問題,她拒絕為《BBC》的報導力度進行回覆。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

中央地方攜手合作,全面啟動臺灣智慧水聯網

環保署8月17日在新竹市舉辦「2020臺灣智慧水聯網」啟動發表會,正式發表5種水質感測元件及固定式、移動式、手持式等3款水質感測器,同時發給13個縣市政府400臺感測器,合辦建構我國智慧水聯網。智慧水聯網為打破傳統人工採樣限制,利用水質感測器每分鐘感測河川水體的酸鹼度、電導度、溫度及溶氧,結合地理資訊系統定位,以AI人工智慧即時監控水質在時間及空間上的變化,達到環境智慧執法、推動公民環境教育以及拓展相關產業跨域應用等目標。

智慧水聯網過去4個月試驗應用期間,於3縣市共查獲17件異常案例,有2件地檢署偵辦中,持續追繳罰鍰,在水質感測器輔助下,打擊不肖廠商效果顯著,讓污染無所遁形。環保署為擴大科技執法應用層面,已與全臺13個縣市合作,將布設在陳情或列管工廠集中地區,24小時水質監控不間斷,並將針對偵測的污染,即時智慧派遣查處污染。

環保署表示,除了智慧稽查外,5G時代來臨,環保署所研發之手持式水質感測器具備成本低、使用簡單、結合個人行動裝置等優點,學術單位可利用感測器推動環境教育、探索水體生態等課程,也成為河川巡守隊巡查新利器,鼓勵隊員巡檢並參與污染通報、髒亂清理等工作,讓政府民眾齊心共創護水新生活。

環保署也持續活化產業跨域應用,利用新型感測技術推動各類用水水質管理,促進產業交流與技術媒合,提升產業數位轉型量能。未來環保署將以「優化環境治理、驅動民間感測、開展產業應用」為目標,達到「感測,無水不在;應用,無限可能」數位時代願景!

新聞來源:https://enews.epa.gov.tw/Page/3B3C62C78849F32F/2042f3c7-e254-47af-aeca-3a6999f0178c

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司“嚨底家”!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

特斯拉代號 D 新車出爐 搭半自動駕駛系統

  美國電動車厰特斯拉(Tesla)執行長馬斯克(Elon Musk)發表代號「D」的新一代豪華電動車 Model S,搭載雙電動馬達,由前一代的後輪驅動,升級為全時四輪傳動(AWD),起步加速到 100 公里只需 4 秒,充飽電可行駛 442.57 公里,採用鋰電池提供馬力,讓充電更快速方便,預計 12 月開始出貨。   馬斯克在美國時間 10 月 9 日發表先前他在推特預告的代號 D 車款,其實就是現有車款 Model S 車款的升級版,D 指的就是雙馬達(Dual Motors)。馬斯克表示,雙馬達 AWD 的設計,可提升行路能力,應付歐美惡劣天候,並提升效率、增強動力及加速性。   此外,新車款同時搭載全新自動駕駛(autopilot)軟體,配備包括長距離雷達、影像辨識鏡頭及 360 度的超音波聲納,雖無法完全自動駕駛,但可以判讀交通號誌與辨別行人,具備路邊停車輔助功能。且若停在自宅門口,車主可以召喚愛車,車內的車用電腦還能連結至車主行事曆,需要出門時汽車就能準備就緒。   (Source:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

約定民生銀行 特斯拉將在中國20城市建400個充電樁

特斯拉與民生銀行達成合作,雙方約定將共同在中國20個城市的民生銀行自有營業廳及社區金融門店建至少400個充電樁。截至8月,特斯拉在中國建成的目的地充電裝置已超過370個。在此之前,特斯拉用了一年時間才在中國建了16個超級充電站。   此前,特斯拉已經與銀泰、SOHO和中國聯通簽署過類似的合作協定。其中,特斯拉與地產商銀泰集團宣佈合作啟動“目的地充電”項目,充電1個小時可行駛40公里;還計畫年內依託聯通營業廳在全國120個城市共同建設400個目的地充電站和20個城市超級充電站。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!

電動機車 E-bike 上路 試營運前 30 分鐘免費

  除了有腳踏車 U-bike 可租借,現在連電動機車都能租借得到了。台灣城市動力公司開發自動化公共 E-bike 租借系統,試營運期間提供前 30 分鐘免費優惠,民眾前往租借還可參加多項大獎的抽獎活動。   台灣城市動力公司建構的E-bike租借系統,上周率先在新北市板橋區縣民大道與漢生東路交口的車站停車廣場供國人自由租借,民眾透過悠遊卡註冊後就可選車、取車、還車、付費,方便性與租借U-bike無異。開放試租首日在一個站點就吸引數百民眾註冊借車,該公司相信未來E-bike站點持續擴增後,勢必讓政府推動的機車電動化進度呈跳躍式進展。   台灣城市動力公司總經理洪國修表示,環保減碳是政府重要的施政項目,為提高民眾騎乘電動二輪車之意願,環保署除提供購買電動車 2 萬 4 千元的補助,台灣城市動力公司也配合這項政策,從便民方向建置全球首創的電池交換站系統(BES),民眾在 30 秒即可完成電池更換,免除電池充電過久或保固維護的不便。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

其他動力電池車望塵莫及 鋁氣電池續航達 1,600 公里

不讓美國特斯拉電動車專美於前,美鋁公司(Alcoa)宣稱已完成由以色列飛能(Phinergy)研發成功的鋁氣電池(Al–air batteries),並且達成航距超過 1,600 公里的測試。這項研發讓相繼投入電動車領域的德國寶馬、日本豐田等相形失色。   美鋁和以色列飛能最近在美國蒙特利爾維倫紐夫賽車場,測試了以鋁空氣電池為能源的車輛,驚人的是續航里程竟上升到 994 英里。在金屬空氣電池中,鋁空氣電池就是其中之一,如今這 1,600 千公里的續航力已遠超過包括特斯拉 Model S 在內等現有各類動力電池車。其他插電式混合動力車、增程式電動車(續航在 500 公里左右)或者豐天、現代所謂的氫燃料電池車(續航超過 500-600 公里)等,也同樣望塵莫及。   飛能公司說,這一組電池重僅約 100 公斤,裝有 50 塊電池板,平均 1 塊鋁空氣電池板就可驅動車輛行駛約 32 公里。但鋁空氣電池的放電過程會導致陽極腐蝕產生氫,導致陽極材料過度消耗,並增加電池內部損耗,使其商業化進程放緩。   然而,鋁空氣電池維護非常方便。按現有技術方案,鋁空氣電池是作為鋰電池的補充電源,鋰電池能量耗盡後,鋁空氣電池才接手,所以使用者無需進行充電,每 1-2 個月注入自來水維持其化學反應,每年也只需讓技術人員進行一次保養即可,電池壽命甚至可達 20 至 30 年。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

東元強攻菲電動車市場 擬明年第二季投產

東元海外新布局持續有所斬獲,公司年初獲菲律賓馬尼拉最大車隊千台電動吉普巴士訂單,首批 50 輛將於年底前陸續出貨。東元表示,菲律賓當地擁有銀行的前三大機車經銷商今年正式向公司提出合作,並期盼公司能在當地設廠就近供應,而內部評估對方所提之方案可行性很高,預期最快 2015 年第二季就會在當地投產,未來該廠將同時生產特種電動三輪車、電動吉普巴士等。   東元集團看好電動車市場大有可為,但無意與美國 Tesla、德國 BMW、日本豐田、本田及日產等國際大廠競逐純電動車市場商機,利用本身擅長的馬達及電控系統強項發展特種電動車,作為進軍全球電動車市場的試金石,目前拿下雲林西螺果菜市場 8 百輛電動搬運車,約 2 億元標案。   此外,東元在土耳其市場也有所進展;公司指出,預期土耳其市場 的 2014 年可帶進營收貢獻約 9 千萬元,2015 年布局效益將更進一步顯現,並以挑戰倍增為銷售目標;同時,土耳其亦可作為業務拓展的跳板,有助於進一步把旗下機電、馬達、電控與商用空調等產品,銷售至歐洲、中東與非洲等市場。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

日 TDK 開發出電動車無線充電技術

日本 TDK 開發出了用於電動車(EV)及插電式混合動力車(PHV)的非接觸供電系統。當電動車或插電式混合動力車停在使用了該系統的停車場時,無需使用有線電纜即可充電。若在公路上大規模鋪設該系統,甚至可能讓電動車等邊行駛邊充電,預計在 2018 年上路應用。   TDK 今年 4 月與美國麻州的創業企業 WiTricity 合作,獲得有關電動汽車無線供電的技術經驗。基於 WiTricity 的技術,並利用 TDK 擅長的磁線圈技術成功開發了無線供充電系統。系統由無線供電用送電線圈和受電線圈組成,線圈之間的距離即使超過 10 厘米也能送電。TDK 計劃從 2015 年上半年開始向汽車廠商等提供樣品。   此外,TDK 還針對電動車的行駛途中供電,開始試驗。在周長為 30 米的試驗場地路面下方,每隔 5 米鋪設 6 個送電線圈,讓試製車在上方行駛。據稱,目前已能以 5 公里時速行駛 120 公里。  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

小師妹學JVM之:java的字節碼byte code簡介

目錄

  • 簡介
  • Byte Code的作用
  • 查看Byte Code字節碼
  • java Byte Code是怎麼工作的
  • 總結

簡介

Byte Code也叫做字節碼,是連接java源代碼和JVM的橋樑,源代碼編譯成為字節碼,而字節碼又被加載進JVM中運行。字節碼怎麼生成,怎麼查看字節碼,隱藏在Byte Code背後的秘密是什麼呢?快跟小師妹一起來看看吧。

Byte Code的作用

小師妹:F師兄,為什麼Java需要字節碼呢?直接編譯成為機器碼不是更快嗎?

小師妹,Java的設計初衷是一次編寫,到處運行。為了兼容各個平台的運行環境,java特別為各種平台設計了JVM。

我們可以把JVM看做是一種抽象,對外提供了統一的接口。這樣我們只需要編寫符合JVM規範的代碼,即可在JVM中運行。

回想下之前我們提到過的java的執行過程:

  1. 編寫java代碼文件比如Example.java
  2. 使用java編譯器javac將源文件編譯成為Example.class文件
  3. JVM加載生成的字節碼文件,將其轉換成為機器可以識別的native machine code執行

小師妹:F師兄,我有一個大膽的想法,JVM的作用是將字節碼解釋或者編譯成為機器碼。然後在相應的運行環境中執行。那麼有沒有可能,不需要JVM,不需要機器碼,而是直接在對應的平台上執行字節碼呢?

愛因斯坦說過沒有想像力的靈魂,就像沒有望遠鏡的天文台。小師妹你這個想法很好,這種實現有個專業的說法叫做:Java processor。

Java processor就是用硬件來實現的JVM。因此字節碼可以直接在Java processor中運行。

其中比較出名的是Jazelle DBX,這是一個主要支持J2ME環境的硬件架構。為了提升java在手機端的執行速度。

但是這樣做其實也是有缺點的,後面我們會講到,java字節碼中的指令非常非常多。所以如果用硬件來實現的話,就會非常非常複雜。

一般來說Java processor不會實現全部的字節碼中的功能,只會提供部分的實現。

查看Byte Code字節碼

小師妹:F師兄,那使用javac編譯過後的class文件跟字節碼有什麼關係呢?

class文件中大部分都是byte code,其他的部分是一些meta data元數據信息。這些組合在一起就是class文件了。

小師妹:F師兄,你說class文件是byte code,為什麼我在IDE中打開的時候,直接显示的是反編譯出來的源文件呢?

小師妹,這是IDE的一個便利功能。因為大多數情況下,沒有人想去看class文件的Byte code的,大家都是想去看看這個class文件的源文件是什麼樣的。

我們舉個最簡單的例子:

這個類中,我們定義了一個很簡單的testByteCode方法,裏面定義了兩個變量,然後返回他們兩個的和。

現在有兩種方法來查看這個類的Byte Code:

第一種方法是用javap命令:

javap -c ByteCodeUsage.class

生成的結果如上所示。

第二種方法就是在IDEA中,選中class文件,然後在view中選中show Bytecode:

我們看下輸出結果:

兩個的結果在显示上面可能有細微的差異,但是並不影響我們後面對其的解析。

java Byte Code是怎麼工作的

小師妹:F師兄,能講解一下這些byte code到底是怎麼工作的嗎?

首先我們要介紹一下JVM的實現是基於棧的結構的。為什麼要基於棧的結構呢?那是因為棧是最適合用來實現function互相調用的。

我們再回顧一下上面的testByteCode的字節碼。裏面有很多iconst,istore的東西,這些東西被稱作Opcode,也就是一些基於棧的操作指令。

上面講了java bytecode的操作指令其實有很多個。下面我們列出這些指令的部分介紹:

實在是太多了,這裏就不把所有的列出來了。

我們看到的指令名字其實是一個助記詞,真實的Opcode是一個佔用兩個字節的数字。

下面我們來詳細解釋一下testByteCode方法:

public int testByteCode();
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: ireturn

第一步,iconst_1將int 1加載到stack中。

第二步,istore_1將入棧的int 1出棧,並存儲到變量1中。

第三步,iconst_2將int 2入棧。

第四步,istore_2將入棧的int 2出棧,並存儲到變量2中。

第五步,iload_1將變量1中的值入棧。

第六步,iload_2將變量2中的值入棧。

第七步,iadd將棧中的兩個變量出棧,並相加。然後將結果入棧。

第八步,ireturn將棧中的結果出棧。

這幾步實際上完美的還原了我們在testByteCode方法中定義的功能。

當然我們只介紹了最賤的byte code命令,通過這些簡單的命令可以組合成為更加複雜的java命令。

總結

本文介紹了java byte code的作用和具體的指令,並分析了一個簡單的例子來做說明。希望大家能夠掌握。

本文的例子https://github.com/ddean2009/learn-java-base-9-to-20

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/jvm-byte-code/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等着您!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

Spring Boot2+Resilience4j實現容錯之Bulkhead

Resilience4j是一個輕量級、易於使用的容錯庫,其靈感來自Netflix Hystrix,但專為Java 8和函數式編程設計。輕量級,因為庫只使用Vavr,它沒有任何其他外部庫依賴項。相比之下,Netflix Hystrix對Archaius有一個編譯依賴關係,Archaius有更多的外部庫依賴關係,如Guava和Apache Commons。

Resilience4j提供高階函數(decorators)來增強任何功能接口、lambda表達式或方法引用,包括斷路器、速率限制器、重試或艙壁。可以在任何函數接口、lambda表達式或方法引用上使用多個裝飾器。優點是您可以選擇所需的裝飾器,而無需其他任何東西。

有了Resilience4j,你不必全力以赴,你可以選擇你需要的。

https://resilience4j.readme.io/docs/getting-started

概覽

Resilience4j提供了兩種艙壁模式(Bulkhead),可用於限制併發執行的次數:

  • SemaphoreBulkhead(信號量艙壁,默認),基於Java併發庫中的Semaphore實現。
  • FixedThreadPoolBulkhead(固定線程池艙壁),它使用一個有界隊列和一個固定線程池。

本文將演示在Spring Boot2中集成Resilience4j庫,以及在多併發情況下實現如上兩種艙壁模式。

引入依賴

在Spring Boot2項目中引入Resilience4j相關依賴

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot2</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-bulkhead</artifactId>
    <version>1.4.0</version>
</dependency>

由於Resilience4j的Bulkhead依賴於Spring AOP,所以我們需要引入Spring Boot AOP相關依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

我們可能還希望了解Resilience4j在程序中的運行時狀態,所以需要通過Spring Boot Actuator將其暴露出來

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

實現SemaphoreBulkhead(信號量艙壁)

resilience4j-spring-boot2實現了對resilience4j的自動配置,因此我們僅需在項目中的yml/properties文件中編寫配置即可。

SemaphoreBulkhead的配置項如下:

屬性配置 默認值 含義
maxConcurrentCalls 25 艙壁允許的最大并行執行量
maxWaitDuration 0 嘗試進入飽和艙壁時,應阻塞線程的最長時間。

添加配置

示例(使用yml):

resilience4j.bulkhead:
  configs:
    default:
      maxConcurrentCalls: 5
      maxWaitDuration: 20ms
  instances:
    backendA:
      baseConfig: default
    backendB:
      maxWaitDuration: 10ms
      maxConcurrentCalls: 20

如上,我們配置了SemaphoreBulkhead的默認配置為maxConcurrentCalls: 5,maxWaitDuration: 20ms。並在backendA實例上應用了默認配置,而在backendB實例上使用自定義的配置。這裏的實例可以理解為一個方法/lambda表達式等等的可執行單元。

編寫Bulkhead邏輯

定義一個受SemaphoreBulkhead管理的Service類:

@Service
public class BulkheadService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private BulkheadRegistry bulkheadRegistry;

    @Bulkhead(name = "backendA")
    public JsonNode getJsonObject() throws InterruptedException {
        io.github.resilience4j.bulkhead.Bulkhead.Metrics metrics = bulkheadRegistry.bulkhead("backendA").getMetrics();
        logger.info("now i enter the method!!!,{}<<<<<<{}", metrics.getAvailableConcurrentCalls(), metrics.getMaxAllowedConcurrentCalls());
        Thread.sleep(1000L);
        logger.info("now i exist the method!!!");
        return new ObjectMapper().createObjectNode().put("file", System.currentTimeMillis());
    }
}

如上,我們將@Bulkhead註解放到需要管理的方法上面。並且通過name屬性指定該方法對應的Bulkhead實例名字(這裏我們指定的實例名字為backendA,所以該方法將會利用默認的配置)。

定義接口類:

@RestController
public class BulkheadResource {
    @Autowired
    private BulkheadService bulkheadService;

    @GetMapping("/json-object")
    public ResponseEntity<JsonNode> getJsonObject() throws InterruptedException {
        return ResponseEntity.ok(bulkheadService.getJsonObject());
    }
}

編寫測試:

首先添加測試相關依賴

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.0.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.awaitility</groupId>
    <artifactId>awaitility</artifactId>
    <version>4.0.2</version>
    <scope>test</scope>
</dependency>

這裏我們使用rest-assured和awaitility編寫多併發情況下的API測試

public class SemaphoreBulkheadTests extends Resilience4jDemoApplicationTests {
    @LocalServerPort
    private int port;
    @BeforeEach
    public void init() {
        RestAssured.baseURI = "http://localhost";
        RestAssured.port = port;
    }

    @Test
    public void 多併發訪問情況下的SemaphoreBulkhead測試() {
        CopyOnWriteArrayList<Integer> statusList = new CopyOnWriteArrayList<>();
        IntStream.range(0, 8).forEach(i -> CompletableFuture.runAsync(() -> {
                statusList.add(given().get("/json-object").statusCode());
            }
        ));
        await().atMost(1, TimeUnit.MINUTES).until(() -> statusList.size() == 8);
        System.out.println(statusList);
        assertThat(statusList.stream().filter(i -> i == 200).count()).isEqualTo(5);
        assertThat(statusList.stream().filter(i -> i == 500).count()).isEqualTo(3);
    }
}

可以看到所有請求中只有前五個順利通過了,其餘三個都因為超時而導致接口報500異常。我們可能並不希望這種不友好的提示,因此Resilience4j提供了自定義的失敗回退方法。當請求併發量過大時,無法正常執行的請求將進入回退方法。

首先我們定義一個回退方法

private JsonNode fallback(BulkheadFullException exception) {
        return new ObjectMapper().createObjectNode().put("errorFile", System.currentTimeMillis());
    }

注意:回退方法應該和調用方法放置在同一類中,並且必須具有相同的方法簽名,並且僅帶有一個額外的目標異常參數。

然後在@Bulkhead註解中指定回退方法:@Bulkhead(name = "backendA", fallbackMethod = "fallback")

最後修改API測試代碼:

@Test
public void 多併發訪問情況下的SemaphoreBulkhead測試使用回退方法() {
    CopyOnWriteArrayList<Integer> statusList = new CopyOnWriteArrayList<>();
    IntStream.range(0, 8).forEach(i -> CompletableFuture.runAsync(() -> {
            statusList.add(given().get("/json-object").statusCode());
        }
    ));
    await().atMost(1, TimeUnit.MINUTES).until(() -> statusList.size() == 8);
    System.out.println(statusList);
    assertThat(statusList.stream().filter(i -> i == 200).count()).isEqualTo(8);
}

運行單元測試,成功!可以看到,我們定義的回退方法,在請求過量時起作用了。

實現FixedThreadPoolBulkhead(固定線程池艙壁)

FixedThreadPoolBulkhead的配置項如下:

配置名稱 默認值 含義
maxThreadPoolSize Runtime.getRuntime().availableProcessors() 配置最大線程池大小
coreThreadPoolSize Runtime.getRuntime().availableProcessors() - 1 配置核心線程池大小
queueCapacity 100 配置隊列的容量
keepAliveDuration 20ms 當線程數大於核心時,這是多餘空閑線程在終止前等待新任務的最長時間

添加配置

示例(使用yml):

resilience4j.thread-pool-bulkhead:
  configs:
    default:
      maxThreadPoolSize: 4
      coreThreadPoolSize: 2
      queueCapacity: 2
  instances:
    backendA:
      baseConfig: default
    backendB:
      maxThreadPoolSize: 1
      coreThreadPoolSize: 1
      queueCapacity: 1

如上,我們定義了一段簡單的FixedThreadPoolBulkhead配置,我們指定的默認配置為:maxThreadPoolSize: 4,coreThreadPoolSize: 2,queueCapacity: 2,並且指定了兩個實例,其中backendA使用了默認配置而backendB使用了自定義的配置。

編寫Bulkhead邏輯

定義一個受FixedThreadPoolBulkhead管理的方法:

@Bulkhead(name = "backendA", type = Bulkhead.Type.THREADPOOL)
public CompletableFuture<JsonNode> getJsonObjectByThreadPool() throws InterruptedException {
    io.github.resilience4j.bulkhead.ThreadPoolBulkhead.Metrics metrics = threadPoolBulkheadRegistry.bulkhead("backendA").getMetrics();
    logger.info("now i enter the method!!!,{}", metrics);
    Thread.sleep(1000L);
    logger.info("now i exist the method!!!");
    return CompletableFuture.supplyAsync(() -> new ObjectMapper().createObjectNode().put("file", System.currentTimeMillis()));
}

如上定義和SemaphoreBulkhead的方法大同小異,其中@Bulkhead显示指定了type的屬性為Bulkhead.Type.THREADPOOL,表明其方法受FixedThreadPoolBulkhead管理。由於@Bulkhead默認的BulkheadSemaphoreBulkhead,所以在未指定type的情況下為SemaphoreBulkhead。另外,FixedThreadPoolBulkhead只對CompletableFuture方法有效,所以我們必創建返回CompletableFuture類型的方法。

定義接口類方法

@GetMapping("/json-object-with-threadpool")
public ResponseEntity<JsonNode> getJsonObjectWithThreadPool() throws InterruptedException, ExecutionException {
    return ResponseEntity.ok(bulkheadService.getJsonObjectByThreadPool().get());
}

編寫測試代碼

@Test
public void 多併發訪問情況下的ThreadPoolBulkhead測試() {
    CopyOnWriteArrayList<Integer> statusList = new CopyOnWriteArrayList<>();
    IntStream.range(0, 8).forEach(i -> CompletableFuture.runAsync(() -> {
            statusList.add(given().get("/json-object-with-threadpool").statusCode());
        }
    ));
    await().atMost(1, TimeUnit.MINUTES).until(() -> statusList.size() == 8);
    System.out.println(statusList);
    assertThat(statusList.stream().filter(i -> i == 200).count()).isEqualTo(6);
    assertThat(statusList.stream().filter(i -> i == 500).count()).isEqualTo(2);
}

測試中我們并行請求了8次,其中6次請求成功,2次失敗。根據FixedThreadPoolBulkhead的默認配置,最多能容納maxThreadPoolSize+queueCapacity次請求(根據我們上面的配置為6次)。

同樣,我們可能並不希望這種不友好的提示,那麼我們可以指定回退方法,在請求無法正常執行時使用回退方法。

private CompletableFuture<JsonNode> fallbackByThreadPool(BulkheadFullException exception) {
    return CompletableFuture.supplyAsync(() -> new ObjectMapper().createObjectNode().put("errorFile", System.currentTimeMillis()));
}
@Bulkhead(name = "backendA", type = Bulkhead.Type.THREADPOOL, fallbackMethod = "fallbackByThreadPool")
public CompletableFuture<JsonNode> getJsonObjectByThreadPoolWithFallback() throws InterruptedException {
    io.github.resilience4j.bulkhead.ThreadPoolBulkhead.Metrics metrics = threadPoolBulkheadRegistry.bulkhead("backendA").getMetrics();
    logger.info("now i enter the method!!!,{}", metrics);
    Thread.sleep(1000L);
    logger.info("now i exist the method!!!");
    return CompletableFuture.supplyAsync(() -> new ObjectMapper().createObjectNode().put("file", System.currentTimeMillis()));
}

編寫測試代碼

@Test
public void 多併發訪問情況下的ThreadPoolBulkhead測試使用回退方法() {
    CopyOnWriteArrayList<Integer> statusList = new CopyOnWriteArrayList<>();
    IntStream.range(0, 8).forEach(i -> CompletableFuture.runAsync(() -> {
            statusList.add(given().get("/json-object-by-threadpool-with-fallback").statusCode());
        }
    ));
    await().atMost(1, TimeUnit.MINUTES).until(() -> statusList.size() == 8);
    System.out.println(statusList);
    assertThat(statusList.stream().filter(i -> i == 200).count()).isEqualTo(8);
}

由於指定了回退方法,所有請求的響應狀態都為正常了。

總結

本文首先簡單介紹了Resilience4j的功能及使用場景,然後具體介紹了Resilience4j中的Bulkhead。演示了如何在Spring Boot2項目中引入Resilience4j庫,使用代碼示例演示了如何在Spring Boot2項目中實現Resilience4j中的兩種Bulkhead(SemaphoreBulkhead和FixedThreadPoolBulkhead),並編寫API測試驗證我們的示例。

本文示例代碼地址:https://github.com/cg837718548/resilience4j-demo

歡迎訪問筆者博客:blog.dongxishaonian.tech

關注筆者公眾號,推送各類原創/優質技術文章 ⬇️

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※幫你省時又省力,新北清潔一流服務好口碑

※別再煩惱如何寫文案,掌握八大原則!