優質 NAS 快取選擇,全新 Seagate IronWolf 125 4TB SSD 開箱實測_包裝設計

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

Seagate的IronWolf系列,主要面向NAS專用的儲存設備,因為成本考量傳統都是使用 HDD 介面,不過今天我們要開箱的產品是Seagate IronWolf 125系列的4TB SSD,相比去年推出的IronWolf 110,這次全新的IronWolf 125其實可以分為 IronWolf 125 與 IronWolf Pro 125,其實主要就是將IronWolf 110系列的特色一分為二,IronWolf 125有著較低一點點的TBW(壽命)與MTBF(可靠性),而 IronWolf Pro 125 則是繼承了 IronWolf 110 的優點,並且在小檔讀取寫入(較快)以及供電上(只要5V即可驅動)有了改善,讓消費者有更多樣的選擇。

Seagate IronWolf 125 4TB SSD  開箱

IronWolf 125 4TB SSD 從外包裝上就有著霸氣的IronWolf圖案。

包裝上也採用了靜電袋包裝,相當用心。

撕開包裝後,可以看到正面有著大大的IronWolf LOGO。

而背面則是相關資訊,IronWolf 125與IronWolf 110最大的不同就在於供電的差異,IronWolf 125改回SSD的一般5V供電,使得在外接使用上會變得更為方便。

 

Seagate IronWolf 125 4TB SSD 效能測試

IronWolf 125 4TB SSD 屬於全新的IronWolf 125系列,從容量配置上來說,其實是更貼近硬碟的使用者,相比IronWolf 110與IronWolf Pro 125的最大容量3.84TB,IronWolf 125最大容量就是今天我們要測試的4TB版本,不過由於價格定位上的關係,一般大眾比較能接受的IronWolf 125 4TB SSD是有著5,600 TBW與1,800,000hr的MTBF,相比更高價格的IronWolf 125 Pro 3.84TB SSD則是有著7,000 TBW與2,000,000hr的MTBF。

首先可以看到,實際可使用的容量為3.63 TB。(換算格式不同)

IronWolf 125全系列的最大改動,為供電改為原本的5V即可驅動,因此可以直接透過外接硬碟盒驅動,在使用上就變得非常方便,尤其SATA SSD外接硬碟盒目前非常便宜的情況下,搭配一個超大容量的外接SSD就變得非常實用。

接著我們來實際測試傳輸速度,首先使用CrystalDiskMark進行讀寫測試,實際測試的讀寫速度分別為558.72 MB/s 與539.2 MB/s。

接著使用ATTO Disk Benchmark進行讀寫測試,最大的讀寫速度分別為559.7 MB/s 與540.4 MB/s。

因為是SSD,我們另外用了AS SSD Benchmark進行最後測試,其讀取寫入速度分別為523.98 MB/s 與508.28 MB/s,分數為1231。

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

而平常的傳輸檔案上,我們將檔案從桌面移動到SSD內,其實際的寫入速度初期會因為快取的關係跑到非常快,但穩定後速度為494 MB/s。

而反過來將檔案從SSD移到桌面上,則實際的讀取速度為501 MB/s。

 

原廠支援

除了擁有高水準的硬體表現外,Seagate IronWolf全系列還可以在相容的NAS上,啟動專屬的IronWolf Health Management (IHM) 保護機制,直接透過圖表監測NAS 每天的資料流量,掌握各種狀況,項目包含了:資料傳輸、效能、可讀性、可寫性、整體可靠性及其他相關的硬碟健康狀態參數(例如溫度、撞擊、振動、連線穩定度以及訊號完整性)並且針對資料保護提供了預防措施,在使用上更有保障。

除此之外 IronWolf 125 SSD 皆附有3年的Seagate Rescue資料救援服務,使用前須先至官網註冊,在救援計畫保固期限內,當硬碟發生損壞故障情形,資料無法讀取時,Seagate原廠提供免費的救援服務,盡其所能的為使用者救出硬碟內的資料,客戶滿意度高達 95%。

總結

IronWolf 125 SSD系列,除了同樣有著五年的保固外,SSD使用者更在意的TBW,更是有著超乎想像的水準,相比同樣用途的競品有著2~3倍的TBW,長期使用上不擔心,有著如此高TBW的優勢情況下,即使是拿來當作NAS的快取加速使用上,也不再擔心頻繁的寫入下造成的使用壽命縮短,放心的使用吧。

更大的容量 更安全的使用 全新Seagate IronWolf Pro NAS 18TB HDD 開箱

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

帥氣 寬敞 大氣!聽說大部分成熟男人都選了這幾輛座駕!_包裝設計

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

能給駕駛者提供更多的操控樂趣,但是也說不上運動型的底盤。如果忽略高轉速時比較轟耳的噪音,雅閣的舒適性是很不錯的。一汽馬自達-阿特茲指導價:17。58-23。98萬元阿特茲的顏值是一直都為車友們所稱道的,也承認,馬自達的魂動外觀的確是很有設計感,既有肌肉感的同時線條又十分流暢。



上世紀六七十年代,豐田乘着美國人的石油危機,憑藉其高可靠性,低油耗的汽車佔領了美國的汽車市場,奠定了豐田國際化的基礎。然而時至今日,日系車當中的佼佼者已經不止豐田一家。今天就和大家看看,在最能體現車企實力的B級車市場,“兩田一馬”,外加一個日產,其主力車型到底有什麼能耐。

指導價:18.48-32.98萬元

舊的凱美瑞會給人中庸,低調的感覺,難免會有“大叔車”的嫌疑。而新款的凱美瑞,採用了全新的家族式“Keen Look”前臉,六邊形的大嘴下格柵也讓車頭更加動感霸氣。側面的線條則比較簡潔流暢,變化不大,車尾造型依舊比較緊湊,橫穿左右的鍍鉻飾條是近來比較流行的元素,也讓車尾的整體感更強。

凱美瑞的內飾延續了以往車型的穩重大氣風格,採用人造皮革+縫線的工藝,內飾高級感更強。略遺憾的是中控大屏並沒有像其他主動和被動安全配置那樣都有全系標配。座椅厚實舒適的同時也保證一定的橫向支撐,舒適性不錯。

動力方面,搭載2.0L自然吸氣代號為6AR-FSE的發動機採用了D4-S雙模式噴射系統和VVT-iW新世代可變氣門正時技術,最大馬力167pS,6AT手自一體的變速箱集成了空擋控制系統、減擋補油控制系統和預緊差速器,動力平順性很好。實際駕駛感受起步動力是很靈敏的,雖然沒有很強的推背感,但也不會有“力不從心”的感覺,中後段的發力也有足夠的底氣。

凱美瑞的底盤是偏向舒適的設定,車內不會感受到十分直接的震動,同時轉向的助力比較沉穩,但轉向的靈敏度一般。總體來說如果你想要體驗操控樂趣的話,凱美瑞並不適合你,凱美瑞還是適合追求舒適、安靜的家用車用戶。

指導價:16.98-23.78萬元

本田也是很靈敏的廠商,它已經意識到現在購車群體的年輕化,所以就一改了以往雅閣那些濃濃的商務風,於是我們就看到呈現在我們眼前這個前臉造型立體,車身線條凌厲,有一雙科技感十足的LED大燈的新雅閣。當然,還有一些看不見的科技,如前置攝像頭和毫米波雷達,是Honda SENSING的基礎,該系統比較複雜,總的來說就是提供行駛安全輔助和保障。

和外觀不同,雅閣的內飾並沒有大改,對稱式的布局,線條十分流暢且有一點的高級感。不得不提是中控的雙屏設計了,兩個屏幕各司其職,用起來順手,看起來NB。但當你看了儀錶盤,你發現中央的行車電腦還是單色屏,也許是本田控製成本的手段,反正這個屏幕能显示必要信息足矣。

動力方面,2.0L/2.4L地球夢發動機,最大馬力155pS/186pS,搭配的CVT變速箱,都是本田的看見本領。和外觀的動感不同,雅閣的雖然油門響應靈敏,但動力的輸出卻不慌不忙,不會給你很激烈的加速感,

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

整個加速過程很平順。如果你打算購買雅閣,就不要想激烈駕駛了,好好享受那平順的CVT吧。

雅閣的採用多連桿獨立后懸挂,算是B級車標配了,底盤的質感很不錯,反應靈敏,處理震動的動作夠快,比凱美瑞的質感要硬。能給駕駛者提供更多的操控樂趣,但是也說不上運動型的底盤。如果忽略高轉速時比較轟耳的噪音,雅閣的舒適性是很不錯的。

指導價:17.58-23.98萬元

阿特茲的顏值是一直都為車友們所稱道的,也承認,馬自達的魂動外觀的確是很有設計感,既有肌肉感的同時線條又十分流暢。於是,2017款的阿特茲也延續了這種設計理念,大嘴格柵通過鍍鉻飾條與兩隻鷹眼大燈相連,感覺像一種很猛的動物,但是又說不出像什麼動物,大家發揮想象力吧。

內飾設計的改變也不少,全新樣式的方向盤和中控按鍵、懸浮式的中控屏,還有一些銀色飾條的加入,運動感更強,唯一不變的應該是變速箱擋把了。內飾採用軟質的皮革材料,也有縫線工藝,質感不錯。座椅的填充比較結實,不是很厚,支撐性和包裹性都比較好,也符合阿特茲偏向運動的風格。

2.0L/2.5L的Skyactiv發動機,最大馬力158/192pS,搭配換擋邏輯聰明,能夠幾乎讓你忘記它存在的6AT手自一體變速箱,組成這個好開有活力的動力系統。實際駕駛的感受是與歐系車類似的,油門初段比較沉重,後段較線性,動力輸出並不弱且提速很快,但又不會有渦輪增壓車那種激烈的推背感。

國產的阿特茲是針對了國內的情況進行了特殊的調校,前段偏軟,小坑小窪的過濾很到位,但仍保留一定的路感,後段的懸挂表現更加紮實,能為高速轉彎的阿特茲提供更好的支撐性。

指導價:17.58-29.98萬元

全新天籟的外觀加入了日產家族式的V-motion設計理念,V字型的中網鍍鉻飾條以及回力標的大燈造型,這些設計都是為了讓日產的外形更加年輕動感,減少了舊款日產圓潤成熟的氣息。至於新日產的外觀好不好看,那就是見仁見智的了。

至於中控的布局變化變化不大,仍然是簡潔商務風,方方正正的中控台造型給人穩重大氣的感覺,只是少了一點時尚感。觸控大屏的加入是新天籟的一個進化,多媒體功能得到了一些升級。至於座椅則一直是天籟的優點,寬大且柔軟,舒適性很好。

動力方面,新款天籟依舊搭載2.0L/2.5L+CVT變速箱的動力系統,最大馬力為150pS/186pS。實際的動力表現依舊是十分平順線性,沒有什麼爆發點。舊天籟的懸挂調校是很軟的,但新天籟在保證舒適性的基礎上給懸挂增加了一點韌性,配合彎道自動循跡系統,新天籟在轉彎時的側傾控制會比舊款天籟要好,但相對同級車型依然不算突出。

總結:

和德系車不同,日系車的動力少了一份直接;和美系車也不同,日系車少了一份力量感。乍一看彷彿沒有什麼優點,但是當你開在路上的時候你又不會發現動力不夠用,你也不會收到乘客投訴你後排的舒適性。這就是日系B級車,看似平庸,實際上這種中庸的均衡的表現,已經蘊含着不少技術的力量在裡頭。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

IDEA 插件推薦 —— 讓你寫出好代碼的神器!_包裝設計

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

概述

今天介紹的插件主要是圍繞編碼規範的。有追求的程序員,往往都有代碼潔癖,要盡量減少代碼的「壞味道」。

代碼靜態檢查是有很多種類,例如圈複雜度、重複率等。業界提供了很多靜態檢查的插件來識別這些不合規的代碼,幫助提高項目的質量。比較知名的一個產品是 SonarQube,它提供了一個「門禁」平台,集成了很多靜態檢查檢查。下次有機會介紹一下該平台的搭建。

