2016第二屆中國(成都)電動車及新能源專用車輛展覽會

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

保時捷公佈電動汽車研發計畫 2020年前上市

據外媒報導,保時捷近日在北美車展上推出了2017年款保時捷911 Turbo和Turbo S,借著新車發佈的轟動效應,保時捷911專案主管伊哈德-莫斯勒(Erhard Mossle)宣佈,保時捷未來將在旗艦版跑車的基礎上推出插電混動版車型。

伊哈德-莫斯勒表示:“我們正在研究不同的解決方案,同時我們也在研發全電動汽車。當然,我們正在討論推出保時捷911插電版車型的可能性。眼下我們還有很多工作要做,比如如何在車內放置電池組等等。保時捷911插電版或在下一代車型中成為現實。”

伊哈德-莫斯勒還表示,插電版保時捷911跑車在研發過程中仍然會將性能放在首要考慮的位置,未來該款車很有可能保留6缸引擎,不過車輛也會兼顧滿足消費者對於更為綠色環保城市汽車的需求。

下一代保時捷911跑車預計和E任務轎車有望在2020年前同公眾見面。

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

新德里市議員選舉投票 選民關心空污電費減免

摘錄自2020年02月09日中央通訊社印度報導

新德里今(8日)舉行市議員選舉投票,雖有政黨在選舉中主打國家安全政策,不過,許多選民更關心政府如何防治空污、提供社會保障、電費減免和照顧窮人等切身議題。

新德里超過1470萬名合格選民8日上午8時起到晚間6時,在1萬3751個投票所進行投票,從672名市議員候選人中選出70席;選舉結果將在11日出爐,進而由議會多數組成新一屆首都內閣。

小老百姓黨(AAP)上次選舉贏得67席市議員的多數在首都組閣執政,新德里市長克里瓦爾(Arvind Kejriwal)這次率領AAP尋求連任,並利用執政優勢陸續推出水電免費及無線網路、健康、教育免費及婦女免費搭乘公共交通工具等政策,希望吸引選民再給他們5年的執政機會。

不過,由印度總理莫迪和印度人民黨主席(BJP)兼內政部長夏哈(Amit Shah)率領的印度人民黨,從1993年以後就從未曾在新德里市議會選舉中拿下多數,這次希望挾著去年在國會選舉大勝的餘威,奪下首都執政權。

另外,印度人民黨也指控AAP在新德里無法提供乾淨的飲用水,而且沒有能力提供免費無線網路及安裝閉路電視。

不過,在南德里一處小學的投票所,一些排隊投票的市民大多關切的還是如何防治空氣污染、社會保障與社區安全、電力供應與電費減免等切身問題。

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

Java升級那麼快,多個版本如何靈活切換和管理?

前言

近兩年,Java 版本升級頻繁,感覺剛剛掌握 Java8,寫本文時,已聽到 java14 的消息,無論是嘗鮮新特性(),還是由於項目升級/兼容需要,我們可能都要面臨管理多個 Java 版本的情

另外 Oracle 自 Java11 開始,更改了用戶協議,任何商用都會收費。在寫本文時,得到消息「微軟宣布加入 OpenJDK」,打不過就選擇 OpenJDK。隨便 G 一下,當個故事了解就可以

配置單個 Java 環境變量本身沒什麼技術含量可言,但當需要管理多個 Java 版本,重複配置環境變量顯然是非常枯燥的,按照傳統的配置方式我們又不能靈活的切換 Java 版本

那要如何輕鬆管理與使用多個版本 Java?

多版本 Java 管理

顯然我們不是第一個有這種困境的人,我所知道的現有方案有三種:

本文主要說明如何通過 sdkman 打破我們面臨的困境,幫助我們靈活配置與使用 Java

sdkman 介紹

SDKMAN 是一個用於在大多數基於 Unix 系統上管理 多個軟件開發工具包 (Java, Groovy, Scala, Kotlin and Ceylon. Ant, Gradle 等) 的并行版本的工具 。

它提供了一個方便的命令行接口 (CLI) 和 API,用於安裝、切換、刪除和列出候選對象。本文主要通過管理 Java 來說明 sdkman 的使用

sdkman 安裝

在類 unix 平台上安裝 sdkman 非常容易。它可以順利的安裝在Mac OSX、Linux、WLS、Cygwin、Solaris和FreeBSD 上,同時還支持Bash和 ZSH shell。

只需打開一個新終端機並輸入:

$ curl -s "https://get.sdkman.io" | bash

按照相應的指令提示,完成相應的操作後繼續輸入:

$ source "$HOME/.sdkman/bin/sdkman-init.sh"

到這裏我們就可以驗證 sdk 的安裝版本了:

$ sdk version

上圖紅色框標記显示我當前 sdkman 的版本,每次執行 sdk version 命令時,都會檢查是否會有新版本,如果要更新輸入 y 就可以

有些系統發行版本不包含 zip 和 unzip,如果安裝時遇到相關錯誤,可以輸入如下命令安裝 zip 和 unzip

$ sudo apt-get install zip unzip

從上面的安裝命令上可以看出,sdkman 默認的安裝路徑是在$HOME/.sdkman 下,我們也可以自定義安裝路徑,只需要指定 SDKMAN_DIR 變量值就好了:

$ export SDKMAN_DIR="/usr/local/sdkman" && curl -s "https://get.sdkman.io" | bash

到這裏 sdkman 的安裝就結束了,我們來看看如何使用

sdkman 使用教程

命令行下學習一個新玩意當然是查看它的 help 命令,輸入:

$ sdkman help

感覺上圖按顏色區分內容后,sdkman 的使用說明也就結束了,我們按照上面的圖來詳細說明一下使用教程

sdk list

先來輸入:

$ sdk list

綠色的標記就是 sdkman 集成的所有可用的 candidate,通過按回車「enter」按鍵,會看到更多可用 candidate

我們指定 candidate,輸入:

$ sdk list java

從上圖中可以看到所有 java 可用的版本 version,以及標識 indentifier,以及狀態 status,我已經安裝了 java 12 和 11

有了這些信息做鋪墊,我們可以安裝任意 sdkman 內置的軟件開發包了,繼續以 java 為例

sdk install

回看 sdkman help 命令的輸出,使用 install 命令,我們再安裝一個 Java 最新 13.0.1.j9 版本

從上圖你可以看出,綠色標記的內容是 list 命令結果中的 version 值,但是報錯不可用,輸入indentifier 編號才能正常下載,這裏需要注意

安裝完后,status 就會編程 installed 狀態

sdk current

當安裝多個版本的 java 時,我們輸入下面命令獲取當前正在用 candidate 的版本

$ sdk current java

sdk use

了解了當前使用版本,如果我們想切換到其他版本, 可以輸入:

$ sdk use java 12.0.2.j9-adpt

注意️: 這裏同樣是指定的 indentifier 的值

sdk default

如果我們想指定某個版本為默認版本,可以輸入:

$ sdk default java jdk1.8.0_162.jdk

注意️: 這裏同樣是指定的 indentifier 的值

sdk uninstall

當我們想卸載某個版本可以輸入:

$ sdk uninstall java 12.0.2.j9-adpt

注意️: 這裏同樣是指定的 indentifier 的值

sdk upgrade

如果我們想升級某個 candidate,可以輸入:

$ sdk upgrade java

sdk flush

使用 sdkman 時間變長也會慢慢產生很多緩存內容,我們可以輸入
清理廣播消息:

$ sdk flush broadcast

清理下載的 sdk 二進制文件(長時間使用后清理,可以節省出很多空間):

$ sdk flush archives

清理臨時文件內容:

$ sdk flush temp

到這裏 sdkman 的基本使用就已經介紹完了,其實這些命令都不用急,想不起來的時候執行 sdk help 來臨時查看一下就好

sdkman 卸載

如果我們不喜歡 sdkman 了,我們也可以輕鬆的卸載掉它:

$ tar zcvf ~/sdkman-backup_$(date +%F-%kh%M).tar.gz -C ~/ .sdkman
$ rm -rf ~/.sdkman

最後打開你的 .bashrc、.bash_profile 和/或者 .profile,找到並刪除下面這幾行。

#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
[[ -s "/home/dudette/.sdkman/bin/sdkman-init.sh" ]] && source "/home/dudette/.sdkman/bin/sdkman-init.sh"

我用的 zshrc,找到 .zshrc 文件刪除掉上面內容即可

到這裏基於 Unix 系統的,有關 sdkman 的安裝,使用及下載都已經介紹完了,可以上手試一試了,相信很多小夥伴用的是 Windows,除了 jenv, sdkman 和 Jabba 都有 windows 用戶的解決方案:

sdkman windows 解決方案

在 sdkman 官網首頁同樣為 windows 用戶提供了解決方案,小夥伴們找到如下位置查看即可

我看了一下過程,也是很簡單,由於手頭沒有 windows 電腦,這個請小夥伴們自行嘗試吧,有問題歡迎留言

靈魂追問

  1. 你現在用的 Java 版本是多少?
  2. 有跟隨新版本嘗試更多新特性嗎?
  3. 你的燈還亮着嗎?

    歡迎持續關注公眾號:「日拱一兵」

    • 前沿 Java 技術乾貨分享
    • 高效工具匯總 | 回復「工具」
    • 面試問題分析與解答
    • 技術資料領取 | 回復「資料」

以讀偵探小說思維輕鬆趣味學習 Java 技術棧相關知識,本着將複雜問題簡單化,抽象問題具體化和圖形化原則逐步分解技術問題,技術持續更新,請持續關注……

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

【其他文章推薦】

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

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

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

※南投搬家前需注意的眉眉角角,別等搬了再說!

還看不懂同事的代碼?超強的 Stream 流操作姿勢還不學習一下

Java 8 新特性系列文章索引。

前言

我們都知道 Lambda 和 Stream 是 Java 8 的兩大亮點功能,在前面的文章里已經介紹過 Lambda 相關知識,這次介紹下 Java 8 的 Stream 流操作。它完全不同於 java.io 包的 Input/Output Stream ,也不是大數據實時處理的 Stream 流。這個 Stream 流操作是 Java 8 對集合操作功能的增強,專註於對集合的各種高效、便利、優雅的聚合操作。藉助於 Lambda 表達式,顯著的提高編程效率和可讀性。且 Stream 提供了并行計算模式,可以簡潔的編寫出并行代碼,能充分發揮如今計算機的多核處理優勢。

在使用 Stream 流操作之前你應該先了解 Lambda 相關知識,如果還不了解,可以參考之前文章: 。

1. Stream 流介紹

Stream 不同於其他集合框架,它也不是某種數據結構,也不會保存數據,但是它負責相關計算,使用起來更像一個高級的迭代器。在之前的迭代器中,我們只能先遍歷然後在執行業務操作,而現在只需要指定執行什麼操作, Stream 就會隱式的遍歷然後做出想要的操作。另外 Stream 和迭代器一樣的只能單向處理,如同奔騰長江之水一去而不復返。

由於 Stream 流提供了惰性計算和并行處理的能力,在使用并行計算方式時數據會被自動分解成多段然後并行處理,最後將結果匯總。所以 Stream 操作可以讓程序運行變得更加高效。

2. Stream 流概念

Stream 流的使用總是按照一定的步驟進行,可以抽象出下面的使用流程。

數據源(source) -> 數據處理/轉換(intermedia) -> 結果處理(terminal )

2.1. 數據源

數據源(source)也就是數據的來源,可以通過多種方式獲得 Stream 數據源,下面列舉幾種常見的獲取方式。

  • Collection.stream(); 從集合獲取流。
  • Collection.parallelStream(); 從集合獲取并行流。
  • Arrays.stream(T array) or Stream.of(); 從數組獲取流。
  • BufferedReader.lines(); 從輸入流中獲取流。
  • IntStream.of() ; 從靜態方法中獲取流。
  • Stream.generate(); 自己生成流

2.2. 數據處理

數據處理/轉換(intermedia)步驟可以有多個操作,這步也被稱為intermedia(中間操作)。在這個步驟中不管怎樣操作,它返回的都是一個新的流對象,原始數據不會發生任何改變,而且這個步驟是惰性計算處理的,也就是說只調用方法並不會開始處理,只有在真正的開始收集結果時,中間操作才會生效,而且如果遍歷沒有完成,想要的結果已經獲取到了(比如獲取第一個值),會停止遍歷,然後返回結果。惰性計算可以顯著提高運行效率。

數據處理演示。

@Test
public void streamDemo(){
    List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
    // 1. 篩選出名字長度為4的
    // 2. 名字前面拼接 This is
    // 3. 遍歷輸出
    nameList.stream()
            .filter(name -> name.length() == 4)
            .map(name -> "This is "+name)
            .forEach(name -> System.out.println(name));
}
// 輸出結果
// This is Jack
// This is Poul

數據處理/轉換操作自然不止是上面演示的過濾 filter 和 map映射兩種,另外還有 map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered 等。

2.3. 收集結果

結果處理(terminal )是流處理的最後一步,執行完這一步之後流會被徹底用盡,流也不能繼續操作了。也只有到了這個操作的時候,流的數據處理/轉換等中間過程才會開始計算,也就是上面所說的惰性計算。結果處理也必定是流操作的最後一步。