本文主要介紹 IDEA 中對於 Java 語言靜態檢查的好插件:

  • Alibaba Java Coding Guidelines 阿里基於他們 Java 規範提供的插件
  • CheckStyle-IDEA 檢查代碼的格式是否符合規範
  • FindBugs-IDEA 檢查代碼是否有常見的一些 Bug

Alibaba Java Coding Guidelines

阿里巴巴 Java 編碼指南插件支持。

首先說說阿里的 p3c 項目,它的 Github 主頁地址是:https://github.com/alibaba/p3c 阿里之前開源過一份 Java 開發手冊。手冊從編程規約、異常日誌、單元測試、MySQL 數據庫、工程結構、設計規約等角度,介紹了阿里的 Java 開發規範,這個對於 Java 新手幫助挺大的,能夠學到不少東西。有一些坑可能老司機也會翻車。

開發人員 Coding 時,可能就忘記規範了,寫出來的代碼還是會有『壞味道』。這時候Alibaba Java Coding Guidelines 插件就派上用場了。它會根據上面的 Java 開發規範對你的代碼進行檢查,不符合規範的代碼會有提示,並給出修改建議。阿里作為國內 Java 大廠,基於成千上萬的工程師總結出來的踩坑經驗,我相信給出的規範建議還是比較可靠的。

上個栗子:

  String str = "hello";
  for (int i = 0; i < 100; i++) {
      str = str + "world!";
  }

先不要往下看,試着分析一下這段代碼哪裡可以優化?

其實,插鍵掃描的結果不僅有這個問題,還有『魔法数字』的問題。插件的用法,見下面的截圖。

除此以外,建議在 IDEA 進行代碼提交時,勾選上它提供的檢查項按鈕,這樣如果有不合規的代碼進行提交,就會提醒你修改:

CheckStyle-IDEA

項目主頁:https://github.com/jshiell/checkstyle-idea

安裝好之後,進入設置,勾選上你要選用的默認檢查規範:

大廠往往都有自己的語言規範,可以導入選用:

右鍵菜單,選擇 Check Current File 即可檢查當前文件是否符合編碼規範:

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

檢查結果:

如果不符合規範的寫法有點多,整改起來就會很痛苦了,這時候該怎麼辦?有一個功能叫格式化代碼(Reformat Code),快捷鍵是:

  • Mac:Command+Option+L
  • Win:Ctrl+Shift+L

如果想按照你指定的規則進行格式化,可以按照如下方式進行自定義:

FindBugs-IDEA

FindBugs 是一款老牌 Java 靜態檢查插件了。它的功能和阿里 p3c 那個插件很像,只不過它歷史悠久、國際化一點。它同樣的可以掃描代碼,發現一些可能會引入 Bug 的代碼段,給出參考建議。

啟動 FindBugs 的方式,右鍵菜單中,Findbugs 提供了好幾個選項:

  • Analyze Current File:檢查當前文件
  • Analyze Class uner Cursor:檢查光標處的類
  • Analyze Package Files:檢查包文件
  • Analyze Modul Files:檢查 Module 文件
  • Analyze Project Files:檢查項目文件
  • Analyze Scope Files:檢查指定範圍內的文件
  • Analyze All Modified Files:檢查所有修改過的文件
  • Analyze changelist files:檢查變更列表中的文件

檢查結果:

檢查結果分為如下類別:

  • Bad practice:不好的做法,代碼違反了公認的最佳實踐標準;
  • Malicious code vulnerbility:惡意的代碼漏洞;
  • Correctness:可能不正確,比如錯誤的強制類型轉換;
  • Performance:潛在的性能問題;
  • Security:安全性;
  • Dodgy code:糟糕的代碼,FindBugs團隊認為該類型下的問題代碼導 Bug 的可能性很高;
  • Experimental:實驗;
  • Multithreaded correctness:關注於同步和多線程問題;
  • Internationalization:國際化

掃描出來的結果怎麼看懂,官網有專門的一頁介紹 FindBugs Bug Description http://findbugs.sourceforge.net/bugDescriptions.html

除了上面右鍵菜單啟動檢查之外,還可以在相應文件夾右鍵菜單中啟動:

針對檢查的嚴格程度,其實是可以調節的,建議修改為 low,這樣會盡可能的掃描出有潛在 Bug 的代碼片段:

總結

以上是目前工作中經常用到的靜態代碼檢查插鍵,雖然不是用了它們就真的能寫出好代碼,但是這些工具的確能夠讓你能夠在前人的肩膀上少踩一些坑。比如阿里的那個檢查插鍵,你可以按照它的提示,對照着他們的 Java 開發手冊查看,分析一下,為何他們會有如此的規約。高樓大廈不都是一磚一瓦砌成的嘛?小知識點的基礎打紮實了,才能走得更高!

由於國內網絡問題,我提前將最新版的《阿里巴巴 Java 開發手冊(泰山版).pdf》上傳至雲盤了,有需要的小夥伴公眾號後台回復 泰山版 即可獲得下載鏈接。

一言

上周的寫的一篇文章分享到微信群里,群友有人指出來標題有錯別字,真是有點尷尬!其實,我寫文章也比較隨意,也是最近才開始堅持每周至少輸出一篇分享的。但想想既然寫了,就要盡量保證質量。引以為戒,以後要認真點才行!

目前分享的內容主要是開發環境、效率工具等。自己一直對這方面的文章比較感興趣,因此之前就有相關積累。今後希望能通過閱讀帶來一些讀書總結的分享,也希望關注的同學後台多留言,給出你的建議,感謝~

生命不息,折騰不止!關注 「Coder魔法院」,祝你 Niubilitiy !

參考

  • 代碼缺陷掃描神器——FindBugs:https://juejin.im/entry/591ad01ba22b9d005833903e

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

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

吐血輸出:2萬字長文帶你細細盤點五種負載均衡策略。_包裝設計

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

2020 年 5 月 15 日,Dubbo 發布 2.7.7 release 版本。其中有這麼一個 Features

新增一個負載均衡策略。

熟悉我的老讀者肯定是知道的,Dubbo 的負載均衡我都寫過專門的文章,對每個負載均衡算法進行了源碼的解讀,還分享了自己調試過程中的一些騷操作。

新的負載均衡出來了,那必須的得解讀一波。

先看一下提交記錄:

https://github.com/chickenlj/incubator-dubbo/commit/6d2ba7ec7b5a1cb7971143d4262d0a1bfc826d45

負載均衡是基於 SPI 實現的,我們看到對應的文件中多了一個名為 shortestresponse 的 key。

這個,就是新增的負載均衡策略了。看名字,你也知道了這個策略的名稱就叫:最短響應。

所以截止 2.7.7 版本,官方提供了五種負載均衡算法了,他們分別是:

  1. ConsistentHashLoadBalance 一致性哈希負載均衡
  2. LeastActiveLoadBalance 最小活躍數負載均衡
  3. RandomLoadBalance 加權隨機負載均衡
  4. RoundRobinLoadBalance 加權輪詢負載均衡
  5. ShortestResponseLoadBalance 最短響應時間負載均衡

前面四種我已經在之前的文章中進行了詳細的分析。有的讀者反饋說想看合輯,所以我會在這篇文章中把之前文章也整合進來。

所以,需要特彆強調一下的是,這篇文章集合了之前寫的三篇負載均衡的文章。看完最短響應時間負載均衡這一部分后,如果你看過我之前的那三篇文章,你可以溫故而知新,也可以直接拉到文末看看我推薦的一個活動,然後點個贊再走。如果你沒有看過那三篇,這篇文章如果你細看,肯定有很多收穫,以後談起負載均衡的時候若數家珍,但是肯定需要看非常非常長的時間,做好心理準備。

我已經預感到了,這篇文章妥妥的會超過 2 萬字。屬於硬核勸退文章,想想就害怕。

最短響應時間負載均衡

首先,我們看一下這個類上的註解,先有個整體的認知。

org.apache.dubbo.rpc.cluster.loadbalance.ShortestResponseLoadBalance

我來翻譯一下是什麼意思:

  1. 從多個服務提供者中選擇出調用成功的且響應時間最短的服務提供者,由於滿足這樣條件的服務提供者有可能有多個。所以當選擇出多個服務提供者后要根據他們的權重做分析。
  2. 但是如果只選擇出來了一個,直接用選出來這個。
  3. 如果真的有多個,看它們的權重是否一樣,如果不一樣,則走加權隨機算法的邏輯。
  4. 如果它們的權重是一樣的,則隨機調用一個。

再配個圖,就好理解了,可以先不管圖片中的標號:

有了上面的整體概念的鋪墊了,接下來分析源碼的時候就簡單了。

源碼一共就 66 行,我把它分為 5 個片段去一一分析。

這裏一到五的標號,對應上面流程圖中的標號。我們一個個的說。

標號為①的部分

這一部分是定義並初始化一些參數,為接下來的代碼服務的,翻譯一下每個參數對應的註釋:

length 參數:服務提供者的數量。

shortestResponse 參數:所有服務提供者的估計最短響應時間。(這個地方我覺得註釋描述的不太準確,看後面的代碼可以知道這隻是一個零時變量,在循環中存儲當前最短響應時間是多少。)

shortCount 參數:具有相同最短響應時間的服務提供者個數,初始化為 0。

shortestIndexes 參數:數組裡面放的是具有相同最短響應時間的服務提供者的下標。

weights 參數:每一個服務提供者的權重。

totalWeight 參數:多個具有相同最短響應時間的服務提供者對應的預熱(預熱這個點還是挺重要的,在下面講最小活躍數負載均衡的時候有詳細說明)權重之和。

firstWeight 參數:第一個具有最短響應時間的服務提供者的權重。

sameWeight 參數:多個滿足條件的提供者的權重是否一致。

標號為②的部分

這一部分代碼的關鍵,就在上面框起來的部分。而框起來的部分,最關鍵的地方,就在於第一行。

獲取調用成功的平均時間。

成功調用的平均時間怎麼算的?

調用成功的請求數總數對應的總耗時 / 調用成功的請求數總數 = 成功調用的平均時間。

所以,在下面這個方法中,首先獲取到了調用成功的請求數總數:

這個 succeeded 參數是怎麼來的呢?

答案就是:總的請求數減去請求失敗的數量,就是請求成功的總數!

那麼為什麼不能直接獲取請求成功的總數呢?

別問,問就是沒有這個選項啊。你看,在 RpcStatus 裏面沒有這個參數呀。

請求成功的總數我們有了,接下來成功總耗時怎麼拿到的呢?

答案就是:總的請求時間減去請求失敗的總時間,就是請求成功的總耗時!

那麼為什麼不能直接獲取請求成功的總耗時呢?

別問,問就是……

我們看一下 RpcStatus 中的這幾個參數是在哪裡維護的:

org.apache.dubbo.rpc.RpcStatus#endCount(org.apache.dubbo.rpc.RpcStatus, long, boolean)

其中的第二個入參是本次請求調用時長,第三個入參是本次調用是否成功。

具體的方法不必細說了吧,已經顯而易見了。

再回去看框起來的那三行代碼:

  1. 第一行獲取到了該服務提供者成功請求的平均耗時。
  2. 第二行獲取的是該服務提供者的活躍數,也就是堆積的請求數。
  3. 第三行獲取的就是如果當前這個請求發給這個服務提供者預計需要等待的時間。乘以 active 的原因是因為它需要排在堆積的請求的後面嘛。

這裏,我們就獲取到了如果選擇當前循環中的服務提供者的預計等待時間是多長。

後面的代碼怎麼寫?

當然是出來一個更短的就把這個踢出去呀,或者出來一個一樣長時間的就記錄一下,接着去 pk 權重了。

所以,接下來 shortestIndexes 參數和 weights 參數就排上用場了:

另外,多說一句的,它裏面有這樣的一行註釋:

和 LeastActiveLoadBalance 負載均衡策略一致,我給你截圖對比一下:

可以看到,確實是非常的相似,只是一個是判斷誰的響應時間短,一個是判斷誰的活躍數低。

標號為③的地方

標號為③的地方是這樣的:

裏面參數的含義我們都知道了,所以,標號為③的地方的含義就很好解釋了:經過選擇后只有一個服務提供者滿足條件。所以,直接使用這個服務提供者。

標號為④的地方

這個地方我就不展開講了(後面的加權隨機負載均衡那一小節有詳細說明),熟悉的朋友一眼就看出來這是加權隨機負載均衡的寫法了。

不信?我給你對比一下:

你看,是不是一模一樣的。

標號為⑤的地方

一行代碼,沒啥說的。就是從多個滿足條件的且權重一樣的服務提供者中隨機選擇一個。

如果一定要多說一句的話,我截個圖吧:

可以看到,這行代碼在最短響應時間、加權隨機、最小活躍數負載均衡策略中都出現了,且都在最後一行。

好了,到這裏最短響應時間負載均衡策略就講完了,你再回過頭去看那張流程圖,會發現其實流程非常的清晰,完全可以根據代碼結構畫出流程圖。一個是說明這個算法是真的不複雜,另一個是說明好的代碼會說話。

優雅

你知道 Dubbo 加入這個新的負載均衡算法提交了幾個文件嗎?

四個文件,其中還包含兩個測試文件:

這裏就是策略模式和 SPI 的好處。對原有的負載均衡策略沒有任何侵略性。只需要按照規則擴展配置文件,實現對應接口即可。

這是什麼?

這就是值得學習優雅!

那我們優雅的進入下一議題。

最小活躍數負載均衡

這一小節所示源碼,沒有特別標註的地方均為 2.6.0 版本。

為什麼沒有用截止目前(我當時寫這段文章的時候是2019年12月01日)的最新的版本號 2.7.4.1 呢?因為 2.6.0 這個版本裏面有兩個 bug 。從 bug 講起來,印象更加深刻。

最後會對 2.6.0/2.6.5/2.7.4.1 版本進行對比,通過對比學習,加深印象。

我這裏補充一句啊,僅僅半年的時間,版本號就從 2.7.4.1 到了 2.7.7。其中還包含一個 2.7.5 這樣的大版本。

所以還有人說 Dubbo 不夠活躍?(幾年前的文章現在還有人在發。)

對吧,我們不吵架,我們擺事實,聊數據嘛。

Demo 準備

我看源碼的習慣是先搞個 Demo 把調試環境搭起來。然後帶着疑問去抽絲剝繭的 Debug,不放過在這個過程中在腦海裏面一閃而過的任何疑問。

這一小節分享的是Dubbo負載均衡策略之一最小活躍數(LeastActiveLoadBalance)。所以我先搭建一個 Dubbo 的項目,並啟動三個 provider 供 consumer 調用。

三個 provider 的 loadbalance 均配置的是 leastactive。權重分別是默認權重、200、300。

**默認權重是多少?**後面看源碼的時候,源碼會告訴你。

三個不同的服務提供者會給調用方返回自己是什麼權重的服務。

啟動三個實例。(注:上面的 provider.xml 和 DemoServiceImpl 其實只有一個,每次啟動的時候手動修改端口、權重即可。)

到 zookeeper 上檢查一下,服務提供者是否正常:

可以看到三個服務提供者分別在 20880、20881、20882 端口。(每個紅框的最後5個数字就是端口號)。

最後,我們再看服務消費者。消費者很簡單,配置consumer.xml

直接調用接口並打印返回值即可。

斷點打在哪?

相信很多朋友也很想看源碼,但是不知道從何處下手。處於一種在源碼裏面”亂逛”的狀態,一圈逛下來,收穫並不大。

這一部分我想分享一下我是怎麼去看源碼。首先我會帶着問題去源碼裏面尋找答案,即有針對性的看源碼。

如果是這種框架類的,正如上面寫的,我會先翻一翻官網(Dubbo 的官方文檔其實寫的挺好了),然後搭建一個簡單的 Demo 項目,然後 Debug 跟進去看。Debug 的時候當然需要是設置斷點的,那麼這個斷點如何設置呢?

第一個斷點,當然毋庸置疑,是打在調用方法的地方,比如本文中,第一個斷點是在這個地方:

接下里怎麼辦?

你當然可以從第一個斷點處,一步一步的跟進去。但是在這個過程中,你發現了嗎?大多數情況你都是被源碼牽着鼻子走的。本來你就只帶着一個問題去看源碼的,有可能你Debug了十分鐘,還沒找到關鍵的代碼。也有可能你Debug了十分鐘,問題從一個變成了無數個。

所以不要慌,我們點支煙,慢慢分析。

首先怎麼避免被源碼牽着四處亂逛呢?

我們得找到一個突破口,還記得我在《很開心,在使用mybatis的過程中我踩到一個坑》這篇文章中提到的逆向排查的方法嗎?這次的文章,我再次展示一下該方法。

看源碼之前,我們的目標要十分明確,就是想要找到 Dubbo 最小活躍數算法的具體實現類以及實現類的具體邏輯是什麼。

根據我們的 provider.xml 裏面的:

很明顯,我們知道 loadbalance 是關鍵字。所以我們拿着 loadbalance 全局搜索,可以看到 Dubbo 包下面的 LoadBalance。

這是一個 SPI 接口 com.alibaba.dubbo.rpc.cluster.LoadBalance:

其實現類為:

com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance

AbstractLoadBalance 是一個抽象類,該類裏面有一個抽象方法doSelect。這個抽象方法其中的一個實現類就是我們要分析的最少活躍次數負載均衡的源碼。

同時,到這裏我們知道了 LoadBalance 是一個 SPI 接口,說明我們可以擴展自己的負載均衡策略。抽象方法 doSelect 有四個實現類。這個四個實現類,就是 Dubbo 官方提供的負載均衡策略(截止 2.7.7 版本之前),他們分別是:

  1. ConsistentHashLoadBalance 一致性哈希算法
  2. LeastActiveLoadBalance 最小活躍數算法
  3. RandomLoadBalance 加權隨機算法
  4. RoundRobinLoadBalance 加權輪詢算法

我們已經找到了 LeastActiveLoadBalance 這個類了,那麼我們的第二個斷點打在哪裡已經很明確了。

目前看來,兩個斷點就可以支撐我們的分析了。

有的朋友可能想問,那我想知道 Dubbo 是怎麼識別出我們想要的是最少活躍次數算法,而不是其他的算法呢?其他的算法是怎麼實現的呢?從第一個斷點到第二個斷點直接有着怎樣的調用鏈呢?

在沒有徹底搞清楚最少活躍數算法之前,這些統統先記錄在案但不予理睬。一定要明確目標,帶着一個問題進來,就先把帶來的問題解決了。之後再去解決在這個過程中碰到的其他問題。在這樣環環相扣解決問題的過程中,你就慢慢的把握了源碼的精髓。這是我個人的一點看源碼的心得。供諸君參考。

模擬環境

既然叫做最小活躍數策略。那我們得讓現有的三個消費者都有一些調用次數。所以我們得改造一下服務提供者和消費者。

服務提供者端的改造如下:

!

PS:這裏以權重為 300 的服務端為例。另外的兩個服務端改造點相同。

客戶端的改造點如下:

一共發送 21 個請求:其中前 20 個先發到服務端讓其 hold 住(因為服務端有 sleep),最後一個請求就是我們需要 Debug 跟蹤的請求。

運行一下,讓程序停在斷點的地方,然後看看控制台的輸出:

權重為300的服務端共計收到9個請求

權重為200的服務端共計收到6個請求

默認權重的服務端共計收到5個請求

我們還有一個請求在 Debug。直接進入到我們的第二個斷點的位置,並 Debug 到下圖所示的一行代碼(可以點看查看大圖):

正如上面這圖所說的:weight=100 回答了一個問題,active=0 提出的一個問題。

weight=100 回答了什麼問題呢?

默認權重是多少?是 100。

我們服務端的活躍數分別應該是下面這樣的

  • 權重為300的服務端,active=9
  • 權重為200的服務端,active=6
  • 默認權重(100)的服務端,active=5

但是這裏為什麼截圖中的active會等於 0 呢?這是一個問題。

繼續往下 Debug 你會發現,每一個服務端的 active 都是 0。所以相比之下沒有一個 invoker 有最小 active 。於是程序走到了根據權重選擇 invoker 的邏輯中。

active為什麼是0?

active 為 0 說明在 Dubbo 調用的過程中 active 並沒有發生變化。那 active 為什麼是 0,其實就是在問 active 什麼時候發生變化

要回答這個問題我們得知道 active 是在哪裡定義的,因為在其定義的地方,必有其修改的方法。

下面這圖說明了active是定義在RpcStatus類裏面的一個類型為AtomicInteger 的成員變量。

在 RpcStatus 類中,有三處()調用 active 值的方法,一個增加、一個減少、一個獲取:

很明顯,我們需要看的是第一個,在哪裡增加。

所以我們找到了 beginCount(URL,String) 方法,該方法只有兩個 Filter 調用。ActiveLimitFilter,見名知意,這就是我們要找的東西。

com.alibaba.dubbo.rpc.filter.ActiveLimitFilter具體如下:

看到這裏,我們就知道怎麼去回答這個問題了:為什麼active是0呢?因為在客戶端沒有配置ActiveLimitFilter。所以,ActiveLimitFilter沒有生效,導致active沒有發生變化。

怎麼讓其生效呢?已經呼之欲出了。

好了,再來試驗一次:

加上Filter之後,我們通過Debug可以看到,對應權重的活躍數就和我們預期的是一致的了。

1.權重為300的活躍數為6

2.權重為200的活躍數為11

3.默認權重(100)的活躍數為3

根據活躍數我們可以分析出來,最後我們Debug住的這個請求,一定會選擇默認權重的invoker去執行,因為他是當前活躍數最小的invoker。如下所示:

雖然到這裏我們還沒開始進行源碼的分析,只是把流程梳理清楚了。但是把Demo完整的搭建了起來,而且知道了最少活躍數負載均衡算法必須配合ActiveLimitFilter使用,位於RpcStatus類的active字段才會起作用,否則,它就是一個基於權重的算法。

比起其他地方直接告訴你,要配置ActiveLimitFilter才行哦,我們自己實驗得出的結論,能讓我們的印象更加深刻。

我們再仔細看一下加上ActiveLimitFilter之後的各個服務的活躍數情況:

  • 權重為300的活躍數為6
  • 權重為200的活躍數為11
  • 默認權重(100)的活躍數為3

你不覺得奇怪嗎,為什麼權重為200的活躍數是最高的

其在業務上的含義是:我們有三台性能各異的服務器,A服務器性能最好,所以權重為300,B服務器性能中等,所以權重為200,C服務器性能最差,所以權重為100。

當我們選擇最小活躍次數的負載均衡算法時,我們期望的是性能最好的A服務器承擔更多的請求,而真實的情況是性能中等的B服務器承擔的請求更多。這與我們的設定相悖。

如果你說20個請求數據量太少,可能是巧合,不足以說明問題。說明你還沒被我帶偏,我們不能基於巧合編程。

所以為了驗證這個地方確實有問題,我把請求擴大到一萬個。

同時,記得擴大 provider 端的 Dubbo 線程池:

由於每個服務端運行的代碼都是一樣的,所以我們期望的結果應該是權重最高的承擔更多的請求。但是最終的結果如圖所示:

各個服務器均攤了請求。這就是我文章最開始的時候說的Dubbo 2.6.0 版本中最小活躍數負載均衡算法的Bug之一。

接下來,我們帶着這個問題,去分析源碼。

剖析源碼

com.alibaba.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance的源碼如下,我逐行進行了解讀。可以點開查看大圖,細細品讀,非常爽:

下圖中紅框框起來的部分就是一個基於權重選擇invoker的邏輯:

我給大家畫圖分析一下:

請仔細分析圖中給出的舉例說明。同時,上面這圖也是按照比例畫的,可以直觀的看到,對於某一個請求,區間(權重)越大的服務器,就越可能會承擔這個請求。所以,當請求足夠多的時候,各個服務器承擔的請求數,應該就是區間,即權重的比值。