常見的結果處理操作有 forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator 等。

下面演示了簡單的結果處理的例子。

/**
 * 轉換成為大寫然後收集結果,遍歷輸出
 */
@Test
public void toUpperCaseDemo() {
    List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
    List<String> upperCaseNameList = nameList.stream()
            .map(String::toUpperCase)
            .collect(Collectors.toList());
    upperCaseNameList.forEach(name -> System.out.println(name + ","));
}
// 輸出結果
// DARCY,CHRIS,LINDA,SID,KIM,JACK,POUL,PETER,

2.4. short-circuiting

有一種 Stream 操作被稱作 short-circuiting ,它是指當 Stream 流無限大但是需要返回的 Stream 流是有限的時候,而又希望它能在有限的時間內計算出結果,那麼這個操作就被稱為short-circuiting。例如 findFirst 操作。

3. Stream 流使用

Stream 流在使用時候總是藉助於 Lambda 表達式進行操作,Stream 流的操作也有很多種方式,下面列舉的是常用的 11 種操作。

3.1. Stream 流獲取

獲取 Stream 的幾種方式在上面的 Stream 數據源里已經介紹過了,下面是針對上面介紹的幾種獲取 Stream 流的使用示例。

@Test
public void createStream() throws FileNotFoundException {
    List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
    String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"};
    // 集合獲取 Stream 流
    Stream<String> nameListStream = nameList.stream();
    // 集合獲取并行 Stream 流
    Stream<String> nameListStream2 = nameList.parallelStream();
    // 數組獲取 Stream 流
    Stream<String> nameArrStream = Stream.of(nameArr);
    // 數組獲取 Stream 流
    Stream<String> nameArrStream1 = Arrays.stream(nameArr);
    // 文件流獲取 Stream 流
    BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
    Stream<String> linesStream = bufferedReader.lines();
    // 從靜態方法獲取流操作
    IntStream rangeStream = IntStream.range(1, 10);
    rangeStream.limit(10).forEach(num -> System.out.print(num+","));
    System.out.println();
    IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
    intStream.forEach(num -> System.out.print(num+","));
}

3.2. forEach

forEach 是 Strean 流中的一個重要方法,用於遍歷 Stream 流,它支持傳入一個標準的 Lambda 表達式。但是它的遍歷不能通過 return/break 進行終止。同時它也是一個 terminal 操作,執行之後 Stream 流中的數據會被消費掉。

如輸出對象。

List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numberList.stream().forEach(number -> System.out.println(number+","));
// 輸出結果
// 1,2,3,4,5,6,7,8,9,

3.3. map / flatMap

使用 map 把對象一對一映射成另一種對象或者形式。

/**
 * 把数字值乘以2
 */
@Test
public void mapTest() {
    List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    // 映射成 2倍数字
    List<Integer> collect = numberList.stream()
            .map(number -> number * 2)
            .collect(Collectors.toList());
    collect.forEach(number -> System.out.print(number + ","));
    System.out.println();

    numberList.stream()
            .map(number -> "数字 " + number + ",")
            .forEach(number -> System.out.println(number));
}
// 輸出結果
// 2,4,6,8,10,12,14,16,18,
// 数字 1,数字 2,数字 3,数字 4,数字 5,数字 6,数字 7,数字 8,数字 9,

上面的 map 可以把數據進行一對一的映射,而有些時候關係可能不止 1對 1那麼簡單,可能會有1對多。這時可以使用 flatMap。下面演示使用 flatMap把對象扁平化展開。

/**
 * flatmap把對象扁平化
 */
@Test
public void flatMapTest() {
    Stream<List<Integer>> inputStream = Stream.of(
            Arrays.asList(1),
            Arrays.asList(2, 3),
            Arrays.asList(4, 5, 6)
    );
    List<Integer> collect = inputStream
            .flatMap((childList) -> childList.stream())
            .collect(Collectors.toList());
    collect.forEach(number -> System.out.print(number + ","));
}
// 輸出結果
// 1,2,3,4,5,6,

3.4. filter

使用 filter 進行數據篩選,挑選出想要的元素,下面的例子演示怎麼挑選出偶數数字。

/**
 * filter 數據篩選
 * 篩選出偶數数字
 */
@Test
public void filterTest() {
    List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    List<Integer> collect = numberList.stream()
            .filter(number -> number % 2 == 0)
            .collect(Collectors.toList());
    collect.forEach(number -> System.out.print(number + ","));
}

得到如下結果。

2,4,6,8,

3.5. findFirst

findFirst 可以查找出 Stream 流中的第一個元素,它返回的是一個 Optional 類型,如果還不知道 Optional 類的用處,可以參考之前文章 。

/**
 * 查找第一個數據
 * 返回的是一個 Optional 對象
 */
@Test
public void findFirstTest(){
    List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    Optional<Integer> firstNumber = numberList.stream()
            .findFirst();
    System.out.println(firstNumber.orElse(-1));
}
// 輸出結果
// 1

findFirst 方法在查找到需要的數據之後就會返回不再遍歷數據了,也因此 findFirst 方法可以對有無限數據的 Stream 流進行操作,也可以說 findFirst 是一個 short-circuiting 操作。

3.6. collect / toArray

Stream 流可以輕鬆的轉換為其他結構,下面是幾種常見的示例。

 /**
 * Stream 轉換為其他數據結構
 */
@Test
public void collectTest() {
    List<Integer> numberList = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5);
    // to array
    Integer[] toArray = numberList.stream()
            .toArray(Integer[]::new);
    // to List
    List<Integer> integerList = numberList.stream()
            .collect(Collectors.toList());
    // to set
    Set<Integer> integerSet = numberList.stream()
            .collect(Collectors.toSet());
    System.out.println(integerSet);
    // to string
    String toString = numberList.stream()
            .map(number -> String.valueOf(number))
            .collect(Collectors.joining()).toString();
    System.out.println(toString);
    // to string split by ,
    String toStringbJoin = numberList.stream()
            .map(number -> String.valueOf(number))
            .collect(Collectors.joining(",")).toString();
    System.out.println(toStringbJoin);
}
// 輸出結果
// [1, 2, 3, 4, 5]
// 112233445
// 1,1,2,2,3,3,4,4,5

3.7. limit / skip

獲取或者扔掉前 n 個元素

/**
 * 獲取 / 扔掉前 n 個元素
 */
@Test
public void limitOrSkipTest() {
    // 生成自己的隨機數流
    List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
    ageList.stream()
            .limit(3)
            .forEach(age -> System.out.print(age+","));
    System.out.println();
    
    ageList.stream()
            .skip(3)
            .forEach(age -> System.out.print(age+","));
}
// 輸出結果
// 11,22,13,
// 14,25,26,