其中第 81 行有調用 getWeight 方法,位於抽象類 AbstractLoadBalance 中,也需要進行重點解讀的代碼。

com.alibaba.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance 的源碼如下,我也進行了大量的備註:

在 AbstractLoadBalance 類中提到了一個預熱的概念。官網中是這樣的介紹該功能的:

權重的計算過程主要用於保證當服務運行時長小於服務預熱時間時,對服務進行降權,避免讓服務在啟動之初就處於高負載狀態。服務預熱是一個優化手段,與此類似的還有 JVM 預熱。主要目的是讓服務啟動后“低功率”運行一段時間,使其效率慢慢提升至最佳狀態。

從上圖代碼裏面的公式(演變后):*計算后的權重=(uptime/warmup)weight 可以看出:隨着服務啟動時間的增加(uptime),計算后的權重會越來越接近weight。從實際場景的角度來看,隨着服務啟動時間的增加,服務承擔的流量會慢慢上升,沒有一個陡升的過程。所以這是一個優化手段。同時 Dubbo 接口還支持延遲暴露。

在仔細的看完上面的源碼解析圖后,配合官網的總結加上我的靈魂畫作,相信你可以對最小活躍數負載均衡算法有一個比較深入的理解:

  1. 遍歷 invokers 列表,尋找活躍數最小的 Invoker
  2. 如果有多個 Invoker 具有相同的最小活躍數,此時記錄下這些 Invoker 在 invokers 集合中的下標,並累加它們的權重,比較它們的權重值是否相等
  3. 如果只有一個 Invoker 具有最小的活躍數,此時直接返回該 Invoker 即可
  4. 如果有多個 Invoker 具有最小活躍數,且它們的權重不相等,此時處理方式和 RandomLoadBalance 一致
  5. 如果有多個 Invoker 具有最小活躍數,但它們的權重相等,此時隨機返回一個即可

所以我覺得最小活躍數負載均衡的全稱應該叫做:有最小活躍數用最小活躍數,沒有最小活躍數根據權重選擇,權重一樣則隨機返回的負載均衡算法。

Bug在哪裡?

Dubbo2.6.0最小活躍數算法Bug一

問題出在標號為 ① 和 ② 這兩行代碼中:

標號為 ① 的代碼在url中取出的是沒有經過 getWeight 方法降權處理的權重值,這個值會被累加到權重總和(totalWeight)中。

標號為 ② 的代碼取的是經過 getWeight 方法處理后的權重值。

取值的差異會導致一個問題,標號為 ② 的代碼的左邊,offsetWeight 是一個在 [0,totalWeight) 範圍內的隨機數,右邊是經過 getWeight 方法降權后的權重。所以在經過 leastCount 次的循環減法后,offsetWeight 在服務啟動時間還沒到熱啟動設置(默認10分鐘)的這段時間內,極大可能仍然大於 0。導致不會進入到標號為 ③ 的代碼中。直接到標號為 ④ 的代碼處,變成了隨機調用策略。這與設計不符,所以是個 bug。

前面章節說的情況就是這個Bug導致的。

這個Bug對應的issues地址和pull request分為:

https://github.com/apache/dubbo/issues/904

https://github.com/apache/dubbo/pull/2172

那怎麼修復的呢?我們直接對比 Dubbo 2.7.4.1 的代碼:

可以看到獲取weight的方法變了:從url中直接獲取變成了通過getWeight方法獲取。獲取到的變量名稱也變了:從weight變成了afterWarmup,更加的見名知意。

還有一處變化是獲取隨機值的方法的變化,從Randmo變成了ThreadLoaclRandom,性能得到了提升。這處變化就不展開講了,有興趣的朋友可以去了解一下。

Dubbo2.6.0最小活躍數算法Bug二

這個Bug我沒有遇到,但是我在官方文檔上看了其描述(官方文檔中的版本是2.6.4),引用如下:

官網上說這個問題在2.6.5版本進行修復。我對比了2.6.0/2.6.5/2.7.4.1三個版本,發現每個版本都略有不同。如下所示:

圖中標記為①的三處代碼:

2.6.0版本的是有Bug的代碼,原因在上面說過了。

2.6.5版本的修復方式是獲取隨機數的時候加一,所以取值範圍就從**[0,totalWeight)變成了[0,totalWeight]**,這樣就可以避免這個問題。

2.7.4.1版本的取值範圍還是[0,totalWeight),但是它的修復方法體現在了標記為②的代碼處。2.6.0/2.6.5版本標記為②的地方都是if(offsetWeight<=0),而2.7.4.1版本變成了if(offsetWeight<0)

你品一品,是不是效果是一樣的,但是更加優雅了。

朋友們,魔鬼,都在細節里啊!

好了,進入下一議題。

一致性哈希負載均衡

這一部分是對於Dubbo負載均衡策略之一的一致性哈希負載均衡的詳細分析。對源碼逐行解讀、根據實際運行結果,配以豐富的圖片,可能是東半球講一致性哈希算法在Dubbo中的實現最詳細的文章了。

本小節所示源碼,沒有特別標註的地方,均為2.7.4.1版本。

在撰寫本文的過程中,發現了Dubbo2.7.0版本之後的一個bug。會導致性能問題,如果你們的負載均衡配置的是一致性哈希或者考慮使用一致性哈希的話,可以了解一下。

哈希算法

在介紹一致性哈希算法之前,我們看看哈希算法,以及它解決了什麼問題,帶來了什麼問題。

如上圖所示,假設0,1,2號服務器都存儲的有用戶信息,那麼當我們需要獲取某用戶信息時,因為我們不知道該用戶信息存放在哪一台服務器中,所以需要分別查詢0,1,2號服務器。這樣獲取數據的效率是極低的。

對於這樣的場景,我們可以引入哈希算法。

還是上面的場景,但前提是每一台服務器存放用戶信息時是根據某一種哈希算法存放的。所以取用戶信息的時候,也按照同樣的哈希算法取即可。

假設我們要查詢用戶號為100的用戶信息,經過某個哈希算法,比如這裏的userId mod n,即100 mod 3結果為1。所以用戶號100的這個請求最終會被1號服務器接收並處理。

這樣就解決了無效查詢的問題。

但是這樣的方案會帶來什麼問題呢?

擴容或者縮容時,會導致大量的數據遷移。最少也會影響百分之50的數據。

為了說明問題,我們加入一台服務器3。服務器的數量n就從3變成了4。還是查詢用戶號為100的用戶信息時,100 mod 4結果為0。這時,請求就被0號服務器接收了。

當服務器數量為3時,用戶號為100的請求會被1號服務器處理。

當服務器數量為4時,用戶號為100的請求會被0號服務器處理。

所以,當服務器數量增加或者減少時,一定會涉及到大量數據遷移的問題。可謂是牽一發而動全身。

對於上訴哈希算法其優點是簡單易用,大多數分庫分表規則就採取的這種方式。一般是提前根據數據量,預先估算好分區數。

缺點是由於擴容或收縮節點導致節點數量變化時,節點的映射關係需要重新計算,會導致數據進行遷移。所以擴容時通常採用翻倍擴容,避免數據映射全部被打亂,導致全量遷移的情況,這樣只會發生50%的數據遷移。

假設這是一個緩存服務,數據的遷移會導致在遷移的時間段內,有緩存是失效的。

緩存失效,可怕啊。還記得我之前的文章嗎,《當周杰倫把QQ音樂干翻的時候,作為程序猿我看到了什麼?》就是講緩存擊穿、緩存穿透、緩存雪崩的場景和對應的解決方案。

一致性哈希算法

為了解決哈希算法帶來的數據遷移問題,一致性哈希算法應運而生。

對於一致性哈希算法,官方說法如下:

一致性哈希算法在1997年由麻省理工學院提出,是一種特殊的哈希算法,在移除或者添加一個服務器時,能夠盡可能小地改變已存在的服務請求與處理請求服務器之間的映射關係。一致性哈希解決了簡單哈希算法在分佈式哈希表( Distributed Hash Table,DHT) 中存在的動態伸縮等問題。

什麼意思呢?我用大白話加畫圖的方式給你簡單的介紹一下。

一致性哈希,你可以想象成一個哈希環,它由0到2^32-1個點組成。A,B,C分別是三台服務器,每一台的IP加端口經過哈希計算后的值,在哈希環上對應如下:

當請求到來時,對請求中的某些參數進行哈希計算后,也會得出一個哈希值,此值在哈希環上也會有對應的位置,這個請求會沿着順時針的方向,尋找最近的服務器來處理它,如下圖所示:

一致性哈希就是這麼個東西。那它是怎麼解決服務器的擴容或收縮導致大量的數據遷移的呢?

看一下當我們使用一致性哈希算法時,加入服務器會發什麼事情。

當我們加入一個D服務器后,假設其IP加端口,經過哈希計算后落在了哈希環上圖中所示的位置。

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

這時影響的範圍只有圖中標註了五角星的區間。這個區間的請求從原來的由C服務器處理變成了由D服務器請求。而D到C,C到A,A到B這個區間的請求沒有影響,加入D節點后,A、B服務器是無感知的。

所以,在一致性哈希算法中,如果增加一台服務器,則受影響的區間僅僅是新服務器(D)在哈希環空間中,逆時針方向遇到的第一台服務器(B)之間的區間,其它區間(D到C,C到A,A到B)不會受到影響。

在加入了D服務器的情況下,我們再假設一段時間后,C服務器宕機了:

當C服務器宕機后,影響的範圍也是圖中標註了五角星的區間。C節點宕機后,B、D服務器是無感知的。

所以,在一致性哈希算法中,如果宕機一台服務器,則受影響的區間僅僅是宕機服務器(C)在哈希環空間中,逆時針方向遇到的第一台服務器(D)之間的區間,其它區間(C到A,A到B,B到D)不會受到影響。

綜上所述,在一致性哈希算法中,不管是增加節點,還是宕機節點,受影響的區間僅僅是增加或者宕機服務器在哈希環空間中,逆時針方向遇到的第一台服務器之間的區間,其它區間不會受到影響。

是不是很完美?

不是的,理想和現實的差距是巨大的。

一致性哈希算法帶來了什麼問題?

當節點很少的時候可能會出現這樣的分佈情況,A服務會承擔大部分請求。這種情況就叫做數據傾斜。

怎麼解決數據傾斜呢?加入虛擬節點。

怎麼去理解這個虛擬節點呢?

首先一個服務器根據需要可以有多個虛擬節點。假設一台服務器有n個虛擬節點。那麼哈希計算時,可以使用IP+端口+編號的形式進行哈希值計算。其中的編號就是0到n的数字。由於IP+端口是一樣的,所以這n個節點都是指向的同一台機器。

如下圖所示:

在沒有加入虛擬節點之前,A服務器承擔了絕大多數的請求。但是假設每個服務器有一個虛擬節點(A-1,B-1,C-1),經過哈希計算后落在了如上圖所示的位置。那麼A服務器的承擔的請求就在一定程度上(圖中標註了五角星的部分)分攤給了B-1、C-1虛擬節點,實際上就是分攤給了B、C服務器。

一致性哈希算法中,加入虛擬節點,可以解決數據傾斜問題。

當你在面試的過程中,如果聽到了類似於數據傾斜的字眼。那大概率是在問你一致性哈希算法和虛擬節點。

在介紹了相關背景后,我們可以去看看一致性哈希算法在Dubbo中的應用了。

一致性哈希算法在Dubbo中的應用

前面我們說了Dubbo中負載均衡的實現是通過org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance中的 doSelect 抽象方法實現的,一致性哈希負載均衡的實現類如下所示:

org.apache.dubbo.rpc.cluster.loadbalance.ConsistentHashLoadBalance

由於一致性哈希實現類看起來稍微有點抽象,不太好演示,所以我想到了一個”騷”操作。前面的文章說過 LoadBalance 是一個 SPI 接口:

既然是一個 SPI 接口,那我們可以自己擴展一個一模一樣的算法,只是在算法裏面加入一點輸出語句方便我們觀察情況。怎麼擴展 SPI 接口就不描述了,只要記住代碼裏面的輸出語句都是額外加的,此外沒有任何改動即可,如下:

整個類如下圖片所示,請先看完整個類,有一個整體的概念后,我會進行方法級別的分析。

圖片很長,其中我加了很多註釋和輸出語句,可以點開大圖查看,一定會幫你更加好的理解一致性哈希在Dubbo中的應用:

改造之後,我們先把程序跑起來,有了輸出就好分析了。

服務端代碼如下:

其中的端口是需要手動修改的,我分別啟動服務在20881和20882端口。

項目中provider.xml配置如下:

consumer.xml配置如下:

然後,啟動在20881和20882端口分別啟動兩個服務端。客戶端消費如下:

運行結果輸出如下,可以先看個大概的輸出,下面會對每一部分輸出進行逐一的解讀

好了,用例也跑起來了,日誌也有了。接下來開始結合代碼和日誌進行方法級別的分析。

首先是doSelect方法的入口:

從上圖我們知道了,第一次調用需要對selectors進行put操作,selectors的 key 是接口中定義的方法,value 是 ConsistentHashSelector 內部類

ConsistentHashSelector通過調用其構造函數進行初始化的。invokers(服務端)作為參數傳遞到了構造函數中,構造函數裏面的邏輯,就是把服務端映射到哈希環上的過程,請看下圖,結合代碼,仔細分析輸出數據:

從上圖可以看出,當 ConsistentHashSelector 的構造方法調用完成后,8個虛擬節點在哈希環上已經映射完成。兩台服務器,每一台4個虛擬節點組成了這8個虛擬節點。

doSelect方法繼續執行,並打印出每個虛擬節點的哈希值和對應的服務端,請仔細品讀下圖:

說明一下:上面圖中的哈希環是沒有考慮比例的,僅僅是展現了兩個服務器在哈希環上的相對位置。而且為了演示說明方便,僅僅只有8個節點。假設我們有4台服務器,每台服務器的虛擬節點是默認值(160),這個情況下哈希環上一共有160*4=640個節點。

哈希環映射完成后,接下來的邏輯是把這次請求經過哈希計算后,映射到哈希環上,並順時針方向尋找遇到的第一個節點,讓該節點處理該請求:

還記得地址為 468e8565 的 A 服務器是什麼端口嗎?前面的圖片中有哦,該服務對應的端口是 20882 。

最後我們看看輸出結果:

和我們預期的一致。整個調用就算是完成了。

再對兩個方法進行一個補充說明。

第一個方法是 selectForKey,這個方法裏面邏輯如下圖所示:

虛擬節點都存儲在 TreeMap 中。順時針查詢的邏輯由 TreeMap 保證。看一下下面的 Demo 你就明白了。

第二個方法是 hash 方法,其中的 & 0xFFFFFFFFL 的目的如下:

&是位運算符,而 0xFFFFFFFFL 轉換為四字節表現后,其低32位全是1,所以保證了哈希環的範圍是 [0,Integer.MAX_VALUE]:

所以這裏我們可以改造這個哈希環的範圍,假設我們改為 100000。十進制的 100000 對於的 16 進製為 186A0 。所以我們改造后的哈希算法為:

再次調用后可以看到,計算后的哈希值都在10萬以內。但是分佈極不均勻,說明修改數據后這個哈希算法不是一個優秀的哈希算法:

以上,就是對一致性哈希算法在Dubbo中的實現的解讀。需要特殊說明一下的是,一致性哈希負載均衡策略和權重沒有任何關係

我又發現了一個BUG

前面我介紹了Dubbo 2.6.5版本之前,最小活躍數算法的兩個 bug。

很不幸,這次我又發現了Dubbo 2.7.4.1版本,一致性哈希負載均衡策略的一個bug,我提交了issue 地址如下:

https://github.com/apache/dubbo/issues/5429

我在這裏詳細說一下這個Bug現象、原因和我的解決方案。

現象如下,我們調用三次服務端:

輸出日誌如下(有部分刪減):

可以看到,在三次調用的過程中並沒有發生服務的上下線操作,但是每一次調用都重新進行了哈希環的映射。而我們預期的結果是應該只有在第一次調用的時候進行哈希環的映射,如果沒有服務上下線的操作,後續請求根據已經映射好的哈希環進行處理。

上面輸出的原因是由於每次調用的invokers的identityHashCode發生了變化:

我們看一下三次調用invokers的情況:

經過debug我們可以看出因為每次調用的invokers地址值不是同一個,所以System.identityHashCode(invokers)方法返回的值都不一樣。

接下來的問題就是為什麼每次調用的invokers地址值都不一樣呢?

經過Debug之後,可以找到這個地方:

org.apache.dubbo.rpc.cluster.RouterChain#route

問題就出在這個TagRouter中:

org.apache.dubbo.rpc.cluster.router.tag.TagRouter#filterInvoker

所以,在TagRouter中的stream操作,改變了invokers,導致每次調用時其

System.identityHashCode(invokers)返回的值不一樣。所以每次調用都會進行哈希環的映射操作,在服務節點多,虛擬節點多的情況下會有一定的性能問題。

到這一步,問題又發生了變化。這個TagRouter怎麼來的呢

如果了解Dubbo 2.7.x版本新特性的朋友可能知道,標籤路由是Dubbo2.7引入的新功能。

通過加載下面的配置加載了RouterFactrory:

META-INF\dubbo\internal\org.apache.dubbo.rpc.cluster.RouterFactory(Dubbo 2.7.0版本之前)

META-INF\dubbo\internal\com.alibaba.dubbo.rpc.cluster.RouterFactory(Dubbo 2.7.0之前)

下面是Dubbo 2.6.7(2.6.x的最後一個版本)和Dubbo 2.7.0版本該文件的對比:

可以看到確實是在 Dubbo 2.7.0 之後引入了 TagRouter。

至此,Dubbo 2.7.0 版本之後,一致性哈希負載均衡算法的 Bug 的來龍去脈也介紹清楚了。

解決方案是什麼呢?特別簡單,把獲取 identityHashCode 的方法從 System.identityHashCode(invokers) 修改為 invokers.hashCode() 即可。

此方案是我提的 issue 裏面的評論,這裏 System.identityHashCode 和 hashCode 之間的聯繫和區別就不進行展開講述了,不清楚的大家可以自行了解一下。

(我的另外一篇文章:夠強!一行代碼就修復了我提的Dubbo的Bug。)

改完之後,我們再看看運行效果:

可以看到第二次調用的時候並沒有進行哈希環的映射操作,而是直接取到了值,進行調用。

加入節點,畫圖分析

最後,我再分析一種情況。在A、B、C三個服務器(20881、20882、20883端口)都在正常運行,哈希映射已經完成的情況下,我們再啟動一個D節點(20884端口),這時的日誌輸出和對應的哈希環變化情況如下:

根據日誌作圖如下:

根據輸出日誌和上圖再加上源碼,你再細細回味一下。我個人覺得還是講的非常詳細了。

一致性哈希的應用場景

當大家談到一致性哈希算法的時候,首先的第一印象應該是在緩存場景下的使用,因為在一個優秀的哈希算法加持下,其上下線節點對整體數據的影響(遷移)都是比較友好的。

但是想一下為什麼 Dubbo 在負載均衡策略裏面提供了基於一致性哈希的負載均衡策略?它的實際使用場景是什麼?

我最開始也想不明白。我想的是在 Dubbo 的場景下,假設需求是想要一個用戶的請求一直讓一台服務器處理,那我們可以採用一致性哈希負載均衡策略,把用戶號進行哈希計算,可以實現這樣的需求。但是這樣的需求未免有點太牽強了,適用場景略小。

直到有天晚上,我睡覺之前,電光火石之間突然想到了一個稍微適用的場景了。

如果需求是需要保證某一類請求必須順序處理呢?

如果你用其他負載均衡策略,請求分發到了不同的機器上去,就很難保證請求的順序處理了。比如A,B請求要求順序處理,現在A請求先發送,被負載到了A服務器上,B請求后發送,被負載到了B服務器上。而B服務器由於性能好或者當前沒有其他請求或者其他原因極有可能在A服務器還在處理A請求之前就把B請求處理完成了。這樣不符合我們的要求。

這時,一致性哈希負載均衡策略就上場了,它幫我們保證了某一類請求都發送到固定的機器上去執行。比如把同一個用戶的請求發送到同一台機器上去執行,就意味着把某一類請求發送到同一台機器上去執行。所以我們只需要在該機器上運行的程序中保證順序執行就行了,比如你加一個隊列。

一致性哈希算法+隊列,可以實現順序處理的需求。

好了,一致性哈希負載均衡算法就寫到這裏。

繼續進入下一個議題。

加權輪詢負載均衡

這一小節是對於Dubbo負載均衡策略之一的加權隨機算法的詳細分析。

從 2.6.4 版本聊起,該版本在某些情況下存在着比較嚴重的性能問題。由問題入手,層層深入,了解該算法在 Dubbo 中的演變過程,讀懂它的前世今生。

什麼是輪詢?

在描述加權輪詢之前,先解釋一下什麼是輪詢算法,如下圖所示:

假設我們有A、B、C三台服務器,共計處理6個請求,服務處理請求的情況如下:

  1. 第一個請求發送給了A服務器
  2. 第二個請求發送給了B服務器
  3. 第三個請求發送給了C服務器
  4. 第四個請求發送給了A服務器
  5. 第五個請求發送給了B服務器
  6. 第六個請求發送給了C服務器
  7. ……

上面這個例子演示的過程就叫做輪詢。可以看出,所謂輪詢就是將請求輪流分配給每台服務器

輪詢的優點是無需記錄當前所有服務器的鏈接狀態,所以它一種無狀態負載均衡算法,實現簡單,適用於每台服務器性能相近的場景下。

輪詢的缺點也是顯而易見的,它的應用場景要求所有服務器的性能都相同,非常的局限。

大多數實際情況下,服務器性能是各有差異,針對性能好的服務器,我們需要讓它承擔更多的請求,即需要給它配上更高的權重。

所以加權輪詢,應運而生。

什麼是加權輪詢?

為了解決輪詢算法應用場景的局限性。當遇到每台服務器的性能不一致的情況,我們需要對輪詢過程進行加權,以調控每台服務器的負載。

經過加權后,每台服務器能夠得到的請求數比例,接近或等於他們的權重比。比如服務器 A、B、C 權重比為 5:3:2。那麼在10次請求中,服務器 A 將收到其中的5次請求,服務器 B 會收到其中的3次請求,服務器 C 則收到其中的2次請求。

這裏要和加權隨機算法做區分哦。直接把前面介紹的加權隨機算法畫的圖拿過來:

上面這圖是按照比例畫的,可以直觀的看到,對於某一個請求,區間(權重)越大的服務器,就越可能會承擔這個請求。所以,當請求足夠多的時候,各個服務器承擔的請求數,應該就是區間,即權重的比值。

假設有A、B、C三台服務器,權重之比為5:3:2,一共處理10個請求。

那麼負載均衡採用加權隨機算法時,很有可能A、B服務就處理完了這10個請求,因為它是隨機調用。

採用負載均衡採用輪詢加權算法時,A、B、C服務一定是分別承擔5、3、2個請求。

Dubbo2.6.4版本的實現

對於Dubbo2.6.4版本的實現分析,可以看下圖,我加了很多註釋,其中的輸出語句都是我加的:

示例代碼還是沿用之前文章中的Demo,這裏分別在 20881、20882、20883 端口啟動三個服務,各自的權重分別為 1,2,3。

客戶端調用 8 次:

輸出結果如下:

可以看到第七次調用后mod=0,回到了第一次調用的狀態。形成了一個閉環。

再看看判斷的條件是什麼:

其中mod在代碼中扮演了極其重要的角色,mod根據一個方法的調用次數不同而不同,取值範圍是[0,weightSum)。

因為weightSum=6,所以列舉mod不同值時,最終的選擇結果和權重變化:

可以看到20881,20882,20883承擔的請求數量比值為1:2:3。同時我們可以看出,當 mod >= 1 后,20881端口的服務就不會被選中了,因為它的權重被減為0了。當 mod >= 4 后,20882端口的服務就不會被選中了,因為它的權重被減為0了。

結合判斷條件和輸出結果,我們詳細分析一下(下面內容稍微有點繞,如果看不懂,多結合上面的圖片看幾次):

第一次調用

mod=0,第一次循環就滿足代碼塊①的條件,直接返回當前循環的invoker,即20881端口的服務。此時各端口的權重情況如下:

第二次調用

mod=1,需要進入代碼塊②,對mod進行一次遞減。

第一次循環對20881端口的服務權重減一,mod-1=0。

第二次循環,mod=0,循環對象是20882端口的服務,權重為2,滿足代碼塊①,返回當前循環的20882端口的服務。

此時各端口的權重情況如下:

第三次調用

mod=2,需要進入代碼塊②,對mod進行兩次遞減。

第一次循環對20881端口的服務權重減一,mod-1=1;

第二次循環對20882端口的服務權重減一,mod-1=0;

第三次循環時,mod已經為0,當前循環的是20883端口的服務,權重為3,滿足代碼塊①,返回當前循環的20883端口的服務。

此時各端口的權重情況如下:

第四次調用

mod=3,需要進入代碼塊②,對mod進行三次遞減。

第一次循環對20881端口的服務權重減一,從1變為0,mod-1=2;

第二次循環對20882端口的服務權重減一,從2變為1,mod-1=1;

第三次循環對20883端口的服務權重減一,從3變為2,mod-1=0;

第四次循環的是20881端口的服務,此時mod已經為0,但是20881端口的服務的權重已經變為0了,不滿足代碼塊①和代碼塊②,進入第五次循環。

第五次循環的是20882端口的服務,當前權重為1,mod=0,滿足代碼塊①,返回20882端口的服務。

此時各端口的權重情況如下:

第五次調用

mod=4,需要進入代碼塊②,對mod進行四次遞減。

第一次循環對20881端口的服務權重減一,從1變為0,mod-1=3;

第二次循環對20882端口的服務權重減一,從2變為1,mod-1=2;

第三次循環對20883端口的服務權重減一,從3變為2,mod-1=1;

第四次循環的是20881端口的服務,此時mod為1,但是20881端口的服務的權重已經變為0了,不滿足代碼塊②,mod不變,進入第五次循環。

第五次循環時,mod為1,循環對象是20882端口的服務,權重為1,滿足代碼塊②,權重從1變為0,mod從1變為0,進入第六次循環。

第六次循環時,mod為0,循環對象是20883端口的服務,權重為2,滿足條件①,返回當前20883端口的服務。

此時各端口的權重情況如下:

第六次調用

第六次調用,mod=5,會循環九次,最終選擇20883端口的服務,讀者可以自行分析一波,分析出來了,就了解的透透的了。

第七次調用

第七次調用,又回到mod=0的狀態:

2.6.4版本的加權輪詢就分析完了,但是事情並沒有這麼簡單。這個版本的加權輪詢是有性能問題的。

該問題對應的issue地址如下:

https://github.com/apache/dubbo/issues/2578

問題出現在invoker返回的時機上:

截取issue裏面的一個回答:

10分鐘才選出一個invoker,還怎麼玩?

有時間可以讀一讀這個issue,裏面各路大神針對該問題進行了激烈的討論,第一種改造方案被接受后,很快就被推翻,被第二種方案代替,可以說優化思路十分值得學習,很精彩,接下來的行文路線就是按照該issue展開的。

推翻,重建。

上面的代碼時間複雜度是O(mod),而第一次修復之後時間複雜度降低到了常量級別。可以說是一次非常優秀的優化,值得我們學習,看一下優化之後的代碼:

其關鍵優化的點是這段代碼,我加入輸出語句,便於分析。

輸出日誌如下:

把上面的輸出轉化到表格中去,7次請求的選擇過程如下:

該算法的原理是:

把服務端都放到集合中(invokerToWeightList),然後獲取服務端個數(length),並計算出服務端權重最大的值(maxWeight)。

index表示本次請求到來時,處理該請求的服務端下標,初始值為0,取值範圍是[0,length)。

currentWeight表示當前調度的權重,初始值為0,取值範圍是[0,maxWeight)。

當請求到來時,從index(就是0)開始輪詢服務端集合(invokerToWeightList),如果是一輪循環的開始(index=0)時,則對currentWeight進行加一操作(不會超過maxWeight),在循環中找出第一個權重大於currentWeight的服務並返回。

這裏說的一輪循環是指index再次變為0所經歷過的循環,這裏可以把index=0看做是一輪循環的開始。每一輪循環的次數與Invoker的數量有關,Invoker數量通常不會太多,所以我們可以認為上面代碼的時間複雜度為常數級。

從issue上看出,這個算法最終被merged了。

但是很快又被推翻了:

這個算法不夠平滑。什麼意思呢?

翻譯一下上面的內容就是:服務器[A, B, C]對應權重[5, 1, 1]。進行7次負載均衡后,選擇出來的序列為[A, A, A, A, A, B, C]。前5個請求全部都落在了服務器A上,這將會使服務器A短時間內接收大量的請求,壓力陡增。而B和C此時無請求,處於空閑狀態。而我們期望的結果是這樣的[A, A, B, A, C, A, A],不同服務器可以穿插獲取請求。

我們設置20881端口的權重為5,20882、20883端口的權重均為1。

進行實驗,發現確實如此:可以看到一共進行7次請求,第1次到5次請求都分發給了權重為5的20881端口的服務,前五次請求,20881和20882都處於空閑狀態:

轉化為表格如下:

從表格的最終結果一欄也可以直觀的看出,七次請求對應的服務器端口為:

分佈確實不夠均勻。

再推翻,再重建,平滑加權。

從issue中可以看到,再次重構的加權算法的靈感來源是Nginx的平滑加權輪詢負載均衡

看代碼之前,先介紹其計算過程。

假設每個服務器有兩個權重,一個是配置的weight,不會變化,一個是currentWeight會動態調整,初始值為0。當有新的請求進來時,遍歷服務器列表,讓它的currentWeight加上自身權重。遍歷完成后,找到最大的currentWeight,並將其減去權重總和,然後返回相應的服務器即可。

如果你還是不知道上面的表格是如何算出來的,我再給你詳細的分析一下第1、2個請求的計算過程:

第一個請求計算過程如下:

第二個請求計算過程如下:

後面的請求你就可以自己分析了。

從表格的最終結果一欄也可以直觀的看出,七次請求對應的服務器端口為:

可以看到,權重之比同樣是5:1:1,但是最終的請求分發的就比較的”平滑”。對比一下:

對於平滑加權算法,我想多說一句。我覺得這個算法非常的神奇,我是徹底的明白了它每一步的計算過程,知道它最終會形成一個閉環,但是我想了很久,我還是不知道背後的數學原理是什麼,不明白為什麼會形成一個閉環,非常的神奇。

很正常,我不糾結的,程序猿的工作不就是這樣嗎?我也不知道為什麼,它能工作。別問,問就是玄學,如果一定要說出點什麼的話,我想,我願稱之為:絕活吧。

但是我們只要能夠理解我前面所表達的平滑加權輪詢算法的計算過程,知道其最終會形成閉環,就能理解下面的代碼。配合代碼中的註釋食用,效果更佳。

以下代碼以及註釋來源官網:

http://dubbo.apache.org/zh-cn/docs/source_code_guide/loadbalance.html

總結

好了,到這裏關於Dubbo的五種負載均衡策略就講完了。簡單總結一下:(加權隨機算法在講最小活躍數算法的時候提到過,因為原理十分簡單,這裏就不專門拿出章節來描述了。)

最短響應時間負載均衡:在所有服務提供者中選出平均響應時間最短的一個,如果能選出來,則使用選出來的一個。如果不能選出來多個,再根據權重選,如果權重也一樣,則隨機選擇。

一致性哈希負載均衡:在一致性哈希算法中,不管是增加節點,還是宕機節點,受影響的區間僅僅是增加或者宕機服務器在哈希環空間中,逆時針方向遇到的第一台服務器之間的區間,其它區間不會受到影響。為了解決數據傾斜的問題,引入了虛擬節點的概念。一致性哈希算法是 Dubbo 中唯一一個與權重沒有任何關係的負載均衡算法,可以保證相同參數的請求打到同一台機器上。

最小活躍數負載均衡:需要配合 activeFilter 使用,活躍數在方法調用前後進行維護,響應越快的服務器堆積的請求越少,對應的活躍數也少。Dubbo 在選擇的時候遵循下面的規則,有最小活躍數用最小活躍數,沒有最小活躍數根據權重選擇,權重一樣則隨機返回的負載均衡算法。

加權隨機算法:隨機,顧名思義,就是從多個服務提供者中隨機選擇一個出來。加權,就是指需要按照權重設置隨機概率。常見場景就是對於性能好的機器可以把對應的權重設置的大一點,而性能相對較差的,權重設置的小一點。哎,像極了這個社會上的某些現象,對外宣傳是隨機搖號,背後指不定有一群權重高的人呢。

加權輪詢負載均衡:輪詢就是雨露均沾的意思,所有的服務提供者都需要調用。而當輪詢遇到加權則可以讓請求(不論多少)嚴格按照我們的權重之比進行分配。比如有A、B、C三台服務器,權重之比為5:3:2,一共處理10個請求。那麼採用負載均衡採用輪詢加權算法時,A、B、C服務一定是分別承擔5、3、2個請求。同時需要注意的是加權輪詢算法的兩次升級過程,以及最終的“平滑”的解決方案。

再說一件事

本文主要聊的是負載均衡嘛,讓我想起了 2019 年阿里巴巴第五屆中間件挑戰賽的初賽賽題也是實現一個負載均衡策略。

具體的賽題可以看這裏:

https://tianchi.aliyun.com/competition/entrance/231714/information

這種比賽還是很有意思的,你報名之後僅僅是讀懂賽題,然後自己多想想怎麼實現,哪怕是不提交代碼,在比賽完成后看前幾名的賽題分析,再去把他們的代碼拉下來看看,你就會發現,其實最終的思路都大同小異,差別會體現在參數調優和代碼優化程度上。

當然最大的差別還是會體現在語言的層面。如果不限制參數語言的話,Java 系的选手一定是被 C 系选手吊打的。

但是,被吊打不重要,重要的是真的能學到很多的東西,而這些東西,在絕大部分工作中是很難學到的。

最近,阿里巴巴第六屆中間件挑戰賽也開始了,可以看一下這個鏈接:

https://tianchi.aliyun.com/competition/entrance/231790/introduction?spm=5176.12281968.1008.3.65818188YmzFqa

這次是分為三個賽道,選擇性更多了。

作為這個比賽的長期關注者(持續關注三年了吧),這次作為一個自來水免費宣傳一波。

朋友,我真心建議你去看一下,報個名,玩一玩,收穫真的很大的。

當然,如果能在報名的時候邀請人那一欄填【why技術】,我真心感謝你。

最後說一句(求關注)

點個“贊”吧,周更很累的,不要白嫖我,需要一點正反饋。

才疏學淺,難免會有紕漏,如果你發現了錯誤的地方,還請你留言指出來,我對其加以修改。

感謝您的閱讀,我堅持原創,十分歡迎並感謝您的關注。

我是 why,一個被代碼耽誤的文學創作者,不是大佬,但是喜歡分享,是一個又暖又有料的四川好男人。

歡迎關注我的微信公眾號:why技術。在這裏我會分享一些java技術相關的知識,用匠心敲代碼,對每一行代碼負責。偶爾也會荒腔走板的聊一聊生活,寫一寫書評、影評。感謝你的關注,願你我共同進步。

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

這款2.0L全新SUV氣場堪比寶馬X6!上市后13萬內就賣瘋_包裝設計

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