3.8. Statistics

數學統計功能,求一組數組的最大值、最小值、個數、數據和、平均數等。

/**
 * 數學計算測試
 */
@Test
public void mathTest() {
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
    IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics();
    System.out.println("最小值:" + stats.getMin());
    System.out.println("最大值:" + stats.getMax());
    System.out.println("個數:" + stats.getCount());
    System.out.println("和:" + stats.getSum());
    System.out.println("平均數:" + stats.getAverage());
}
// 輸出結果
// 最小值:1
// 最大值:6
// 個數:6
// 和:21
// 平均數:3.5

3.9. groupingBy

分組聚合功能,和數據庫的 Group by 的功能一致。

/**
 * groupingBy
 * 按年齡分組
 */
@Test
public void groupByTest() {
    List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
    Map<String, List<Integer>> ageGrouyByMap = ageList.stream()            
        .collect(Collectors.groupingBy(age -> String.valueOf(age / 10)));
    ageGrouyByMap.forEach((k, v) -> {
        System.out.println("年齡" + k + "0多歲的有:" + v);
    });
}
// 輸出結果
// 年齡10多歲的有:[11, 13, 14]
// 年齡20多歲的有:[22, 25, 26]

3.10. partitioningBy

/**
 * partitioningBy
 * 按某個條件分組
 * 給一組年齡,分出成年人和未成年人
 */
public void partitioningByTest() {
    List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
    Map<Boolean, List<Integer>> ageMap = ageList.stream()
            .collect(Collectors.partitioningBy(age -> age > 18));
    System.out.println("未成年人:" + ageMap.get(false));
    System.out.println("成年人:" + ageMap.get(true));
}
// 輸出結果
// 未成年人:[11, 13, 14]
// 成年人:[22, 25, 26]

3.11. 進階 – 自己生成 Stream 流

/**
 * 生成自己的 Stream 流
 */
@Test
public void generateTest(){
    // 生成自己的隨機數流
    Random random = new Random();
    Stream<Integer> generateRandom = Stream.generate(random::nextInt);
    generateRandom.limit(5).forEach(System.out::println);
    // 生成自己的 UUID 流
    Stream<UUID> generate = Stream.generate(UUID::randomUUID);
    generate.limit(5).forEach(System.out::println);
}

// 輸出結果
// 793776932
// -2051545609
// -917435897
// 298077102
// -1626306315
// 31277974-841a-4ad0-a809-80ae105228bd
// f14918aa-2f94-4774-afcf-fba08250674c
// d86ccefe-1cd2-4eb4-bb0c-74858f2a7864
// 4905724b-1df5-48f4-9948-fa9c64c7e1c9
// 3af2a07f-0855-455f-a339-6e890e533ab3

上面的例子中 Stream 流是無限的,但是獲取到的結果是有限的,使用了 Limit 限制獲取的數量,所以這個操作也是 short-circuiting 操作。

4. Stream 流優點

4.1. 簡潔優雅

正確使用並且正確格式化的 Stream 流操作代碼不僅簡潔優雅,更讓人賞心悅目。下面對比下在使用 Stream 流和不使用 Stream 流時相同操作的編碼風格。

/**
 * 使用流操作和不使用流操作的編碼風格對比
 */
@Test
public void diffTest() {
    // 不使用流操作
    List<String> names = Arrays.asList("Jack", "Jill", "Nate", "Kara", "Kim", "Jullie", "Paul", "Peter");
    // 篩選出長度為4的名字
    List<String> subList = new ArrayList<>();
    for (String name : names) {
        if (name.length() == 4) {
            subList.add(name);
        }
    }
    // 把值用逗號分隔
    StringBuilder sbNames = new StringBuilder();
    for (int i = 0; i < subList.size() - 1; i++) {
        sbNames.append(subList.get(i));
        sbNames.append(", ");
    }
    // 去掉最後一個逗號
    if (subList.size() > 1) {
        sbNames.append(subList.get(subList.size() - 1));
    }
    System.out.println(sbNames);
}
// 輸出結果
// Jack, Jill, Nate, Kara, Paul

如果是使用 Stream 流操作。

// 使用 Stream 流操作
String nameString = names.stream()
       .filter(num -> num.length() == 4)
       .collect(Collectors.joining(", "));
System.out.println(nameString);

4.2. 惰性計算

上面有提到,數據處理/轉換(intermedia) 操作 map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered 等這些操作,在調用方法時並不會立即調用,而是在真正使用的時候才會生效,這樣可以讓操作延遲到真正需要使用的時刻。

下面會舉個例子演示這一點。

 /**
  * 找出偶數
  */
 @Test
 public void lazyTest() {
     // 生成自己的隨機數流
     List<Integer> numberLIst = Arrays.asList(1, 2, 3, 4, 5, 6);
     // 找出偶數
     Stream<Integer> integerStream = numberLIst.stream()
             .filter(number -> {
                 int temp = number % 2;
                 if (temp == 0 ){
                     System.out.println(number);
                 }
                 return temp == 0;
             });

     System.out.println("分割線");
     List<Integer> collect = integerStream.collect(Collectors.toList());
 }

如果沒有 惰性計算,那麼很明顯會先輸出偶數,然後輸出 分割線。而實際的效果是。

分割線
2
4
6

可見 惰性計算 把計算延遲到了真正需要的時候。

4.3. 并行計算

獲取 Stream 流時可以使用 parallelStream 方法代替 stream 方法以獲取并行處理流,并行處理可以充分的發揮多核優勢,而且不增加編碼的複雜性。

下面的代碼演示了生成一千萬個隨機數后,把每個隨機數乘以2然後求和時,串行計算和并行計算的耗時差異。

  /**
  * 并行計算
  */
 @Test
 public void main() {
     // 生成自己的隨機數流,取一千萬個隨機數
     Random random = new Random();
     Stream<Integer> generateRandom = Stream.generate(random::nextInt);
     List<Integer> numberList = generateRandom.limit(10000000).collect(Collectors.toList());

     // 串行 - 把一千萬個隨機數,每個隨機數 * 2 ,然後求和
     long start = System.currentTimeMillis();
     int sum = numberList.stream()
         .map(number -> number * 2)
         .mapToInt(x -> x)
         .sum();
     long end = System.currentTimeMillis();
     System.out.println("串行耗時:"+(end - start)+"ms,和是:"+sum);

     // 并行 - 把一千萬個隨機數,每個隨機數 * 2 ,然後求和
     start = System.currentTimeMillis();
     sum = numberList.parallelStream()
         .map(number -> number * 2)
         .mapToInt(x -> x)
         .sum();
     end = System.currentTimeMillis();
     System.out.println("并行耗時:"+(end - start)+"ms,和是:"+sum);
 }

得到如下輸出。

串行耗時:1005ms,和是:481385106
并行耗時:47ms,和是:481385106

效果顯而易見,代碼簡潔優雅。

5. Stream 流建議

5.1 保證正確排版

從上面的使用案例中,可以發現使用 Stream 流操作的代碼非常簡潔,而且可讀性更高。但是如果不正確的排版,那麼看起來將會很糟糕,比如下面的同樣功能的代碼例子,多幾層操作呢,是不是有些讓人頭大?

// 不排版
String string = names.stream().filter(num -> num.length() == 4).map(name -> name.toUpperCase()).collect(Collectors.joining(","));
// 排版
String string = names.stream()
        .filter(num -> num.length() == 4)
        .map(name -> name.toUpperCase())
        .collect(Collectors.joining(","));

5.1 保證函數純度

如果想要你的 Stream 流對於每次的相同操作的結果都是相同的話,那麼你必須保證 Lambda 表達式的純度,也就是下面亮點。

  • Lambda 中不會更改任何元素。
  • Lambda 中不依賴於任何可能更改的元素。

這兩點對於保證函數的冪等非常重要,不然你程序執行結果可能會變得難以預測,就像下面的例子。

@Test
public void simpleTest(){
    List<Integer> numbers = Arrays.asList(1, 2, 3);
    int[] factor = new int[] { 2 };
    Stream<Integer> stream = numbers.stream()
            .map(e -> e * factor[0]);
    factor[0] = 0;
    stream.forEach(System.out::println);
}
// 輸出結果
// 0
// 0
// 0

文中代碼都已經上傳到

。

個人網站:
如果你喜歡這篇文章,可以關注公眾號,一起成長。
關注公眾號回復資源可以沒有套路的獲取全網最火的的 Java 核心知識整理&面試資料。

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

暖冬導致「熊出沒」增加 日本9個月捕殺近5700隻熊創新高

摘錄自2020年2月19日星島日報報導

據日本共同社報道,2019年4至12月日本捕殺亞洲黑熊和棕熊的數目更創歷年新高,多達5,667隻,本年度尚未結束就已創下歷史新高。

據統計,日本自2007年度起,保持捕殺1,000至3,000多隻, 2018年度為3,446頭,但19年度尚未結束,已創下新高,較18年度增加39.1%。日本專家分析,可能與熊的分布地區擴大、食物減少有關。

報道又指,去年進入12月熊的冬眠期後,仍有逾200隻熊被捕殺,專家估計可能是因為天氣暖導致熊的冬眠期推遲,因而四處覓食。2019年度至12月底為止,「熊出沒」事故的受害人達155人,其中20人受傷。

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

馬斯克承認低油價不利電動車銷售,但稱特斯拉較不受影響

油價直直落,美國人大買耗油車,這股風潮豈不是對電動車相當不利?特斯拉(Tesla)執行長艾隆‧馬斯克(Elon Musk)於 2016 年 1 月底受邀前往香港 StartmeupHK 新創論壇(StartmeupHK Venture Forum)擔任演講來賓,在香港受 CNN 訪問時,承認低油價對整體電動車市場不利,但認為特斯拉將比其他電動車對手更不受影響。

馬斯克承認低油價對電動車的不利影響,表示這符合經濟常識。事實上,低油價已經使得 2015 年美國車市燒油較兇的貨卡以及休旅車大行其道,就更大的市場方向來說,油價的經濟考量,也顯然會對消費者在傳統燃油車、油電混合車,以及全電動車之間的選擇發生影響力。   不過馬斯克認為,特斯拉受到的影響將較其他電動車對手小,因為特斯拉將本身定位於高檔市場,因此其消費者購車時的經濟考量程度較輕,相對的,馬斯克認為以低價搶市的電動車對手,面對低油價讓燃油車更為經濟的情況,將會大受打擊,他表示,有些電動車和燃油車車款除了動力來源並沒有基本差異,如此一來,消費者只會比較經濟面,這樣的電動車對手將會在低油價下受到重大影響,但是馬斯克認為就算低油價讓燃油車更為經濟,特斯拉的 Model 3 仍然會表現良好。Model 3 是特斯拉較為大眾取向的車款,車價 3.4 萬美元,相當於約 114 萬元新台幣。   馬斯克也歡迎其他車廠共襄盛舉,一同推出更多電動車,可把餅做大,如通用汽車(GM)的雪佛蘭(Chevrolet)Bolt,馬斯克表示,若通用汽車或其他車廠開發出讓消費者滿意的電動車,對世界是好事,他會歡迎它們。   馬斯克也談及中國市場,表示中國電動車市場雖然只是剛開始起步,但正朝向正確的方向邁進,他表示有些中國公司,指巴菲特投資的比亞迪,正朝著製造出性能良好電動車的方向前進,進展快速。不過,特斯拉本身在中國市場表現並不理想,要如何在中國建立生產線,特斯拉還在嘗試中,而身為進口車,特斯拉要蒙受高額進口稅,且無法得到中國政府對電動車的補貼,因此受到相當大的阻礙,一旦能在中國本地生產,將對生意有相當大助益。   馬斯克認為中國政府政策將不可避免的往電動車傾斜,以減輕空氣污染與碳排放,中國政府也了解電動車對未來相當重要,想讓城市擁有潔淨空氣,就必須發展電動車。馬斯克認為 Model 3 終有一天會在中國生產,不過可能要 3 年才能辦得到這點。

(首圖來源:)    (本文授權轉載自《》─〈〉)

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

※小三通物流營運型態?

※快速運回,大陸空運推薦?

使用JaCoCo Maven插件創建代碼覆蓋率報告

這篇博客文章描述了我們如何使用JaCoCo Maven插件為單元和集成測試創建代碼覆蓋率報告。

我們的構建要求如下:

運行測試時,我們的構建必須為單元測試和集成測試創建代碼覆蓋率報告。
代碼覆蓋率報告必須在單獨的目錄中創建。換句話說,必須將用於單元測試的代碼覆蓋率報告創建到與用於集成測試的代碼覆蓋率報告不同的目錄中。
讓我們開始吧。

配置JaCoCo Maven插件

我們使用JaCoCo Maven插件有兩個目的:

  • 它使我們可以訪問JaCoCo運行時代理,該代理記錄了執行覆蓋率數據。
  • 它根據JaCo​​Co運行時代理記錄的執行數據創建代碼覆蓋率報告。
  • 我們可以按照以下步驟配置JaCoCo Maven插件:

將JaCoCo Maven插件添加到我們的POM文件的插件部分。

  • 為單元測試配置代碼覆蓋率報告。
  • 配置代碼覆蓋率報告以進行集成測試。
    下面將更詳細地描述這些步驟。

將JaCoCo Maven插件添加到POM文件

通過將以下插件聲明添加到其“ 插件”部分,我們可以將JaCoCo Maven插件添加到我們的POM文件中:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
</plugin>

配置單元測試的代碼覆蓋率報告

我們可以通過將兩個執行添加到插件聲明中來為單元測試配置代碼覆蓋率報告。這些執行方式如下所述:

  • 第一次執行將創建一個指向JaCoCo運行時代理的屬性。確保執行數據已寫入文件target / coverage-reports / jacoco-ut.exec。將該屬性的名稱設置為surefireArgLine。運行單元測試時,此屬性的值作為VM參數傳遞。
  • 運行單元測試后,第二次執行將為單元測試創建代碼覆蓋率報告。確保從文件target / coverage-reports / jacoco-ut.exec中讀取執行數據,並將代碼覆蓋率報告寫入目錄target / site / jacoco-ut中。

我們的插件配置的相關部分如下所示:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
    <executions>
        <!--
           Prepares the property pointing to the JaCoCo runtime agent which
           is passed as VM argument when Maven the Surefire plugin is executed.
       -->
        <execution>
            <id>pre-unit-test</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
                <!--
                   Sets the name of the property containing the settings
                   for JaCoCo runtime agent.
               -->
                <propertyName>surefireArgLine</propertyName>
            </configuration>
        </execution>
        <!--
           Ensures that the code coverage report for unit tests is created after
           unit tests have been run.
       -->
        <execution>
            <id>post-unit-test</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
                <!-- Sets the output directory for the code coverage report. -->
                <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

讓我們找出如何為集成測試配置代碼覆蓋率報告。

配置集成測試的代碼覆蓋率報告

我們可以通過在插件聲明中添加兩個執行來為集成測試配置代碼覆蓋率報告。這些執行方式如下所述:

  • 第一次執行將創建一個指向JaCoCo運行時代理的屬性。確保將執行數據寫入文件target / coverage-reports / jacoco-it.exec。將該屬性的名稱設置為failsafeArgLine。運行我們的集成測試時,此屬性的值作為VM參數傳遞。
  • 創建一個執行,該執行在集成測試運行後為集成測試創建代碼覆蓋率報告。確保從文件target / coverage-reports / jacoco-it.exec中讀取執行數據,並將代碼覆蓋率報告寫入目錄target / site / jacoco-it。

我們的插件配置的相關部分如下所示:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
    <executions>
        <!-- The Executions required by unit tests are omitted. -->
        <!--
           Prepares the property pointing to the JaCoCo runtime agent which
           is passed as VM argument when Maven the Failsafe plugin is executed.
       -->
        <execution>
            <id>pre-integration-test</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                <!--
                   Sets the name of the property containing the settings
                   for JaCoCo runtime agent.
               -->
                <propertyName>failsafeArgLine</propertyName>
            </configuration>
        </execution>
        <!--
           Ensures that the code coverage report for integration tests after
           integration tests have been run.
       -->
        <execution>
            <id>post-integration-test</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>report</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
                <!-- Sets the output directory for the code coverage report. -->
                <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

現在,我們已經配置了JaCoCo Maven插件。下一步是配置Maven Surefire插件。讓我們找出如何做到這一點。

配置Maven Surefire插件

我們使用Maven Surefire插件運行示例應用程序的單元測試。因為我們要為單元測試創​​建代碼覆蓋率報告,所以我們必須確保在運行單元測試時JaCoCo代理正在運行。我們可以通過添加的價值保證本surefireArgLine財產作為價值argLine配置參數。

Maven Surefire插件的配置如下所示(突出显示了所需的更改):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.15</version>
    <configuration>
        <!-- Sets the VM argument line used when unit tests are run. -->
        <argLine>${surefireArgLine}</argLine>
        <!-- Skips unit tests if the value of skip.unit.tests property is true -->
        <skipTests>${skip.unit.tests}</skipTests>
        <!-- Excludes integration tests when unit tests are run. -->
        <excludes>
            <exclude>**/IT*.java</exclude>
        </excludes>
    </configuration>
</plugin>

我們快完成了。剩下要做的就是配置Maven Failsafe插件。讓我們找出如何做到這一點。

配置Maven故障安全插件

我們的示例應用程序的集成測試由Maven Failsafe插件運行。因為我們要為集成測試創建代碼覆蓋率報告,所以我們必須確保在運行集成測試時JaCoCo代理正在運行。我們可以通過將failsafeArgLine屬性的值添加為argLine配置參數的值來實現。

Maven Failsafe插件的配置如下所示(突出显示了所需的更改):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.15</version>
    <executions>
        <!--
            Ensures that both integration-test and verify goals of the Failsafe Maven
            plugin are executed.
        -->
        <execution>
            <id>integration-tests</id>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
            <configuration>
                <!-- Sets the VM argument line used when integration tests are run. -->
                <argLine>${failsafeArgLine}</argLine>
                <!--
                    Skips integration tests if the value of skip.integration.tests property
                    is true
                -->
                <skipTests>${skip.integration.tests}</skipTests>
            </configuration>
        </execution>
    </executions>
</plugin>

創建代碼覆蓋率報告

現在,我們已成功完成所需的配置。讓我們看看如何為單元測試和集成測試創建代碼覆蓋率報告。

此博客文章的示例應用程序具有三個構建配置文件,下面對此進行了描述:

  • 在開發配置文件開發過程中使用,這是我們構建的默認配置文件。當此配置文件處於活動狀態時,僅運行單元測試。
  • 在集成測試配置文件用於運行集成測試。
  • 在所有的測試配置文件用於為運行單元測試和集成測試。
    我們可以通過在命令提示符處運行以下命令來創建不同的代碼覆蓋率報告:

  • 命令mvn clean test運行單元測試,併為目錄target / site / jacoco-ut創建單元測試的代碼覆蓋率報告。
  • 命令mvn clean verify -P integration-test運行集成測試,併為目錄target / site / jacoco-it創建用於集成測試的代碼覆蓋率報告。
  • 命令mvn clean verify -P all-tests運行單元測試和集成測試,併為單元測試和集成測試創建代碼覆蓋率報告。

技術類文章精選

非技術文章精選

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

※小三通物流營運型態?

※快速運回,大陸空運推薦?

Kubernetes概述

1. Kubernetes是什麼