不過遺憾的是T90並沒有配備群眾們喜聞樂見的全景天窗,只是尺寸也不算很大的普通天窗。乘坐空間這一點對於國內消費者來說就是重中之重了,國人就是喜歡大尺寸、大空間,畢竟拖家帶口空間小了坐着確實憋屈。T90的座椅使用了和天籟同級的人體工程學座椅,座椅填充物柔軟,舒適性和包裹性都非常好,絕對也能稱得上是移動大沙發。

前段時間小編去體驗了一把國產版寶馬X6-啟辰T90,之所以說是X6,是因為在外形上,T90和X6看起來確實比較像。T90定位中型轎跑型SUV,上市之後將會成為啟辰的旗艦車型。預售價將會在廣州車展上公布。

由於是中型SUV,所以T90的尺寸自然不會小,長寬高為4793*1865*1592mm,軸距為2765mm,個頭算是挺大的了。因為是溜背的造型,再加上較長的車身,所以側面來看T90顯得很修長,同時空載的時候最小離地間隙為194mm,通過性還是不錯的。不過最吸引人的是廠家宣稱T90是啟辰“風雕美學”設計理念的第一款車型,整車原創度非常高,同時別緻的前進氣格柵也使T90讓人眼前一亮。

到了車內,大家會發現T90的原創度會更高了,內飾不管是做工還是用料,都是十分的用心。新車的氣味較小,可見內飾選材還是比較嚴格的。同時配置又很高,尤其是中控那個高達12.3英寸的大屏幕,絕對很奪人眼球,同時它的分辨率高達1920*768,畫面清晰,運行流暢,

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

沒有遇到卡頓的情況。同時它還可以分屏显示,左側小屏幕显示菜單功能,不會影響右側屏幕的显示。配備百度CarLife系統,這是啟辰和百度合作開發的,可以鏈接安卓和蘋果手機,功能豐富。

不單中控做的好,內飾用料也很不錯。進入車內凡是手可以碰到的地方全部是使用了軟性材料,比如中控面板,扶手箱,門把手等,所以幾乎你在車內是感覺不到廉價感覺的。不過遺憾的是T90並沒有配備群眾們喜聞樂見的全景天窗,只是尺寸也不算很大的普通天窗。

乘坐空間這一點對於國內消費者來說就是重中之重了,國人就是喜歡大尺寸、大空間,畢竟拖家帶口空間小了坐着確實憋屈。T90的座椅使用了和天籟同級的人體工程學座椅,座椅填充物柔軟,舒適性和包裹性都非常好,絕對也能稱得上是移動大沙發。後排空間較大,但是溜背的造型會犧牲一定的頭部空間。

動力系統應該是T90最拿得出手的東西了。T90配備日產MR20自然吸氣發動機,排量為2.0L,最大功率144馬力,最大扭矩198牛·米,匹配CVT無級變速箱。這套動力系統同時也在天籟和逍客上面使用,所以T90的動力系統應該是很讓人放心了。畢竟這是一套成熟、可靠、穩定、經濟的動力系統。

T90馬上就會成為啟辰的旗艦轎車,所以啟辰方面也是特別重視的,從整車的做工來看也能看出來廠家確實是在用心做產品。後期我們還會有T90的試駕文章,喜歡它的消費者可以留意一下。

儘管T90會在即將到來的廣州車展公布預售價,但是官方曾說,這款車的預售價在20萬以下,聽到這價格我就心涼了半截,只是覺得,好貴…到時候價格真的是接近20萬了,那估計銷量真的堪比寶馬X6了。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

春節假期第四天全國主要道路交通安全順暢_包裝設計

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

新華社北京1月27日電 公安部交管局27日發布信息,春節假期第四天,各主要高速公路、國省道幹線公路交通安全順暢,根據全國35條高速公路200個重要通道監測節點流量監測情況,交通總流量與去年同期相比下降39.9%。截至17時,未發生長時間長距離交通擁堵,未接報一次死亡5人以上較大交通事故。

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

全國公安交管部門根據公安部統一部署,在當地黨委政府和公安機關的統一指揮下,主動擔當、积極作為,統籌春節假日交通安保和交通應急管理,會同和配合有關部門嚴密重點路段管控、嚴密重點部位防護、嚴密重點車輛查控,全力投入疫情防控工作,全力保障道路交通安全暢通。據統計,各地公安交管部門共出動警力18萬餘人次,出動警車7萬餘輛次,啟動交警執法站4100餘個,設立臨時執勤點1.2萬餘個。

根據中央氣象台預報,27日至28日,西南部局地有大雪或暴雪。27日夜間至28日早晨,湖北東部、湖南北部、江西東北部、山東中部、江蘇北部等地部分地區將有大霧天氣,局部有濃霧或強濃霧。公安部交管局提示廣大駕駛人朋友:霧天行車要打開霧燈,控制車速、保持安全車距;在冰雪路面行車時,要做到“緩加油、輕減速、慢轉彎”;請牢記“安全帶——生命帶”,駕車一定系好安全帶,莫忘為兒童選用適合其年齡、體重的兒童安全座椅。特別是請按照各地疫情防控工作的要求,盡量減少交通出行。

本站聲明:網站內容來http://www.societynews.cn/html/wh/fq/,如有侵權,請聯繫我們,我們將及時處理

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

循序漸進VUE+Element 前端應用開發(5)— 表格列表頁面的查詢,列表展示和字段轉義處理,循序漸進VUE+Element 前端應用開發(4)— 獲取後端數據及產品信息頁面的處理_包裝設計

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

在我們一般開發的系統界面裏面,列表頁面是一個非常重要的綜合展示界面,包括有條件查詢、列表展示和分頁處理,以及對每項列表內容可能進行的轉義處理,本篇隨筆介紹基於Vue +Element基礎上實現表格列表頁面的查詢,列表展示和字段轉義處理。

在前面隨筆《循序漸進VUE+Element 前端應用開發(4)— 獲取後端數據及產品信息頁面的處理》介紹了一個對產品列表的卡片式圖片分頁展示處理,其中涉及到了對於Element 組件分頁控件的操作,本篇隨筆繼續深化這一組件的使用,結合表格展示來處理效果展示。

1、列表查詢界面效果

在介紹任何代碼處理邏輯之前,我們先來做一個感官的認識,貼上一個效果圖,在逐一介紹其中處理的步驟和注意事項。

 常規的列表展示界面,一般分為幾個區域,一個是查詢區域,一個是列表展示區域,一個是底部的分頁組件區域。查詢區域主要針對常規條件進行布局,以及增加一些全局或者批量的操作,如導入、導出、添加、批量添加、批量刪除等按鈕;而其中主體的列表展示區域,是相對比較複雜一點的地方,需要對各項數據進行比較友好的展示,可以結合Tag,圖標,按鈕等界面元素來展示,其中列表一般後面會包括一些對單行記錄處理的操作,如查看、編輯、刪除的操作,如果是批量刪除,可以放到頂部的按鈕區域。

 

2、查詢區域的處理

查詢區域一般的界面效果如下所示,除了包含一些常用的查詢條件,並增加一些常規的處理按鈕,如查詢、重置、新增、批量刪除、導入、導出等按鈕。

  對於查詢區域來說,它也是一個表單的處理,因此也需要添加一一個對應的對象來承載表單的數據,在data裏面增加一個searchForm的模型對象,以及一個用於分頁查詢的pageinfo對象,如下代碼所示。