Kubernetes是一個可移植的、可擴展的、用於管理容器化工作負載和服務的開源平台,它簡化(促進)了聲明式配置和自動化。它有一個龐大的、快速增長的生態系統。Kubernetes的服務、支持和工具隨處可見。

Kubernetes一詞源於希臘語,意為舵手或飛行員。2014年,谷歌開放了Kubernetes項目的源代碼。Kubernetes基於谷歌在大規模運行生產工作負載方面的15年經驗,以及來自社區的最佳想法和實踐。

使用 Kubernetes, 我們可以快速高效地響應客戶需求:

  • 快速、可預測地部署你的應用程序
  • 擁有即時擴展應用程序的能力
  • 不影響現有業務的情況下,無縫地發布新功能
  • 優化硬件資源,降低成本

Kubernetes的目標是構建一個軟件和工具的生態系統,以減輕你在公共雲或私有雲運行應用程序的負擔。

1.1. 時光倒流

讓我們把時間回溯到從前,看看為什麼Kubernetes是如此有用。

傳統部署時代:在早期,組織在物理服務器上運行應用程序。無法為物理服務器中的應用程序定義資源邊界,這導致了資源分配問題。例如,如果一個物理服務器上運行多個應用程序,那麼在某些情況下,一個應用程序將佔用大部分資源,從而導致其他應用程序性能下降。對此的解決方案是在不同的物理服務器上運行每個應用程序。但是,由於資源沒有得到充分利用,而且維護許多物理服務器的成本很高,所以無法進行擴展。

虛擬化部署時代:作為一種解決方案,引入了虛擬化。它允許你在單個物理服務器的CPU上運行多個虛擬機(vm)。虛擬化允許在vm之間隔離應用程序,並提供一定程度的安全性,因為一個應用程序的信息不能被另一個應用程序自由訪問。

虛擬化可以更好地利用物理服務器中的資源,並提供更好的可伸縮性,因為可以方便地添加或更新應用程序,從而降低硬件成本,等等。通過虛擬化,你可以將一組物理資源表示為一次性虛擬機集群。

每個VM是一個完整的機器,運行所有組件,包括它自己的操作系統,運行在虛擬硬件之上。

容器部署時代:容器類似於vm,但是它們具有寬鬆的隔離屬性,以便在應用程序之間共享操作系統(OS)。因此,容器被認為是輕量級的。與VM類似,容器有自己的文件系統、CPU、內存、進程空間等等。由於它們與底層基礎設施解耦,因此可以跨雲和OS發行版移植。

容器已經變得很流行,因為它們提供了額外的好處,比如:

  • 敏捷應用程序創建和部署:與使用VM鏡像相比,增加了容器鏡像創建的方便性和效率
  • 持續開發、集成和部署:提供可靠且頻繁的容器鏡像構建和部署,具有快速且輕鬆的回滾
  • 開發和運維關注點分離:在構建/發布時而不是部署時創建應用程序容器鏡像,從而將應用程序與基礎設施分離
  • 可觀察性:不僅能显示操作系統級的信息和指標,還能显示應用程序的健康狀況和其他信號
  • 跨開發、測試和生產的環境一致性:在筆記本電腦上運行與在雲上運行完全相同
  • 雲和操作系統發布的可移植性:運行在Ubuntu, RHEL, CoreOS, on-prem,谷歌Kubernetes引擎,和其他任何地方
  • 以應用程序為中心的管理:將抽象級別從在虛擬硬件上運行操作系統提高到使用邏輯資源在操作系統上運行應用程序
  • 鬆散耦合、分佈式、彈性、解放的微服務:應用程序被分解成更小的獨立部分,可以動態地部署和管理——而不是運行在一台大型單用途機器上的單片堆棧
  • 資源隔離:可預測的應用程序性能
  • 資源利用:效率高,密度大 

1.2. 為什麼需要Kubernetes?它能做什麼?

容器是捆綁和運行應用程序的好方法。在生產環境中,你需要管理運行應用程序的容器,並確保沒有停機時間。例如,如果一個容器發生故障,則需要啟動另一個容器。如果這個行為由一個系統來處理不是更容易嗎?

Kubernetes為你提供了一個能夠彈性地運行分佈式系統的框架。它負責處理應用程序的擴展和故障轉移,提供部署模式,等等。

Kubernetes為你提供:

服務發現和負載平衡

  Kubernetes可以使用DNS名稱或自己的IP地址公開容器。如果到容器的通信量很高,Kubernetes能夠實現負載平衡並分配網絡通信量,從而使部署保持穩定

存儲編排

  Kubernetes允許你自動掛載自己選擇的存儲系統,比如本地存儲、公有雲提供商等等

自動滾動更新和回滾

  可以使用Kubernetes描述所部署容器的期望狀態,並且可以以受控的速率將實際狀態更改為期望狀態

自動包裝

  你只需為Kubernetes提供一組節點,它便可以使用這些節點來運行容器化的任務。告訴Kubernetes每個容器需要多少CPU和內存(RAM)。Kubernetes可以在你的節點上放置容器,以充分利用你的資源。 

自動重啟 

  Kubernetes會重新啟動失敗的容器,替換容器,殺死不響應用戶定義的健康檢查的容器,並且在它們準備好服務之前不會將他們暴露給客戶端。

秘密和配置管理

  Kubernetes允許你存儲和管理敏感信息,比如密碼、OAuth令牌和ssh密鑰。你可以部署和更新秘密和應用程序配置,而無需重新構建容器映像,也無需在堆棧配置中公開秘密。 

1.3. Kubernetes不是什麼

Kubernetes不是一個傳統的、包羅萬象的PaaS(平台即服務)系統。由於Kubernetes是在容器級別而不是在硬件級別操作的,所以它提供了一些PaaS產品常見的通用特性,例如部署、擴展、負載平衡、日誌記錄和監視。但是,Kubernetes不是單片的,這些默認的解決方案是可選的和可插拔的。Kubernetes為構建開發人員平台提供了構建塊,但是在重要的地方保留了用戶的選擇和靈活性。

  • 不限制所支持的應用程序類型。Kubernetes的目標是支持非常多樣化的工作負載,包括無狀態、有狀態和數據處理工作負載。如果一個應用程序可以在容器中運行,那麼它應該可以在Kubernetes上運行。
  • 不部署源代碼,也不構建應用程序。持續集成、交付和部署(CI/CD)工作流由組織文化和偏好以及技術需求決定。
  • 不提供應用級服務,如中間件(例如消息總線)、數據處理框架(例如Spark)、數據庫(例如mysql)、緩存,也不提供集群存儲系統(例如Ceph)作為內置服務。這些組件可以運行在Kubernetes上,並且/或者可以由運行在Kubernetes上的應用程序通過可移植的機制(如Open Service Broker)訪問。
  • Kubernetes 允許用戶選擇其他的日誌記錄,監控和告警系統 
  • 不提供也不強制要求配置語言/系統(例如,jsonnet)。它提供了一個聲明性API,可以被任意形式的聲明性規範作為目標。
  • 不提供也不採用任何全面的機器配置、維護、管理或自修復系統。
  • 此外,Kubernetes不僅僅是一個編排系統。事實上,它消除了對編排的需要。編排的技術定義是執行一個已定義的工作流:首先執行a,然後執行B,然後執行c。相反,Kubernetes包括一套獨立、可組合的控制過程,通過聲明式語法使其連續地朝着期望狀態驅動當前狀態。你怎麼從A點到c點都不重要,只要告訴到C的狀態即可。 

2. Kubernetes組件

當你部署Kubernetes的時候,你會得到一個集群。

一個集群是一組機器,稱為節點(nodes),它們運行由Kubernetes管理的容器化應用程序。

一個集群至少有一個工作節點(worker node)和一個主節點(master node)。

工作節點承載應用程序的組件。主節點管理集群中的工作節點和pods。多個主節點用於提供具有故障轉移和高可用性的集群。

下面是Kubernetes集群的關係圖: 

2.1. Master組件

Master組件提供集群的控制面板。Master組件對集群做出全局決策(例如,調度),Master組件檢測並響應集群事件(例如,當部署的replicas字段不滿足時啟動一個新的pod)

Master組件可以在集群中的任何機器上運行。但是,為了簡單起見,設置腳本通常在同一台機器上啟動所有Master組件,並且不在這台機器上運行用戶容器。

kube-apiserver 

  API服務器是一個Kubernetes面板控制組件,用於公開Kubernetes API。它是Kubernetes控制面板的前端。

  Kubernetes API服務器的主要實現是kube-apiserver。kube-apiserver被設計成水平伸縮——也就是說,它通過部署更多實例來伸縮。你可以運行kube-apiserver的多個實例,並在這些實例之間平衡流量。

etcd 

  一致性和高可用的鍵值存儲用作Kubernetes的所有集群數據備份存儲。

  如果你的Kubernetes集群使用etcd作為其備份存儲,請確保對這些數據有備份計劃。

kube-scheduler

  監視沒有分配節點的新創建的pod,併為它們選擇要運行的節點。 

kube-controller-manager

  運行控制器的組件,從邏輯上講,每個控制器都是一個單獨的進程,但是為了降低複雜性,它們都被編譯成一個單一的二進制文件,並在一個進程中運行。

這些控制器包括:

  • Node Controller:節點控制器負責發現和響應節點故障
  • Replication Controller:副本控制器負責為系統中的每個副本控制器對象維護正確的pod數量
  • Endpoints Controller:端點控制器填充端點對象(即,連接服務和pod)
  • Service Account & Token Controllers:為新的名稱空間創建默認帳戶和API訪問令牌 

cloud-controller-manager 

  雲控制器-管理器,運行與底層雲提供商交互的控制器

2.2. Node組件

Node組件在每個節點上運行,維護運行的pods並提供Kubernetes運行時環境。 

kubelet

  kubelet是一個代理,它運行在集群中的每個節點上,它確保容器在一個pod中運行。kubelet只管理由Kubernetes創建的容器。 

kube-proxy

  kube-proxy是運行在集群中每個節點上的網絡代理,是實現Kubernetes服務概念的一部分。

  kube-proxy維護節點上的網絡規則。這些網絡規則允許從集群內外的網絡會話與pod進行網絡通信。

  如果有可用的操作系統包過濾層,kube-proxy將使用它。否則,kube-proxy將轉發流量本身。

Container Runtime

  容器運行時是負責運行容器的軟件。

  Kubernetes支持多個容器運行時:Docker、containerd、crio、rktlet和Kubernetes CRI(容器運行時接口)的任何實現。 

2.3. Addons(插件)

DNS

  雖然其他插件不是嚴格要求的,但所有Kubernetes集群都應該有集群DNS,因為許多示例都依賴於它。

Web UI (Dashboard)

  Dashboard是一個通用的、基於web的Kubernetes集群用戶界面。它允許用戶管理和排除集群中運行的應用程序和集群本身的故障。

Container Resource Monitoring

  容器資源監控記錄中央數據庫中容器的一般時間序列指標,並提供用於瀏覽該數據的UI。

Cluster-level Logging

  集群級別的日誌記錄機制負責將容器日誌保存到具有搜索/瀏覽界面的中央日誌存儲中。

3. 回顧&小結

Kubernetes:

  • 可移植: 無論公有雲、私有雲、混合雲還是多雲架構都全面支持
  • 可擴展: 它是模塊化、可插拔、可掛載、可組合的,支持各種形式的擴展
  • 自修復: 它可以自保持應用狀態、可自重啟、自複製、自縮放的,通過聲明式語法提供了強大的自修復能力

Kubernetes建立在Google公司15年的運維經驗基礎之上,Google所有的應用都運行在容器上 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

※小三通物流營運型態?

※快速運回,大陸空運推薦?

2016 第二屆 亞太新能源汽車國際峰會

隨著全球能源危機的加重及汽車排放引起的環境問題日益得到世界各國的重視,智慧化,網聯化和電動化已成為未來全球汽車行業發展的必然趨勢。汽車行業是能源、資源消耗較大的產業,同時汽車排放也是環境污染的重要原因。我國已經步入汽車生產和消費大國,節能、環保、低碳是我國汽車產業面臨的長期任務。

在此背景下,2016第二屆亞太新能源汽車國際峰會以 “助力智慧網聯電動交通”為主題,旨在為全球新能源汽車參與者打造一個瞭解中國新能源汽車發展現狀,商業模式和技術發展趨勢的前瞻性產業交流平臺。

會議日程:

會議首日(2016.06.02; 星期四)
上午:新能源汽車產業政策及發展趨勢
下午:新能源汽車動力電池及動力總成技術

會議次日(2016.06.03; 星期五)
上午:整車集成,汽車電子及充電解決方案
下午:先進智慧網聯及輕量化技術助力電動交通戰略

更多關於2016ANEVS的資訊,請登錄會議官方網站:

組委會聯繫方式:
連絡人:Fiona Hu           
電  話:021-58560121
郵  箱:

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

【其他文章推薦】

※想知道網站建置、網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計及後台網頁設計

※不管是台北網頁設計公司、台中網頁設計公司,全省皆有專員為您服務

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

※帶您來看台北網站建置,台北網頁設計,各種案例分享

※小三通物流營運型態?

※快速運回,大陸空運推薦?