export default {
  data() {
    return {
      listLoading: true,
      pageinfo: {
        pageindex: 1,
        pagesize: 10,
        total: 0
      },
      searchForm: {
        ProductNo: '',
        BarCode: '',
        ProductType: '',
        ProductName: '',
        Status: 0
      },

視圖模板代碼如下所示

    <el-form ref="searchForm" :model="searchForm" label-width="80px">
      <el-row>
        <el-col :span="6">
          <el-form-item label="產品編號" prop="ProductNo">
            <el-input v-model="searchForm.ProductNo" />
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="產品名稱" prop="ProductName">
            <el-input v-model="searchForm.ProductName" />
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="商品類型" prop="ProductType">
            <el-select v-model="searchForm.ProductType" filterable clearable placeholder="請選擇">
              <el-option
                v-for="(item, key) in typeList"
                :key="key"
                :label="item.value"
                :value="item.key"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="6">
          <el-form-item label="狀態" prop="Status">
            <el-select v-model="searchForm.Status" filterable clearable placeholder="請選擇">
              <el-option
                v-for="item in Status"
                :key="item.Value"
                :label="item.Text"
                :value="item.Value"
              />
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <el-row style="float:right;padding-bottom:10px">
      <el-button icon="el-icon-search" type="primary" round @click="search()">查詢</el-button>
      <el-button icon="el-icon-refresh-left" type="warning" round plain @click="resetForm('searchForm')">重置</el-button>
      <el-button icon="el-icon-document-add" type="success" round @click="showAdd()">新增</el-button>
      <el-button icon="el-icon-document-remove" type="danger" round @click="BatchDelete()">批量刪除</el-button>
      <el-button icon="el-icon-upload2" type="danger" plain="" round @click="showImport()">導入</el-button>
    </el-row>

其中產品類型的是下拉列表,我們通過在data區域獲取一個對象,並在此遍歷可以展示字典內容,如果我們花點時間,可以把這些下拉列表統一按照一個常規的處理模式,定義一個字典組件的方式實現,簡單賦予一個字典類型的Prop值,就可以綁定下拉列表了,這個稍後在細講。

在Vue的腳本處理邏輯裏面,我們可以在Created聲明周期裏面,通過API獲取數據,綁定在模型上,界面就會自動進行更新了,處理過程代碼如下所示。

  created() {
    // 獲取產品類型,用於綁定字典等用途
    GetProductType().then(data => {
      if (data) {
        data.forEach(item => {
          this.productTypes.set(item.id, item.name)
          this.typeList.push({ key: item.id, value: item.name })
        })
      }
    });

    // 獲取列表信息
    this.getlist()
  },
  methods: {
    getlist() { // 構造常規的分頁查詢條件
      var param = {
        type: this.producttype === 'all' ? '' : this.producttype,
        pageindex: this.pageinfo.pageindex,
        pagesize: this.pageinfo.pagesize
      };

      // 把SearchForm的條件加入到param裏面,進行提交查詢
      param.type = this.searchForm.ProductType // 轉換為對應屬性
      Object.assign(param, this.searchForm); // 獲取產品列表,綁定到模型上,並修改分頁數量
      this.listLoading = true
      GetProductList(param).then(data => {
        this.productlist = data.list
        this.pageinfo.total = data.total_count
        this.listLoading = false
      })
    },

其中 Object.assign(param, this.searchForm); 語句處理,是把獲得的查詢條件,覆蓋原來對象裏面的屬性,從而實現查詢條件的變量賦值。

獲得列表數據,就是介紹如何展示表格列表數據的過程了,表格界面效果如下所示。

  先定義一個表格頭部,類似HTML裏面的<table>的標籤,指定樣式和一些常規的操作函數,如下代碼所示。

    <el-table
      v-loading="listLoading"
      :data="productlist"
      border
      fit
      stripe
      highlight-current-row
      :header-cell-style="{background:'#eef1f6',color:'#606266'}"
      @selection-change="selectionChange"
      @row-dblclick="rowDbclick"
    >

具體的屬性可以參考下Element組件關於表格控件的屬性了,在表格列裏面,我們主要關注它的data綁定即可。

接着定義一列複選框選擇的列,用於批量處理的勾選,如批量刪除操作。

  <el-table-column type="selection" width="55"/>

接着就是根據返回JSON屬性,逐一進行內容轉換為表格列的展示過程了,如下所示。

  <el-table-column label="商品編號" width="80">
    <template slot-scope="scope">
      {{ scope.row.ProductNo }}
    </template>
  </el-table-column>

我們如果需要在显示裏面增加處理效果,一般在template裏面修改展示效果即可,如下是單位的處理,增加一個tag標誌強調下。

  <el-table-column align="center" label="單位" width="80">
    <template slot-scope="scope">
      <el-tag type="" effect="plain"> {{ scope.row.Unit }}</el-tag>
    </template>
  </el-table-column>

 而對於一些需要判斷處理的效果,我們可以對內容進行判斷輸出,如下狀態所示。

  <el-table-column label="狀態" width="80">
    <template slot-scope="scope">
      <el-tag v-if="scope.row.Status==0" type="" effect="dark">正常</el-tag>
      <el-tag v-else-if="scope.row.Status==1" type="success" effect="dark">推薦</el-tag>
      <el-tag v-else-if="scope.row.Status==2" type="danger" effect="dark">停用</el-tag>
    </template>
  </el-table-column>

 另外,對於一些常見的日期處理,我們可以使用Formatter,Filter等手段進行內容的轉義處理,可以去掉後面的時間部分。

<el-table-column align="center" label="創建日期" width="120" prop="CreateTime" :formatter="dateFormat" />

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

  dataFormat就是一個轉義函數,函數代碼如下所示。

    dateFormat(row, column, cellValue) {
      return cellValue ? fecha.format(new Date(cellValue), 'yyyy-MM-dd') : ''
    },

使用的時候,需要在頂部引入一個類庫即可

import * as fecha from 'element-ui/lib/utils/date'

對於類似需要進行字典轉義的操作,我們可以使用Formatter的方式轉義,如增加一個函數來解析對應的值為中文信息

  效果可以使用Formatter來轉義

    productTypeFormat(row, column, cellValue) {
      var display = this.productTypes.get(cellValue)
      return display || ''
    },

也可以使用Filter模式來進行處理。

這裏介紹使用Filter的操作處理,首先在界面HTML代碼裏面增加對應的操作,如下代碼所示。

  <el-table-column align="center" label="商品類型" width="120" prop="ProductType">
    <template slot-scope="scope">
      <el-tag type="danger">  {{ scope.row.ProductType | productTypeFilter }}</el-tag>
    </template>
  </el-table-column>

Filter其實就是一個 | 過濾符號,以及接着一個過濾函數處理即可。

export default {
  filters: {
    productTypeFilter: function(value) {
      if (!value) return ''

      var display = that.productTypes.get(value)
      return display || ''
    }
  },

值得注意的是,Filter本身不能引用data裏面的屬性列表進行轉義的需要,如果需要,那麼需要在beforeCreate的鈎子函數裏面記錄this的引用,如下代碼所示。

  對於操作按鈕,我們需要增加一行來显示幾個按鈕即可,如果需要權限控制,可以再根據權限集合判斷一下可操作權限即可。

      <el-table-column label="操作" width="140">
        <template scope="scope">
          <el-row>
            <el-tooltip effect="light" content="查看" placement="top-start">
              <el-button icon="el-icon-search" type="success" circle size="mini" @click="showView(scope.row.ID)" />
            </el-tooltip>
            <el-tooltip effect="light" content="編輯" placement="top-start">
              <el-button icon="el-icon-edit" type="primary" circle size="mini" @click="showEdit(scope.row.ID)" />
            </el-tooltip>
            <el-tooltip effect="light" content="刪除" placement="top-start">
              <el-button icon="el-icon-delete" type="danger" circle size="mini" @click="showDelete(scope.row.ID)" />
            </el-tooltip>
          </el-row>
        </template>
      </el-table-column>

這裏showView/showEdit/ShowDelete主要就是做一些彈出層前的處理操作,我們在data項裏面定義了幾個變量,用來確定是那個操作显示的需要。

      isAdd: false,
      isEdit: false,
      isView: false,
      isImport: false,

例如對應編輯操作,我們是需要通過API處理類,獲取後端數據,並賦值給編輯框的表單對象上,進行展示即可。

    showEdit(id) {
      // 通過ID參數,使用API類獲取數據后,賦值給對象展示
      var param = { id: id }
      GetProductDetail(param).then(data => {
        Object.assign(this.editForm, data);
      })
      this.isEdit = true
    },

對於查看處理,我們除了在每行按鈕上可以單擊進行查看指定行記錄外,我們雙擊指定的行,也應該彈出對應的查看記錄界面

    rowDbclick(row, column) {
      var id = row.ID
      this.showView(id);
    },

這個就是表格定義裏面的一些處理事件

    <el-table
      v-loading="listLoading"
      :data="productlist"
      border
      fit
      stripe
      highlight-current-row
      :header-cell-style="{background:'#eef1f6',color:'#606266'}"
      @selection-change="selectionChange" @row-dblclick="rowDbclick"
    >

每個對話框的:visible的屬性值,則是確定哪個模態對話框的显示和隱藏。

 而對於刪除操作,我們只需要確認一下,然後提交遠端處理,返回正常結果,就提示用戶刪除成功即可。如下邏輯代碼所示。

    showDelete(id) {
      this.$confirm('您確認刪除選定的記錄嗎?', '操作提示',
        {
          type: 'warning' // success,error,info,warning
          // confirmButtonText: '確定',
          // cancelButtonText: '取消'
        }
      ).then(() => {
        // 刪除操作處理代碼

        this.$message({
          type: 'success',
          message: '刪除成功!'
        });
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消刪除'
        });
      });
    },

以上就是常規表格列表頁面查詢、列表展示、字段轉義的一些常規操作,以及對新增、編輯、查看、刪除操作的一些常規處理,通過對這些模型的操作,減少了我們以往重新獲取對應DOM的繁瑣操作,是的數據的操作處理,變得方便了很多。

列出以下前面幾篇隨筆的連接,供參考:

循序漸進VUE+Element 前端應用開發(1)— 開發環境的準備工作

循序漸進VUE+Element 前端應用開發(2)— Vuex中的API、Store和View的使用

循序漸進VUE+Element 前端應用開發(3)— 動態菜單和路由的關聯處理

循序漸進VUE+Element 前端應用開發(4)— 獲取後端數據及產品信息頁面的處理

 

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

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

學習習近平主席聯大重要講話精神暨國家“十四五”應對氣候變化規劃思路研討會圓滿舉行_包裝設計

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

2020-10-09

2020-10-09
分享到:
[打印]
字號:[大] [中] [小]

  9月30日,由生態環境部主辦,國家應對氣候變化戰略研究和國際合作中心承辦的“學習習近平主席在第七十五屆聯合國大會一般性辯論上的重要講話精神專家座談會暨國家‘十四五’應對氣候變化規劃思路及2035年願景展望專家研討會”在京順利召開,來自國家氣候變化專家委員會、國家發展改革委、國務院發展研究中心、中科院、社科院等單位的專家參加了研討。生態環境部副部長趙英民出席研討會並講話。

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

  與會專家一致認為,習近平主席鄭重宣布中國二氧化碳排放力爭於2030年前達到峰值,努力爭取2060年前實現碳中和,這是黨中央、國務院統籌國際國內兩個大局作出的重大戰略決策,進一步彰顯了中國深入貫徹習近平生態文明思想、堅定走綠色低碳發展道路的戰略定力,以及堅定支持多邊主義、积極推動構建人類命運共同體的大國擔當,極大提振了國際社會共同實施《巴黎協定》和推動疫後世界經濟“綠色復蘇”的信心。

  與會專家建議下一步重點加強三方面工作:一是認真做好對習近平主席重要講話精神的學習和宣傳,進一步統一思想和認識,提高政治站位,動員全社會力量,推動各地區、各部門及行業加快形成應對氣候變化工作合力。二是抓緊做好“十四五”應對氣候變化的謀篇布局,在準確把握習近平主席重要講話精神實質的基礎上,結合當前形勢和長遠目標,進一步強化戰略研判、目標引領和政策創新。三是儘早部署實現中長期氣候新行動目標路線圖,儘快出台《二氧化碳排放達峰行動計劃》,加強對2035年遠景目標的論證,系統謀划“碳中和國家”建設基本方略和實施路線圖。

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

什麼?10萬預算就能買到獨立懸挂+帶T動力好的車型!_包裝設計

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

5T 152馬力+5擋手動。艾瑞澤7也是配備了多連桿獨立懸架,如果選擇1。5T車型,那麼絕對也是很具有駕駛激情的,因為車子馬力夠大,同時手動變速箱換擋也很清晰,再加上艾瑞澤7紮實的底盤調校,開起來絕對是非常的穩。另外艾瑞澤7用料也比較足,這點讓消費者也很滿意。

大多數人買車都是比較重視價格,只要價格不合適就說拜拜,但是有一部分人卻覺得車子開着爽了就好了,所以今天就給大家推薦幾款不到十萬的,開着比較有激情自主轎車。

廣汽傳祺GA3S視界

GA3S視界的車身尺寸為4590*1790*1490mm,軸距為2620mm,定位緊湊型轎車。GA3S視界看起來比較緊湊,側面腰線比較凌厲,看起來很帶感。

視界的動力系統為1.6L 122馬力+5擋手動/4擋自動,1.3T 137馬力+5擋手動。要說駕駛激情肯定是要推薦1.3T手動擋車型,GA3S視界配備了獨立懸架,同時發動機和變速箱匹配的很默契,換擋清晰,吸入感強,渦輪爆發力也比較足,再加上紮實的底盤調校,使得視界的操控性很不錯。

奇瑞汽車-艾瑞澤7

艾瑞澤7的車身尺寸為4652*1825*1483mm,

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

軸距為2700mm,也是定位緊湊型轎車,但是車子一點也不小,較大的車身保證了艾瑞澤7有着較大的乘坐空間。

艾瑞澤7的動力系統為1.6L 126馬力+5擋手動/CVT,1.5T 152馬力+5擋手動。艾瑞澤7也是配備了多連桿獨立懸架,如果選擇1.5T車型,那麼絕對也是很具有駕駛激情的,因為車子馬力夠大,同時手動變速箱換擋也很清晰,再加上艾瑞澤7紮實的底盤調校,開起來絕對是非常的穩。另外艾瑞澤7用料也比較足,這點讓消費者也很滿意。

比亞迪-比亞迪G5

G5的車身尺寸為4700*1790*1480mm,軸距為2670mm,G5的外觀尺寸比較大,所以 看起來更加的大氣,但是G5看起來比較沉穩,適合年更加成熟的消費者。

G5的動力系統為1.5T 154馬力+6擋手動/6擋雙離合,這款發動機為比亞迪自主研發的1.5T發動機,採用了缸內直噴、分層燃燒和可變氣門正時等三大技術,最大馬力154,最大扭矩240。數據表現很不錯,自動擋的0-100km/h加速為9.2s左右,提速很快,如果對雙離合不放心了那麼手動擋是更好的選擇。雖然動力十足,但是G5的底盤調教不是很好。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

生態環境部就二氧化碳排放達峰行動方案聽取地方意見_包裝設計

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

2020-12-10

2020-12-10
分享到:
[打印]
字號:[大] [中] [小]   2020年12月7日,生態環境部副部長趙英民在上海主持召開座談會,就二氧化碳排放達峰行動聽取地方意見。生態環境部氣候司、國家氣候戰略中心,31個省(區、市)生態環境廳(局)相關負責同志參加座談。各地介紹了本地區開展二氧化碳排放達峰行動的工作基礎、挑戰及下一步工作考慮,並對生態環境部組織編寫的《省級二氧化碳排放達峰行動方案編製指南(徵求意見稿)》提出意見建議。   會議強調,實現二氧化碳排放達峰目標時間緊迫、任務艱巨,需要各部門、各地區主動作為,

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

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

國家和地方上下聯動、形成合力。各省(區、市)要圍繞貫徹落實習近平總書記關於我國新的達峰目標與碳中和願景的重大宣示,切實提高政治站位,進一步統一思想、提高認識,以開展達峰行動為抓手,以編製達峰行動方案為突破口,加強頂層設計和統籌協調,充分發揮達峰行動對倒逼經濟高質量發展、推進生態文明建設、形成綠色低碳生產生活方式的作用,不斷提高應對氣候變化工作水平和能力。   生態環境部趙英民副部長還赴浦東新區調研應對氣候變化工作,並實地了解上海前灘天然氣分佈式供能項目建設、運行和管理情況。生態環境部氣候司、上海市生態環境局有關同志參加調研。

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。