特斯拉鋰電池價格將降至US$ 125/kWh

Tesla Motors有超過50萬筆Model 3之訂單,為了讓這些訂單準時出貨,Tesla創辦人Elon Musk表示,占地1,500萬平方英尺、專用來生產Tesla電動車用鋰電池的超級工廠Gigafactory進度已超前預定進度兩年。而Gigafactory存在的原因很簡單,即是為了降低鋰電池的生產成本。

據網站Electrek報導,近期研究顯示,電動車鋰電池近6年來已降至每kWh 227美金,下降80%。即便如此,電動車高昂的價格仍令人難以負擔。

降低鋰電池成本一直為Tesla改善的目標之一。在新的宣傳影片裡,Tesla 表示將降低35% 的電池成本。 雖然Tesla 並沒有詳述電池成本下降的細節,但若從釋出的消息中,多少可以拼湊出一些樣貌。

從Tesla於2016年說的「低於每kWh 190美金」,套上降低電池成本35%,電池成本將會來到每kWh 124美金之下。假設一輛Model 3 需要55 kWh之電池,那麼電池成本最多為6,875美金。鋰電池看來似乎是生產成本裡最高的組件,但以一輛3.5 萬美元的電動車來說,評估下來似乎合理。

以Tesla自有品牌家用儲能系統Powerwall來說,規格14 kWh的售價為5,500美金;大型發電設備用的Powerpack、規格210 kWh/供電4小時的售價則為109,750美金。

若要使電動車和燃油車具成本競爭力,電動車之電池成本至少需降至每kWh 100 美金以內。Elon Musk 一度對於Tesla Motors無法在2020達到這個里程碑而失望。但以現階段狀況看來,於內華達州之Gigafactory 1 完成進度已達14%,即將於歐洲設廠之Gigafactory 2也已進行籌備階段,降低鋰點池生產成本的目標看很有機會達成。        

(首圖為Gigafactory。來源:Tesla)                       

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

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案

Tesla樽節,2016年 SolarCity裁員人數達 20%

根據《路透社》的報導指出,美國電動車大廠特斯拉(TESLA) 在 2016  年底所收購的太陽能電池廠商 SolarCity,截至 2016 年底為止,總計已經裁減了 20% 的員工。顯示 TESLA 需要藉由 SolarCity 的樽節措施,來平衡該公司的支出。原因是當前美國太陽能市場,依舊處於需求不足的低迷狀態。

報導指出,根據 SolarCity 在 1 日對美國證券交易委員會提交的相關文件指出,該公司截至 2016 年底的員工總數為 12,243 人,比一年前減少了 19.8%。而在被 TESLA 收購前,營運就出現困難的 SolarCity 已經提出相關裁員計畫,預計裁減包括運營、安裝、製造、銷售和市場行銷等部門職位,只是當時並沒有提出確切人數。據了解,在進入 2017 年後,裁員仍將會持續。

SolarCity 過去是全美最大的屋頂太陽能系統製造和安裝公司。按照過去的計畫,SolarCity 曾希望在 2018 年獲得美國一百萬太陽能家庭用戶,但是後來縮減了目標,主要原因是市場需求不足。2017 年初,由於內華達州一項太陽能補助政策取消,使 SolarCity 裁減該州 550 個工作職位。整體來說,2016 年 SolarCity 在業務上的衰退和過去快速擴張的情況形成鮮明對比,因 2015 年同期統計,該公司的員工人數較前一年成長了 68.7%。

事實上,TESLA 執行長 Elon Musk 當時併購 SolarCity 就引來許多負面聲音。原因是 Elon Musk 與 SolarCity 關係非淺,SolarCity 的創辦人為 Elon Musk 的親戚。所以該項收購案遭質疑是「左口袋到右口袋」的資本金錢遊戲。

為了改善 SolarCity 的財務狀況,Elon Musk 收購完成之後,TESLA 開始對 SolarCity 的業務進行整合。2017 年 1 月,TESLA 表示將會縮減太陽能系統的廣告預算,並且利用特斯拉現有的實體店零售網路,銷售屋頂太陽能發電系統。另外,SolarCity 也將縮減租賃等模式,轉向現金銷售,以便獲得更多現金收入,達到降低成本的效果。

(合作媒體:。圖片出處:Tesla)

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

【其他文章推薦】

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

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

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

※超省錢租車方案

FB行銷專家,教你從零開始的技巧

Tesla於台灣發表休旅款 Model X,車門採鷹翼設計

特斯拉繼 1 月時在台舉行首批 Model S 交車典禮,今天在合作商 BellaVita 場地舉行休旅車款式 Model X 在台發表大會。Model X 定價新台幣4,043,000 元,最多可乘載7 人。

Model X 依據電池容量和性能分為 4 個版本,共有 75D、90D、100D、P100D,各配備75、90、100 kWh 電池,其中 P100D 的加速性能最好,從靜止到百公里只要花3.1 秒。而在內裝上面,分為三種乘載版本:5 人座、6 人座、7 人座。

▲ 特斯拉Model X 的不同版本和座位內裝。

 

至於電動車最重要的智慧成分,除了駕駛座前的面版顯示時速、油耗等訊息,車前有3 個鏡頭,車後也有 1 個鏡頭,並且能與 Autopilot 自動輔助駕駛配合,增加更多攝影鏡頭輔助駕駛抵達目的地。

▲Model X 的車門採鷹翼門設計,車門兩側只要留下1 英尺(約30 公分)寬的空間,就能順利進入車子。

 

特斯拉的休旅車適應全球各地的狀況,像是在香港和台灣地狹人稠,Model X 採上掀式的車門設計鷹翼門,是兩段式的車門設計,先往上升,再向外展開,不用怕停車空間狹小。Model X 電動車省掉內燃機,讓房車設計上給予乘坐者更多空間,像是要上車不必彎下腰才能上車,車體高度相當高,直接可以站立走進去。

 

▲ 特斯拉全球副總裁、亞太區總裁任宇翔示範直接走進Model X 車裡。

 

特斯拉除了 Model S、Model X 等車款在台陸續運購或交車之外,充電服務網也陸續在全台各地設點。這次 Model X 發表大會選在 BellaVita,BellaVita 的停車場也有提供特斯拉車子所需要的充電站,讓來BellaVita 逛街的人要離開時,車子已經充電完了,能順利開回家。

▲Model X 內裝,可看到駕駛座的儀表板。

 

保養方面,特斯拉建議每年或是里程累積達 20,000 公里時進行年度保養,另外在訂購特斯拉車時可選擇預付3 年或4 年期的「保養計畫」。特斯拉在台北跟台中有授權的鈑噴中心,未來也會陸續認證合作商提供維修服務。原先做為保養服務據點的內湖園區,特斯拉全球副總裁、亞太區總裁任宇翔透露特斯拉在台總部也將進駐內湖。

▲5 人座的Model X。

 

另外定價較低,號稱是百萬平價車款的 Model 3 也可以在官網預購。

(合作媒體:。圖片出處:科技新報)

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

【其他文章推薦】

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

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

※超省錢租車方案

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

網頁設計最專業,超強功能平台可客製化

剛果廠2018年重新上線,鋰電池材料鈷價恐直落

車用鋰電池的關鍵材料──鈷在需求增溫、供給短缺的帶動下,年初迄今報價已狂飆135%,但認為鈷價可能漲到外太空的避險基金和投機客要小心了,因為剛果的礦脈2018年將開出大量產能,屆時供需景況驟變、原本飛龍在天的鈷價恐墜回地球。

英國金融時報14日報導,全球最大鈷生產商嘉能可(Glencore Plc)位於剛果共和國的加丹加(Katanga)礦場,在花費4.3億美元整治機台後,明年就可上線產鈷,預計市場將因此增加最多22,000公噸的供應量。目前鈷的全球年產量約在100,000公噸左右。

高盛分析師指出,加丹加礦場重新上線,將明顯改變供需狀態、終結短缺,預計鈷的供給量到了2019年底,都能充分滿足需求。

鈷是銅和鎳的副產品。原物料價格於2015年底慘崩之際,數個銅礦和鎳礦都被迫縮減產能,而嘉能可也在市況最為嚴峻的時候決定暫時封閉加丹加礦場。巴西礦商Votorantim Metais則跟著在2016年初暫停了鎳、鈷的生產線。

不過,中國預定要在2020年讓500萬輛電動車上路,特斯拉(Tesla Motors)首款平價電動車接單接到手軟,卻讓車用電池的需求水漲船高。根據倫敦原物料顧問機構CRU分析師Edward Spencer的數據,高級鈷的報價已拉高至每磅27美元。

看準這個趨勢,業界開始有消息傳出,括瑞士專門關注採礦業的創投機構Pala Investments,以及中國大型原物料基金上海混沌投資(Shanghai Chaos Investment)在內的六家機構,因看好電動車業者的需求,至今已囤積了約6,000公噸的鈷,價值多達2.8億美元,相當於去年全球總產量的17%。(註:混沌投資的控股股東是被稱為「中國索羅斯」的葛衛東。)()

路透社2月14日報導,根據電池用鈷鹽製造商eCobalt Solutions的預估,到了2020年,75%的鋰電池都將含有鈷,因為鈷能增加電動車每一次充電的里程數。

 

不過,由於98%的鈷都是銅、鎳礦的副產品,因此投資人很難買到純粹的鈷。歐洲一名交易員透露,私募股權基金業者雖然考慮過倫敦金屬交易所(LME)的鈷合約,但流動性卻不足,難以滿足投資機構的龐大需求。因此,許多基金公司決定直接囤積鈷、靜待價格上漲,設定的目標價則是每磅25美元,甚至更多。

(本文內容由授權使用。圖片出處:Wikipedia)

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

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

和Tesla抗衡,Volvo平價電動車預計2019上市

瑞典汽車大廠Volvo(富豪汽車)的CEO Lex Kerssemakers在日內瓦汽車展上向記者透漏公司將於2019上市自家電動車,價格約落在$35,000至$40,000美元間。

據媒體Automotive News報導,在這之前,Volvo雖有兩款油電混和車XC90 SUV和V60上市,但不曾真正推出過純電動車。Volvo定出的價格也和電動車龍頭Tesla旗下車款Model 3具競爭力。預定於2017年末上市的Tesla Model 3擁有215英哩的續航,優惠期間可以35,000的價格預購;Chevrolet(雪佛蘭汽車)的電動車Bolt則擁有238英哩的續航里程,優惠價格落在37,500美元。

雖然車體尺寸等具體資訊都還沒有公布,但Kerssemakers表示續航力可達250英哩。外界也推估以這個價位大概是一般轎車而緊湊型轎車(Compact Car)或休旅車。

(首圖來源:Volvo)

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

FB行銷專家,教你從零開始的技巧

docker鏡像瘦身思路

docker鏡像瘦身思路

一、簡介

      docker鏡像太大,帶來了以下幾個問題:

  • 存儲開銷

      這塊影響其實不算很大,因為對服務器磁盤來說,15GB的存儲空間並不算大,除非用戶服務器的磁盤空間很緊張

  • 部署時間

      這塊影響真的很大,交付件zip包太大,導致用戶部署該產品時,花費的時間變長,客戶現場中反饋部署時間超過1.5小時,這嚴重影響用戶的體驗,降低滿意度

  • 性能不穩定

      如果客戶的服務器規格不夠(特別是磁盤讀寫性能不夠),會增大部署失敗的概率。

二、瘦身思路

       以下思路是我在該任務中嘗試使用用於鏡像瘦身的方法,均可以不同程度的降低DOcker鏡像的尺寸。

  • 清理Docker鏡像中的無用安裝包

      在Dockerfile構建Docker鏡像過程中,有可能引入臨時文件,比如:安裝包i、文件壓縮包。這些臨時文件忘記清理,導致佔據了一定的尺寸,有必要對其進行清理。

        如下Dockerfile:   

FROM xxxx/xxxx-jdk:1.0.0RUN apt-get update && apt-get install -y git maven 
mysql-client nodejs nodejs-legacy python-pip graphviz npm unzip  

Dockerfile裏面經常安裝很多工具,安裝完后,需要及時刪除安裝包緩存

(alpine) apk del openssh vim:刪除包及其依賴包

(Ubuntu) Apt-get clean:刪除所有已下載的包文件

(centos) Yum clean all: yum 會把下載的軟件包和header存儲在cache中,而不自動刪除。如果覺得佔用磁盤空間,可以使用yum clean指令進行清除,更精確 的用法是yum clean headers清除header,yum clean packages清除下載的rpm包,yum clean all一全部清除

      上面的dockerfile中在安裝工具后應該執行下: && apt-get clean && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y git maven 
    mysql-client nodejs nodejs-legacy python-pip graphviz npm unzip && apt-get clean && rm -rf /var/lib/apt/lists/*

 

   實例:

      

FROM centos:7
RUN yum update -y RUN yum install -y wget unzip socat java-1.8.0-openjdk-headless
# Set permissions
RUN yum clean all
EXPOSE 8486

 

   修改:將黃色標示的部分改寫成如下,大小從691Mb下降到583Mb

RUN yum update -y  && yum install -y wget unzip socat java-1.8.0-openjdk-headless && yum clean all
  • 避免不必要的工具安裝

     有的Dockerfile中安裝了很多工具,這個工具的加在一起尺寸比較大,這塊需要挨個排查:客戶環境下,需不需要安裝該工具?很多工具其實是面向開發使用的,而用戶根本不會使用,那麼就沒有必要在客戶環境上使用安裝這麼工具的鏡像,應該仔細排除工具的必要性,會給鏡像瘦身帶來比較大的收益。比如, dockerfile中安裝了JDK。 這個有些情況下,完全沒必要,實際上可能jre就能搞定。

     總之,能不安裝,就不安裝;能少安裝,就少安裝;能用輕量級的工具,盡量用輕量級的工具!!!

  • 多階段構建

      Docker多階段構建是17.05以後引入的新特性,旨在解決編譯、構建複雜和鏡像大小的問題。對於多階段構建,可以在Dockerfile中使用多個FROM語句。每個FROM指令可以使用不同的基礎,並且每個指令都開始一個新的構建。您可以選擇性地將工件從一個階段複製到另一個階段,從而在最終image中只留下您想要的內容。

      如下圖所示為多階段構建的使用示例:

把多個Dockerfile合併在一塊,每個Dockerfile單獨作為一個“階段”,“階段”之間可以互相聯繫,讓后一個階段構建可以使用前一個階段構建的產物,形成一條構建階段的chain,最終結果僅產生一個image,避免產生冗餘的多個臨時images或臨時容器對象。

       1)多階段構建使用之前

      針對多階段構建的特點,分析我們產品裏面的dockerfile,如下面所示,該操作的目的是將tar包拷貝值容器內的路徑下,並解壓、執行後續操作。然而COPY層具有一定的大小,只起到臨時層的作用。(特別是這個tar包足足幾百MB!)。

 

FROM xxxx:${project.version}COPY karaf-${ccsdk.opendaylight.version}.tar.gz /tmp/
RUN mkdir /opt/opendaylight \
      && tar zxvf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz --directory /opt/opendaylight \&& rm -rf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz \ 
      && mv /opt/opendaylight/karaf-${ccsdk.opendaylight.version} /opt/opendaylight/current && mkdir -p  /opt/opendaylight/current  && ln -s  /opt/opendaylight/current /opt/opendaylight/karaf-${ccsdk.opendaylight.version}
RUN mkdir -p /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
COPY mariadb-java-client-${ccsdk.mariadb-connector-java.version}.jar /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
EXPOSE 8181   

     2)  使用多階段構建

       使用多階段構建,修改后的dockerfile如下圖所示,修改實現將第一階段拷貝並解壓好的文件複製過來即可,少了拷貝tar包的環節,這樣使得最終形成的鏡像中鏡像層數得到有效的降低,也一定程度上降低了鏡像尺寸。

FROM xxxx:${project.version} as baseFirst
COPY karaf-${ccsdk.opendaylight.version}.tar.gz /tmp/
RUN mkdir /opt/opendaylight \
      && tar zxvf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz --directory /opt/opendaylight \&& rm -rf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz \ 
      && mv /opt/opendaylight/karaf-${ccsdk.opendaylight.version} /opt/opendaylight/current 

FROM xxxxxe:${project.version} as baseSecondRUN mkdir -p  /opt/opendaylight/current  && ln -s  /opt/opendaylight/current /opt/opendaylight/karaf-${ccsdk.opendaylight.version}
COPY --from=baseFirst /opt/opendaylight/current  /opt/opendaylight/current
RUN mkdir -p /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
COPY mariadb-java-client-${ccsdk.mariadb-connector-java.version}.jar /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
EXPOSE 8181
  • Copy和賦權同時執行
FROM ubuntu:16.04
# Copy APIKeys
COPY ./messageservice/ /tmp/zookeeper/gerrit  ------A 
EXPOSE 2181 2888 3888
B------> RUN useradd $ZK_USER && [ `id -u $ZK_USER` -eq 1000 ] && [ `id -g $ZK_USER` -eq 1000 ] && chown -R $ZK_USER:$ZK_USER /opt/$ZK_DIST/ /opt/zookeeper/ /var/lib/ /var/log/ /tmp/zookeeper/    
USER $ZK_USER

      問題排查如下:A處copy的文件700MB太大,很多文件沒用到

                               B處給/tmp/zookeeper添加屬組和屬主,該層也很大

       修改:使用 COPY –chown=1000:1000   ./messageservice/ /tmp/zookeeper/gerrit, 鏡像大小從1.4GB 下降到700Mb

  • 鏡像層的復用

      這一塊修改得當的話,得到的收益是最大的!!!最大的!!!最大的!!!

      我們知道docker鏡像具有層級結構,如果很多鏡像具有相同的層,則這些相同的層就能得到復用(把多個鏡像生成一個tar),docker不會保存兩份相同放入層文件,通過提高層得復用能顯著降低整體的鏡像尺寸。比如常見方法有:替換統一的基礎鏡像、創建出統一的基礎鏡像、調整層的順序等等。這裏東西沒有整理,就不上圖了,可以自行腦補,查閱資料即可

我這邊經過這一步調整后,zip產品包從11.45GB下降到6.96GB

 

最終zip包從15GB下降到7GB

    

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

【其他文章推薦】

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

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

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

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

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

網頁設計最專業,超強功能平台可客製化

004.OpenShift命令及故障排查

一 CLI訪問OpenShift資源

1.1 資源操作


OCP將OpenShift集群中的為由主節點管理的對象統稱為資源,如:node、service、pod、project、deployment、user。

即使針對的是不同的資源,OpenShift命令行工具也提供了一種統一的、一致的方法來更新、修改、刪除和查詢這些資源。

oc命令行工具提供了在軟件開發項目的整個交付生命周期中修改和管理資源的常見操作。

1.2 安裝oc工具


在OpenShift安裝過程中,oc命令行工具安裝在所有master和node節點上,還可以在不屬於OpenShift集群的機器。

安裝后,可以使用用戶名和密碼對任何主節點通過身份驗證后執行相關命令。

根據使用的平台,安裝oc命令行工具有以下幾種方式:

yum安裝:在RHEL平台上,可通過以下命令安裝oc客戶端命令。

[user@host ~]$ sudo yum install atomic-openshift-clients

其它 Linux 發行版本和操作系統,需在擁有 OpenShift 訂閱后,在 Red Hat Customer Portal 中下載。

提示:oc安裝完成后自動補全需要退出一次才可生效,或者source /etc/bash_completion.d/oc。

1.3 oc主要查詢命令


[student@workstation ~]$ oc –help #显示幫助信息

[student@workstation ~]$ oc login -u developer -p redhat https://master.lab.example.com #登錄到OpenShift集群

提示:從client成功通過身份驗證之後,OpenShift將授權令牌保存在用戶的主文件夾中。此令牌用於後續請求,從而無需重新輸入憑據或完整的主URL。

  1 [root@master ~]# oc whoami
  2 system:admin					#master的root用戶為集群的最高權限的用戶
  3 [student@workstation ~]$ oc whoami		        #查看當前用戶
  4 developer
  5 [student@workstation ~]$ oc new-project working	#創建project
  6 [student@workstation ~]$ oc status		        #查看項目狀態
  7 In project working on server https://master.lab.example.com:443
  8 You have no services, deployment configs, or build configs.
  9 Run 'oc new-app' to create an application.
 10 [student@workstation ~]$ oc delete project working	#刪除project
 11 [student@workstation ~]$ oc logout		        #退出該集群。
 12 [student@workstation ~]$ oc get pods		#查看pod
 13 NAME                      READY     STATUS    RESTARTS   AGE
 14 hello-openshift-1-6ls8z   1/1       Running   0          4h
 15 [student@workstation ~]$ oc get all		        #查看所有主要組件信息
 16 [student@workstation ~]$ oc get pods -w		#-w表示以監視模式運行


1.4 oc 其他命令


oc describe:如果oc get提供的摘要不夠,可以使用oc describe命令檢索關於資源的更詳細信息。

[student@workstation ~]$ oc describe pod hello-openshift-1-6ls8z

oc export:使用oc export命令導出資源的定義。典型的用例包括創建備份,或者用於修改定義。默認情況下,export命令以YAML格式輸出對象表示,但是可以通過提供-o選項來更改。

oc create:使用oc create命令從資源定義創建資源。通常,這與用於編輯定義的oc export命令相匹配。

oc delete RESOURCE_TYPE name:使用oc delete命令從OpenShift集群中刪除資源。

注意:部分資源直接刪除後會重新創建,如基於rc的pod,需要對OpenShift體系資源展示形式有一個基本的了解。

oc exec:使用oc exec命令在容器中執行命令,可以使用此命令作為腳本的一部分運行交互式和非交互式批處理命令。

oc rsh POD:oc rsh pod命令打開到容器的遠程shell會話,要遠程登錄到容器shell並執行命令,請運行以下命令。

[student@workstation ~]$ oc rsh <pod>

注意:oc rsh需要pod中存在相應的shell,如bash。

二 OpenShift資源類型

2.1 常見資源


OpenShift容器平台中的應用程序由不同類型的資源組成,主要常見的類型有:

  • Container:如何在可移植Linux環境中運行一個或多個進程的定義。容器從一個映像啟動,並且通常與同一機器上的其他容器隔離。
  • Image:一個分層的Linux文件系統,包含應用程序代碼、依賴關係和函數庫等。image由一個名稱標識,該名稱可以是當前集群的本地名稱,也可以指向遠程Docker倉庫。
  • Pod:部署在節點上並共享唯一IP地址和卷(持久存儲)的一個或多個容器,Pods還為每個容器定義安全性和運行時策略。
  • Label:標籤是鍵值對,可以分配給系統中的任何資源進行分組和選擇。通常資源使用標籤來標識其他資源集。
  • Volume:默認情況下容器不是持久性的,即容器的內容在重新啟動時被清除。volume是掛載在pod及其容器上的文件系統,它們可能由許多本地或網絡的存儲提供。最簡單的卷類型是EmptyDir,它是一台機器上的臨時目錄。
  • Node:node是集群中用來運行容器的節點,node通常由管理員管理,而不是由最終用戶管理。
  • Service:service是表示一組pod的邏輯名稱,service被分配一個IP地址和一個DNS名稱,可以通過端口或route向集群外部公開。名為SERVICE_HOST的環境變量會自動注入到其他pod中。
  • Route:route是一個DNS條目,創建它是為了指向一個service,以便可以從集群外部訪問它。可以配置一個或多個路由器來處理這些route,通常通過HAProxy負載均衡器。
  • Replication Controller:Replication Controller基於匹配一組label的Templates維護特定數量的pod。如果刪除了pod,控制器將創建該pod的新副本。Replication Controller最常用來表示基於image的應用程序部分的單個部署。
  • Deployment Configuration:deployment configuration定義pod的模板,並在屬性更改時管理部署新映像或配置更改。單個deployment configuration通常類似於單個微服務。deployment configuration可以支持許多不同的部署模式,包括完全重啟、可定製的滾動更新以及生命周期前後的順序。每個deployment都表示為一個replication controller。
  • Build Configuration:build configuration包含如何將源代碼和基本image構建為新image的描述。Build可以是基於源代碼的,可以為常見語言(如Java、PHP、Ruby或Python)或基於docker的(從Dockerfile創建構建)使用構建器映像。每個build configuration都有webhook,可以通過對其基本映像的更改自動觸發。
  • Build:構建從源代碼、其他圖像、Dockerfiles或二進制輸入創建新image。Build在容器中運行,具有與普通pod相同的限制。Build通常會導致將image推入Docker倉庫中,但也可以選擇運行post-build測試而不push到image倉庫。
  • Image Streams and Image Stream Tags:IS使用標記名稱對相關is進行分組。它類似於源代碼倉庫中的分支。每個is可以有一個或多個標記(默認標記稱為“latest”),這些標記可能指向外部Docker倉庫、同一is中的其他標記,或者被控製為直接指向已知image。此外,可以通過集成的Docker倉庫直接將image push到docker倉庫。
  • Secret:secret資源可以保存文本或二進制secrets,以便注入至pod。默認情況下,在/var/run/secrets/kubernetes.io/serviceaccount上,每個容器都有一個secret,其中包含訪問API有限特權的令牌。可以創建新的secret並將它們掛載到自己的pod中,也可以引用構建中的secret(用於連接遠程服務器),或者使用它們將遠程image導入到is中。
  • Project:所有上述資源(node除外)都存在於項目中。項目具有成員列表及其role(如view、edit或admin),以及運行的pod上的一組安全控制,並限制項目可以使用多少資源,資源名稱在項目中是惟一的。


使用oc types命令快速查看可用的概念和類型。

2.2 創建應用


簡單的應用程序、複雜的多層應用程序和微服務應用程序都可以使用資源定義文件來描述。

這個文件包含許多pod定義、連接這些pod的服務定義、用於水平伸縮應用程序pod的rc或dc、用於持久存儲應用程序數據的持久卷,以及OpenShift可以管理的任何其他需要的內容。

oc new-app命令可以使用-o json或-o yaml選項分別創建以json或yaml格式的定義文件的資源。可以使用oc create -f <filename>命令調用定義文件,並將其用於創建應用程序,或者與其他資源定義文件合併以創建複合應用程序。

oc new-app命令可以以許多不同的方式創建在OpenShift上運行的pod應用程序。它可以使用source-to-image (S2I)流程從現有docker映像、Dockerfiles或原始源代碼創建pod。

運行oc new-app -h命令,了解在OpenShift上創建新應用程序的所有不同選項。最常見的選項如下:

運行以下命令創建應用程序。OpenShift根據Docker配置文件的ADD_REGISTRY選項定義的倉庫 pull image。

$ oc new-app mysql MYSQL_USER=user MYSQL_PASSWORD=pass MYSQL_DATABASE=testdb -l

db=mysql

根據私有倉庫中的image創建應用程序。

$ oc new-app –docker-image=myregistry.com/mycompany/myapp –name=myapp

根據存儲在Git庫中的源代碼創建應用程序。

$ oc new-app https://github.com/openshift/ruby-hello-world –name=ruby-hello

創建基於存儲在Git庫中的源代碼並引用IS的應用程序。

$ oc new-app https://mygitrepo/php-hello -i php:7.0 –name=php-hello

從Docker配置文件的ADD_REGISTRY指令定義的可用倉庫之一創建一個基於mysql映像的應用程序。l db=mysql選項定義了一個值為mysql的db標籤。

$ oc new-app mysql MYSQL_USER=user \

MYSQL_PASSWORD=pass \

MYSQL_DATABASE=testdb \

-l db=mysql

下圖显示了oc new-app命令在參數為容器image時創建的Kubernetes和OpenShift資源。該命令創建dc、is和svc,可以通過端口或route從外部訪問。



提示:通過使用帶有源代碼的oc new-app,將創建一個build configuration,而bc又從源代碼創建一個新的應用程序。但是,如果命令中沒有使用源代碼,則不會創建gc。該命令始終為應用程序創建dc和svc。

三 oc使用練習

3.1 前置準備


準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

3.2 本練習準備


[student@workstation ~]$ lab manage-oc setup

3.3 驗證OpenShift

  1 [student@workstation ~]$ oc login -u admin -p redhat https://master.lab.example.com
  2 [student@workstation ~]$ oc project default
  3 Already on project "default" on server "https://master.lab.example.com:443".
  4 [student@workstation ~]$ oc project default
  5 Already on project "default" on server "https://master.lab.example.com:443".
  6 [student@workstation ~]$ oc get nodes
  7 NAME                     STATUS    ROLES     AGE       VERSION
  8 master.lab.example.com   Ready     master    23h       v1.9.1+a0ce1bc657
  9 node1.lab.example.com    Ready     compute   23h       v1.9.1+a0ce1bc657
 10 node2.lab.example.com    Ready     compute   23h       v1.9.1+a0ce1bc657
 11 [student@workstation ~]$ oc describe node master.lab.example.com		#查看master節點詳情
 12 [student@workstation ~]$ oc describe node node1.lab.example.com
 13 [student@workstation ~]$ oc describe node node2.lab.example.com
 14 [student@workstation ~]$ oc get pods -o wide
 15 NAME                       READY     STATUS    RESTARTS   AGE       IP              NODE
 16 docker-registry-1-8v7sh    1/1       Running   4          23h       10.129.0.30     node2.lab.example.com
 17 docker-registry-1-rrmhm    1/1       Running   2          23h       10.128.0.12     node1.lab.example.com
 18 registry-console-1-xzxxp   1/1       Running   4          23h       10.129.0.31     node2.lab.example.com
 19 router-1-fwttd             1/1       Running   4          23h       172.25.250.12   node2.lab.example.com
 20 router-1-xdw84             1/1       Running   2          23h       172.25.250.11   node1.lab.example.com
 21 [student@workstation ~]$ oc  describe pod docker-registry-1-8v7sh		#查看pod詳情


3.4 pod操作


[student@workstation ~]$ oc exec docker-registry-1-8v7sh hostname #執行pod中命令

docker-registry-1-8v7sh

[student@workstation ~]$ oc exec router-1-fwttd ls /

[student@workstation ~]$ oc exec docker-registry-1-8v7sh cat /etc/resolv.conf

提示:只要pod中存在的命令,都可以通過oc exec直接執行。

[student@workstation ~]$ oc rsh docker-registry-1-8v7sh #進入pod的shell

sh-4.2$ ls /

3.5 oc其他操作


[student@workstation ~]$ oc status -v #現實詳細的狀態



[student@workstation ~]$ oc get events #查看集群生命周期事件

[student@workstation ~]$ oc get all #獲取所有資源信息

3.6 導出資源


[student@workstation ~]$ oc export pod docker-registry-1-8v7sh

提示:oc export命令通常用於導出現有資源,並將它們轉換為配置文件(YAML或JSON),以便備份或在集群的其他地方重新創建資源。

[student@workstation ~]$ oc export svc,dc docker-registry –as-template=docker-registry

#通過將–as-template選項傳遞給oc export命令,將多個資源作為OpenShift模板同時導出。

[student@workstation ~]$ oc export svc,dc docker-registry > docker-registry.yaml #也可以使用重定嚮導出

[student@workstation ~]$ oc export –help #查看幫助

四 oc常見故障排除

4.1 常見環境信息


使用RPM安裝的OCP,那麼master和node的ocp相關服務將作為Red Hat Enterprise Linux服務運行。從master和node使用標準的sosreport實用程序,收集關於環境的信息,以及docker和openshift相關的信息。

[root@master ~]# sosreport -k docker.all=on -k docker.logs=on

sosreport命令創建一個包含所有相關信息的壓縮歸檔文件,並將其保存在/var/tmp目錄中。

另一個有用的診斷工具是oc adm diagnostics命令,能夠在OpenShift集群上運行多個診斷檢查,包括network、日誌、內部倉庫、master節點和node節點的服務檢查等等。oc adm diagnostics –help命令,獲取幫助。

4.2 常見診斷命令


oc客戶端命令是用來檢測和排除OpenShift集群中的問題的主要工具。它有許多選項,能夠檢測、診斷和修復由集群管理的主機和節點、服務和資源的問題。若已授權所需的權限,可以直接編輯集群中大多數託管資源的配置。

  • oc get events


事件允許OpenShift記錄集群中生命周期事件的信息,以統一的方式查看關於OpenShift組件的信息。oc get events命令提供OpenShift namespace的事件信息,可實現以下事件的捕獲:

    • Pod創建和刪除
    • pod調度的節點
    • master和node節點的狀態


事件通常用於故障排除,從而獲得關於集群中的故障和問題的高級信息,然後使用日誌文件和其他oc子命令進一步定位。

示例:使用以下命令獲得特定項目中的事件列表。

[student@workstation ~]$ oc get events -n <project>

也可以通過Web控制台進行事件的查看events。

  • oc log


oc logs命令查看build、deployment或pod的日誌輸出,。

示例1:使用oc命令查看pod的日誌。

[student@workstation ~]$ oc logs pod

示例2:使用oc命令查看build的日誌。

[student@workstation ~]$ oc logs bc/build-name

使用oc logs命令和-f選項實時跟蹤日誌輸出。例如,這對於連續監視build的進度和檢查錯誤非常有用。

也可以通過Web控制台進行事件的查看log。

  • oc rsync


oc rsync命令將內容複製到正在運行的pod中的目錄或從目錄複製內容。如果一個pod有多個容器,可以使用-c選項指定容器ID。否則,它默認為pod中的第一個容器。通常用於從容器傳輸日誌文件和配置文件。

示例1:將pod目錄中的內容複製到本地目錄。

[student@workstation ~]$ oc rsync <pod>:<pod_dir> <local_dir> -c <container>

示例2:將內容從本地目錄複製到pod的目錄中。

[student@workstation ~]$ oc rsync <local_dir> <pod>:<pod_dir> -c <container>

  • oc port-forward


使用oc port-forward命令將一個或多個本地端口轉發到pod。這允許在本地監聽特定或隨機端口,並將數據轉發到pod中的特定端口。

示例1:本地監聽3306並轉發到pod的3306.

[student@workstation ~]$ oc port-forward <pod> 3306:3306

五 TS常見故障

5.1 資源限制和配額問題


對於設置了資源限制和配額的項目,不適當的資源配置將導致部署失敗。使用oc get events和oc describe命令來排查失敗的原因。

例如試圖創建超過項目中pod數量配額限制的pod數量,那麼在運行oc get events命令時會提示:

Warning FailedCreate {hello-1-deploy} Error creating: pods “hello-1” is forbidden:

exceeded quota: project-quota, requested: cpu=250m, used: cpu=750m, limited: cpu=900m

5.2 S2I build失敗


使用oc logs命令查看S2I構建失敗。例如,要查看名為hello的構建配置的日誌:

[student@workstation ~]$ oc logs bc/hello

例如可以通過在build configuration策略中指定BUILD_LOGLEVEL環境變量來調整build日誌的詳細程度。

  1 {
  2 "sourceStrategy": {
  3 ...
  4 "env": [
  5 {
  6 "name": "BUILD_LOGLEVEL",
  7 "value": "5"
  8 }
  9 ]
 10 }
 11 }


5.3 ErrImagePull和imgpullback錯誤


通常是由不正確的deployment configuration造成、部署期間引用的錯誤或缺少image或Docker配置不當造成。

使用oc get events和oc describe命令排查,通過使用oc edit dc/<deploymentconfig>編輯deployment configuration來修復錯誤。

5.4 docker配置異常


master和node上不正確的docker配置可能會在部署期間導致許多錯誤。

通常檢查ADD_REGISTRY、INSECURE_REGISTRY和BLOCK_REGISTRY設置。使用systemctl status, oc logs, oc get events和oc describe命令對問題進行排查。

可以通添加/etc/sysconfig/docker配置文件中的–log-level參數來更改docker服務日誌級別。

示例:將日誌級別設置為debug。

OPTIONS=’–insecure-registry=172.30.0.0/16 –selinux-enabled –log-level=debug’

5.5 master和node節點失敗


運行systemctl status命令,對atomicopenshift-master、atom-openshift-node、etcd和docker服務中的問題進行排查。使用journalctl -u <unit-name>命令查看與前面列出的服務相關的系統日誌。

可以通過在各自的配置文件中編輯–loglevel變量,然後重新啟動關聯的服務,來增加來自atom-openshift-node、atomicopenshift-master-controllers和atom-openshift-master-api服務的詳細日誌記錄。

示例:設置OpenShift主控制器log level為debug級別,修改/etc/sysconfig/atomic-openshift-master-controllers文件。

OPTIONS=–loglevel=4 –listen=https://0.0.0.0:8444

延伸:

Red Hat OpenShift容器平台有五個級別的日誌詳細程度,無論日誌配置如何,日誌中都會出現帶有致命、錯誤、警告和某些信息嚴重程度的消息。

  • 0:只有錯誤和警告
  • 2:正常信息(默認)
  • 4:debug級信息
  • 6:api級debug信息(請求/響應)
  • 8:帶有完整請求體的API debug信息

5.6 調度pod失敗


OpenShift master調度pod在node上運行,通常由於node本身沒有處於就緒狀態,也由於資源限制和配額,pod無法運行。

使用oc get nodes命令驗證節點的狀態。在調度失敗期間,pod將處於掛起狀態,可以使用oc get pods -o wide命令進行檢查,該命令還显示了計劃在哪個節點上運行pod。使用oc get events和oc describe pod命令檢查調度失敗的詳細信息。

示例1:如下所示pod調度失敗,原因是CPU不足。

{default-scheduler } Warning FailedScheduling pod (FIXEDhello-phb4j) failed to

fit in any node

fit failure on node (hello-wx0s): Insufficient cpu

fit failure on node (hello-tgfm): Insufficient cpu

fit failure on node (hello-qwds): Insufficient cpu

示例2:如下所示pod調度失敗,原因是節點沒有處於就緒狀態,可通過oc describe排查。

{default-scheduler } Warning FailedScheduling pod (hello-phb4j): no nodes

available to schedule pods

六 常見問題排查

6.1 前置準備


準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

6.2 本練習準備


[student@workstation ~]$ lab common-troubleshoot setup

6.3 創建應用


[student@workstation ~]$ oc new-project common-troubleshoot

[student@workstation ~]$ oc new-app –name=hello -i php:5.4 \ #從源代碼創建應用

> http://services.lab.example.com/php-helloworld


6.4 查看詳情


[student@workstation ~]$ oc describe is php -n openshift





結論:由上可知,倉庫中不存在所需鏡像。

6.5 修正錯誤


[student@workstation ~]$ oc new-app –name=hello -i php:7.0 http://services.lab.example.com/php-helloworld

[student@workstation ~]$ oc get pod -o wide #再次查看發現一隻出於pending

NAME READY STATUS RESTARTS AGE IP NODE

hello-1-build 0/1 Pending 0 40s <none> <none>

6.6 查看詳情

  1 [student@workstation ~]$ oc log hello-1-build		#查看log
  2 W0720 20:22:16.455008   18942 cmd.go:358] log is DEPRECATED and will be removed in a future version. Use logs instead.
  3 [student@workstation ~]$ oc get events			#查看事件
  4 LAST SEEN   FIRST SEEN   COUNT     NAME                             KIND      SUBOBJECT   TYPE      REASON             SOURCE              MESSAGE
  5 56s         4m           15        hello-1-build.15b31cbd8da8ff1e   Pod                   Warning   FailedScheduling   default-scheduler   0/3 nodes are available: 1 MatchNodeSelector, 2 NodeNotReady.
  6 [student@workstation ~]$ oc describe pod hello-1-build	#查看詳情
  7 ……
  8 Warning  FailedScheduling  31s (x22 over 5m)  default-scheduler  0/3 nodes are available: 1 MatchNodeSelector, 2 NodeNotReady.
  9 結論:由上可知,沒有node可供調度此pod。
 10 [root@master ~]# oc get nodes				#在master節點進一步排查node情況
 11 NAME                     STATUS     ROLES     AGE       VERSION
 12 master.lab.example.com   Ready      master    1d        v1.9.1+a0ce1bc657
 13 node1.lab.example.com    NotReady   compute   1d        v1.9.1+a0ce1bc657
 14 node2.lab.example.com    NotReady   compute   1d        v1.9.1+a0ce1bc657
 15 結論:由上可知,node狀態異常,都未出於ready狀態。


6.7 檢查服務


[root@node1 ~]# systemctl status atomic-openshift-node.service

[root@node2 ~]# systemctl status atomic-openshift-node.service

[root@node1 ~]# systemctl status docker

[root@node2 ~]# systemctl status docker




結論:由上可知,node節點的docker異常。

6.8 啟動服務


[root@node1 ~]# systemctl start docker

[root@node2 ~]# systemctl start docker

6.9 確認驗證


[root@master ~]# oc get nodes #再次查看node狀態

NAME STATUS ROLES AGE VERSION

master.lab.example.com Ready master 1d v1.9.1+a0ce1bc657

node1.lab.example.com Ready compute 1d v1.9.1+a0ce1bc657

node2.lab.example.com Ready compute 1d v1.9.1+a0ce1bc657

[student@workstation ~]$ oc get pods #確認pod是否正常調度至node

NAME READY STATUS RESTARTS AGE

hello-1-build 1/1 Running 0 22m

[student@workstation ~]$ oc describe is #查看is詳情




結論:由上可知,IS也將image推送至內部倉庫。

七 oc命令綜合實驗

7.1 前置準備


準備完整的OpenShift集群,參考《003.OpenShift網絡》2.1。

7.2 本練習準備


[student@workstation ~]$ lab execute-review setup

7.3 git項目至本地


[student@workstation ~]$ cd /home/student/DO280/labs/execute-review/

[student@workstation execute-review]$ git clone http://services.lab.example.com/node-hello

7.4 docker構建image


[student@workstation execute-review]$ cd node-hello/

[student@workstation node-hello]$ docker build -t node-hello:latest .

[student@workstation node-hello]$ docker images #查看image

REPOSITORY TAG IMAGE ID CREATED SIZE

node-hello latest ff48daa00d8e 12 seconds ago 495 MB

registry.lab.example.com/rhscl/nodejs-6-rhel7 latest fba56b5381b7 22 months ago 489 MB

7.5 修改docker tag


[student@workstation node-hello]$ docker tag ff48daa00d8e \

> registry.lab.example.com/node-hello:latest

[student@workstation node-hello]$ docker images

REPOSITORY TAG IMAGE ID CREATED SIZE

node-hello latest ff48daa00d8e About a minute ago 495 MB

registry.lab.example.com/node-hello latest ff48daa00d8e About a minute ago 495 MB

registry.lab.example.com/rhscl/nodejs-6-rhel7 latest fba56b5381b7 22 months ago 489 MB

7.6 push image

[student@workstation node-hello]$ docker push registry.lab.example.com/node-hello:latest

7.7 創建project


[student@workstation ~]$ oc login -u developer -p redhat \

> https://master.lab.example.com

[student@workstation ~]$ oc projects

[student@workstation ~]$ oc project execute-review

[student@workstation ~]$ oc new-app registry.lab.example.com/node-hello –name hello

[student@workstation ~]$ oc get all #查看全部資源


7.8 排查ImagePullBackOff


[student@workstation ~]$ oc logs hello-1-2jkkj #查看日誌

Error from server (BadRequest): container “hello” in pod “hello-1-2jkkj” is waiting to start: trying and failing to pull image

[student@workstation ~]$ oc describe pod hello-1-2jkkj #查看詳情

[student@workstation ~]$ oc get events –sort-by=’.metadata.creationTimestamp’ #查看事件

結論:由上可知,為image pull失敗。

7.9 手動pull鏡像


[student@workstation ~]$ oc get pod -o wide

NAME READY STATUS RESTARTS AGE IP NODE

hello-1-2jkkj 0/1 ImagePullBackOff 0 8m 10.128.0.45 node1.lab.example.com

hello-1-deploy 1/1 Running 0 8m 10.129.0.72 node2.lab.example.com

[root@node1 ~]# docker pull registry.lab.example.com/node-hello #手動拉去也失敗

Using default tag: latest

Trying to pull repository registry.lab.example.com/node-hello …

All endpoints blocked.

結論:由上可知,所有endpoint都被阻塞了。這種類型的錯誤通常發生在OpenShift中,原因是不正確的部署配置或無效docker配置。

7.10 修正docker配置


[root@node1 ~]# vi /etc/sysconfig/docker

將BLOCK_REGISTRY=’–block-registry registry.access.redhat.com –block-registry docker.io –block-registry registry.

lab.example.com’

修改為

BLOCK_REGISTRY=’–block-registry registry.access.redhat.com –block-registry docker.io’

[root@node1 ~]# systemctl restart docker

提示:node2也需要如上操作。

7.11 更新pod


[student@workstation ~]$ oc rollout latest hello

[student@workstation ~]$ oc get pods #確認

NAME READY STATUS RESTARTS AGE

hello-1-deploy 0/1 Error 0 22m

hello-2-75x9t 1/1 Running 0 47s

7.12 確認驗證


[student@workstation ~]$ oc logs hello-2-75x9t #查看log

nodejs server running on http://0.0.0.0:3000

7.13 暴露服務


[student@workstation ~]$ oc expose svc hello –hostname=hello.apps.lab.example.com

route “hello” exposed

7.14 測試服務


[student@workstation ~]$ curl http://hello.apps.lab.example.com

Hi! I am running on host -> hello-2-75x9t

[student@workstation ~]$ lab execute-review grade #腳本驗證試驗

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

【其他文章推薦】

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

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

※超省錢租車方案

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

網頁設計最專業,超強功能平台可客製化

設計模式系列之組合模式(Composite Pattern)——樹形結構的處理

說明:設計模式系列文章是讀劉偉所著《設計模式的藝術之道(軟件開發人員內功修鍊之道)》一書的閱讀筆記。個人感覺這本書講的不錯,有興趣推薦讀一讀。詳細內容也可以看看此書作者的博客https://blog.csdn.net/LoveLion/article/details/17517213

模式概述

樹形結構在軟件中隨處可見,例如操作系統中的目錄結構、應用軟件中的菜單、辦公系統中的公司組織結構等等,如何運用面向對象的方式來處理這種樹形結構是組合模式需要解決的問題。組合模式通過一種巧妙的設計方案使得用戶可以一致性地處理整個樹形結構或者樹形結構的一部分,也可以一致性地處理樹形結構中的恭弘=叶 恭弘子節點(不包含子節點的節點)和容器節點(包含子節點的節點)。

模式定義

組合模式(Composite Pattern):組合多個對象形成樹形結構以表示具有“整體—部分”關係的層次結構。組合模式對單個對象(即恭弘=叶 恭弘子對象)和組合對象(即容器對象)的使用具有一致性,組合模式又可以稱為“整體—部分”(Part-Whole)模式,它是一種對象結構型模式。

模式結構圖

組合模式結構圖如下所示:

在組合模式結構圖中包含如下幾個角色:

  • Component(抽象構件):它可以是接口或抽象類,為恭弘=叶 恭弘子構件和容器構件對象聲明接口,在該角色中可以包含所有子類共有行為的聲明和實現。在抽象構件中定義了訪問及管理它的子構件的方法,如增加子構件、刪除子構件、獲取子構件等。

  • Leaf(恭弘=叶 恭弘子構件):它在組合結構中表示恭弘=叶 恭弘子節點對象,恭弘=叶 恭弘子節點沒有子節點,它實現了在抽象構件中定義的行為。對於那些訪問及管理子構件的方法,可以通過異常等方式進行處理。

  • Composite(容器構件):它在組合結構中表示容器節點對象,容器節點包含子節點,其子節點可以是恭弘=叶 恭弘子節點,也可以是容器節點,它提供一個集合用於存儲子節點,實現了在抽象構件中定義的行為,包括那些訪問及管理子構件的方法,在其業務方法中可以遞歸調用其子節點的業務方法。

組合模式的關鍵是定義了一個抽象構件類,它既可以代表恭弘=叶 恭弘子,又可以代表容器,而客戶端針對該抽象構件類進行編程,無須知道它到底表示的是恭弘=叶 恭弘子還是容器,可以對其進行統一處理。同時容器對象與抽象構件類之間還建立一個聚合關聯關係,在容器對象中既可以包含恭弘=叶 恭弘子,也可以包含容器,以此實現遞歸組合,形成一個樹形結構。

模式偽代碼

對於客戶端而言,一般針對抽象構件編程,而無須關心其具體子類是容器構件還是恭弘=叶 恭弘子構件。抽象構建類典型代碼如下:

public abstract class Component {
    public abstract void add(Component c); //增加成員

    public abstract void remove(Component c); //刪除成員

    public abstract Component getChild(int i); //獲取成員

    public abstract void operation();  //業務方法
}

如果繼承抽象構件的是恭弘=叶 恭弘子構件,則其典型代碼如下所示:

public class Leaf extends Component {
    @Override
    public void add(Component c) {
        //異常處理或錯誤提示 
    }

    @Override
    public void remove(Component c) {
        //異常處理或錯誤提示 
    }

    @Override
    public Component getChild(int i) {
        //異常處理或錯誤提示 
        return null;
    }

    @Override
    public void operation() {
        //恭弘=叶 恭弘子構件具體業務方法的實現
    }
}

如果繼承抽象構件的是容器構件,則其典型代碼如下所示:

public class Composite extends Component {

    private List<Component> list = new ArrayList<>();

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public Component getChild(int i) {
        return (Component) list.get(i);
    }

    @Override
    public void operation() {
        //容器構件具體業務方法的實現
        //遞歸調用成員構件的業務方法
        for (Object obj : list) {
            ((Component) obj).operation();
        }
    }
}

客戶端對抽象構件類進行編程

public class Client {
    public static void main(String[] args) {
        Component component;
        component = new Leaf();
        //component = new Composite();

        // 無須知道到底是恭弘=叶 恭弘子還是容器
        // 可以對其進行統一處理
        component.operation();
    }
}

模式簡化

透明組合模式

透明組合模式中,抽象構件Component中聲明了所有用於管理成員對象的方法,包括add()、remove()以及getChild()等方法,這樣做的好處是確保所有的構件類都有相同的接口。在客戶端看來,恭弘=叶 恭弘子對象與容器對象所提供的方法是一致的,客戶端可以相同地對待所有的對象。透明組合模式也是組合模式的標準形式。

透明組合模式的完整結構圖如下:

也可以將恭弘=叶 恭弘子構件的add()remove()等方法的實現代碼移至Component中,由Component提供統一的默認實現,這樣子類就不必強制去實現管理子Component。代碼如下所示:

public abstract class Component {
    public void add(Component c) {
        throw new RuntimeException("不支持的操作");
    }

    public void remove(Component c) {
        throw new RuntimeException("不支持的操作");
    }

    public Component getChild(int i) {
        throw new RuntimeException("不支持的操作");
    }

    public abstract void operation();  //業務方法
}

透明組合模式的缺點是不夠安全,因為恭弘=叶 恭弘子對象和容器對象在本質上是有區別的。恭弘=叶 恭弘子對象不可能有下一個層次的對象,即不可能包含成員對象,因此為其提供add()、remove()以及getChild()等方法是沒有意義的,這在編譯階段不會出錯,但在運行階段如果調用這些方法可能會出錯(如果沒有提供相應的錯誤處理代碼)。

安全組合模式

安全組合模式中,在抽象構件Component中沒有聲明任何用於管理成員對象的方法,而是在Composite類中聲明並實現這些方法。

安全組合模式的完整結構圖如下:

此時Component就應該這樣定義了

public abstract class Component {
    // 業務方法
    public abstract void operation();
}

安全組合模式的缺點是不夠透明,因為恭弘=叶 恭弘子構件和容器構件具有不同的方法,且容器構件中那些用於管理成員對象的方法沒有在抽象構件類中定義,因此客戶端不能完全針對抽象編程,必須有區別地對待恭弘=叶 恭弘子構件和容器構件。在實際應用中,安全組合模式的使用頻率也非常高,在Java AWT中使用的組合模式就是安全組合模式。

模式應用

模式在JDK中的應用

Java SE中的AWTSwing包的設計就基於組合模式,在這些界麵包中為用戶提供了大量的容器構件(如Container)和成員構件(如CheckboxButtonTextComponent等),其結構如下圖所示

Component類是抽象構件,CheckboxButtonTextComponent是恭弘=叶 恭弘子構件,而Container是容器構件,在AWT中包含的恭弘=叶 恭弘子構件還有很多。在一個容器構件中可以包含恭弘=叶 恭弘子構件,也可以繼續包含容器構件,這些恭弘=叶 恭弘子構件和容器構件一起組成了複雜的GUI界面。除此以外,在XML解析組織結構樹處理文件系統設計等領域,組合模式都得到了廣泛應用。

模式在開源項目中的應用

Springorg.springframework.web.method.support.HandlerMethodArgumentResolver使用了安全組合模式。提取關鍵代碼如下:

public interface HandlerMethodArgumentResolver {
    
    boolean supportsParameter(MethodParameter parameter);

    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                           NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;

}

再看下它的一個實現類org.springframework.web.method.support.HandlerMethodArgumentResolverComposite

public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {


    private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();

    /**
     * Add the given {@link HandlerMethodArgumentResolver}.
     */
    public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver resolver) {
        this.argumentResolvers.add(resolver);
        return this;
    }

    /**
     * Add the given {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers}.
     */
    public HandlerMethodArgumentResolverComposite addResolvers(
            @Nullable HandlerMethodArgumentResolver... resolvers) {

        if (resolvers != null) {
            Collections.addAll(this.argumentResolvers, resolvers);
        }
        return this;
    }

    /**
     * Clear the list of configured resolvers.
     */
    public void clear() {
        this.argumentResolvers.clear();
    }


    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return getArgumentResolver(parameter) != null;
    }


    @Override
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {

        HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
        if (resolver == null) {
            throw new IllegalArgumentException("Unsupported parameter type [" +
                    parameter.getParameterType().getName() + "]. supportsParameter should be called first.");
        }
        return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
    }
}

模式總結

主要優點

  1. 組合模式可以清楚地定義分層次的複雜對象,表示對象的全部或部分層次,它讓客戶端忽略了層次的差異,方便對整個層次結構進行控制。

  2. 客戶端可以一致地使用一個組合結構或其中單個對象,不必關心處理的是單個對象還是整個組合結構,簡化了客戶端代碼。

  3. 組合模式為樹形結構的面向對象實現提供了一種靈活的解決方案,通過恭弘=叶 恭弘子對象和容器對象的遞歸組合,可以形成複雜的樹形結構,但對樹形結構的控制卻非常簡單。

適用場景

(1) 在具有整體和部分的層次結構中,希望通過一種方式忽略整體與部分的差異,客戶端可以一致地對待它們。

(2) 在一個使用面向對象語言開發的系統中需要處理一個樹形結構。

(3) 在一個系統中能夠分離出恭弘=叶 恭弘子對象和容器對象,而且它們的類型不固定,需要增加一些新的類型。

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

【其他文章推薦】

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

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

※回頭車貨運收費標準

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

※超省錢租車方案

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

Python的多繼承問題-MRO和C3算法

Python 中的方法解析順序(Method Resolution Order, MRO)定義了多繼承存在時 Python 解釋器查找函數解析的正確方式。當 Python 版本從 2.2 發展到 2.3 再到現在的 Python 3,MRO算法也隨之發生了相應的變化。這種變化在很多時候影響了我們使用不同版本 Python 編程的過程。

大部分內容轉載自C3 線性化算法與 MRO 理解Python中的多繼承

什麼是 MRO

MRO 全稱方法解析順序(Method Resolution Order)。它定義了 Python 中多繼承存在的情況下,解釋器查找函數解析的具體順序。什麼是函數解析順序?我們首先用一個簡單的例子來說明。請仔細看下面代碼:

class A():
    def who_am_i(self):
        print("I am A")
        
class B(A):
    pass
        
class C(A):
    def who_am_i(self):
        print("I am C")

class D(B,C):
    pass
    
d = D()

如果我問在 Python 2 中使用 D 的實例調用 d.who_am_i(),究竟執行的是 A 中的 who_am_i() 還是 C 中的 who_am_i(),我想百分之九十以上的人都會不假思索地回答:肯定是 C 中的 who_am_i(),因為 C 是 D 的直接父類。然而,如果你把代碼用 Python 2 運行一下就可以看到 d.who_am_i() 打印的是 I am A

是不是覺得很混亂很奇怪?感到奇怪就對了!!!

這個例子充分展示了 MRO 的作用:決定基類中的函數到底應該以什麼樣的順序調用父類中的函數。可以明確地說,Python 發展到現在,MRO 算法已經不是一個憑藉著執行結果就能猜出來的算法了。如果沒有深入到 MRO 算法的細節,稍微複雜一點的繼承關係和方法調用都能徹底繞暈你。

New-style Class vs. Old-style Class

在介紹不同版本的 MRO 算法之前,我們有必要簡單地回顧一下 Python 中類定義方式的發展歷史。儘管在 Python 3 中已經廢除了老式的類定義方式和 MRO 算法,但對於仍然廣泛使用的 Python 2 來說,不同的類定義方式與 MRO 算法之間具有緊密的聯繫。了解這一點將幫助我們從 Python 2 向 Python 3 遷移時不會出現莫名其妙的錯誤。

在 Python 2.1 及以前,我們定義一個類的時候往往是這個樣子(我們把這種類稱為 old-style class):

class A:
    def __init__(self):
        pass

Python 2.2 引入了新的模型對象(new-style class),其建議新的類型通過如下方式定義:

class A(object):
    def __init__(self):
        pass

注意后一種定義方式显示註明類 A 繼承自 object。Python 2.3 及後續版本為了保持向下兼容,同時提供以上兩種類定義用以區分 old-style class 和 new-style class。Python 3 則完全廢棄了 old-style class 的概念,不論你通過以上哪種方式書寫代碼,Python 3 都將明確認為類 A 繼承自 object。這裏我們只是引入 old-style 和 new-style 的概念,如果你對他們的區別感興趣,可以自行看 stackoverflow 上有關該問題的解釋。

理解 old-style class 的 MRO

我們使用前文中的類繼承關係來介紹 Python 2 中針對 old-style class 的 MRO 算法。如果你在前面執行過那段代碼,你可以看到調用 d.who_am_i() 打印的應該是 I am A。為什麼 Python 2 的解釋器在確定 D 中的函數調用時要先搜索 A 而不是先搜索 D 的直接父類 C 呢?

這是由於 Python 2 對於 old-style class 使用了非常簡單的基於深度優先遍歷的 MRO 算法(關於深度優先遍歷,我想大家肯定都不陌生)。當一個類繼承自多個類時,Python 2 按照從左到右的順序深度遍歷類的繼承圖,從而確定類中函數的調用順序。這個過程具體如下:

  1. 檢查當前的類裏面是否有該函數,如果有則直接調用。
  2. 檢查當前類的第一個父類裏面是否有該函數,如果沒有則檢查父類的第一個父類是否有該函數,以此遞歸深度遍歷。
  3. 如果沒有則回溯一層,檢查下一個父類裏面是否有該函數並按照 2 中的方式遞歸。

上面的過程與標準的深度優先遍歷只有一點細微的差別:步驟 2 總是按照繼承列表中類的先後順序來選擇分支的遍歷順序。具體來說,類 D 的繼承列表中類順序為 B, C,因此,類 D 按照先遍歷 B 分支再遍歷 C 分支的順序來確定 MRO。

我們繼續用第一個例子中的函數繼承圖來說明這個過程:

按照上述深度遞歸的方式,函數 d.who_am_i() 調用的搜索順序是 D, B, A, C, A。由於一個類不能兩次出現,因此在搜索路徑中去除掉重複出現的 A,得到最終的方法解析順序是 D, B, A, C。這樣一來你就明白了為什麼 d.who_am_i() 打印的是 I am A 了。

在 Python 2 中,我們可以通過如下方式來查看 old-style class 的 MRO:

>>> import inspect
>>> inspect.getmro(D)

理解 new-style class 的 MRO

從上面的結果可以看到,使用深度優先遍歷的查找算法並不合理。因此,Python 3 以及 Python 2 針對 new-style class 採用了新的 MRO 算法。如果你使用 Python 3 重新運行一遍上述腳本,你就可以看到函數 d.who_am_i() 的打印結果是 I am C

>>> d.who_am_i()
I am C
>>> D.__mro__
(<class 'test.D'>, <class 'test.B'>, <class 'test.C'>, <class 'test.A'>, <class 'object'>)

新算法與基於深度遍歷的算法類似,但是不同在於新算法會對深度優先遍歷得到的搜索路徑進行額外的檢查。其從左到右掃描得到的搜索路徑,對於每一個節點解釋器都會判斷該節點是不是好的節點。如果不是好的節點,那麼將其從當前的搜索路徑中移除。

那麼問題在於,什麼是一個好的節點?我們說 N 是一個好的節點當且僅當搜索路徑中 N 之後的節點都不繼承自 N。我們還以上述的類繼承圖為例,按照深度優先遍歷得到類 D 中函數的搜索路徑 D, B, A, C, A。之後 Python 解釋器從左向右檢查時發現第三個節點 A 不是一個好的節點,因為 A 之後的節點 C 繼承自 A。因此其將 A 從搜索路徑中移除,然後得到最後的調用順序 D, B, C, A。

採用上述算法,D 中的函數調用將優先查找其直接父類 B 和 C 中的相應函數。

C3線性化算法

上一小結我們從直觀上概述了針對 new-style class 的 MRO 算法過程。事實上這個算法有一個明確的名字 C3 linearization。下面我們給出其形式化的計算過程。

上面的過程看起來好像很複雜,我們用一個例子來具體執行一下,你就會覺得其實還是挺簡單的。假設我們有如下的一個類繼承關係:

參考來源:Understanding Python MRO – Class search path

class X():
    def who_am_i(self):
        print("I am a X")
        
class Y():
    def who_am_i(self):
        print("I am a Y")
        
class A(X, Y):
    def who_am_i(self):
        print("I am a A")
        
class B(Y, X):
     def who_am_i(self):
         print("I am a B")
         
class F(A, B):
    def who_am_i(self):
        print("I am a F")

Traceback (most recent call last):
  File "test.py", line 17, in <module>
    class F(A, B):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases X, Y

為什麼採用C3算法

上圖中都是使用BFS算法來尋找繼承鏈,但是都會有問題,左邊的繼承模式會違背單調性的原則,右邊的棱形繼承鏈,如果是C重寫了繼承於A的方法,B沒有,但是根據MRO繼承鏈,最終調用的都是A類的方法,C中實現的方法永遠不會被調用,這些都是再python2的問題,python引入C3算法后就解決了這些問題。

C3算法最早被提出是用於Lisp的,應用在Python中是為了解決原來基於深度優先搜索算法不滿足本地優先級,和單調性的問題。
本地優先級:指聲明時父類的順序,比如C(A,B),如果訪問C類對象屬性時,應該根據聲明順序,優先查找A類,然後再查找B類。
單調性:如果在C的解析順序中,A排在B的前面,那麼在C的所有子類里,也必須滿足這個順序。

在Python官網的The Python 2.3 Method Resolution Order中作者舉了例子,說明這一情況

F=type('Food', (), {remember2buy:'spam'})
E=type('Eggs', (F,), {remember2buy:'eggs'})
G=type('GoodFood', (F,E), {})

根據本地優先級在調用G類對象屬性時應該優先查找F類,而在Python2.3之前的算法給出的順序是G E F O,而在心得C3算法中通過阻止類層次不清晰的聲明來解決這一問題,以上聲明在C3算法中就是非法的。

小結

C3算法的核心 :

  1. 遍歷執行merge操作的序列,如果一個序列的第一個元素,在其他序列中也是第一個元素,或不在其他序列出現,則從所有執行merge操作序列中刪除這個元素,合併到當前的mro中。

  2. merge操作后的序列,繼續執行merge操作,直到merge操作的序列為空。

  3. 如果merge操作的序列無法為空,則說明不合法。

參考資料

理解Python中的多繼承-C3 線性化算法

Python的多重繼承問題-MRO和C3算法

Deep Thoughts by Raymond Hettinger

C3 linearization

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

【其他文章推薦】

※超省錢租車方案

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

※回頭車貨運收費標準

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

FB行銷專家,教你從零開始的技巧

Tesla市值超越Ford,成全美第二大製造商

電動車究竟行不行得通?讓特斯拉(Tesla)來告訴你答案。3 日上午,隨著特斯拉的股價飆升,特斯拉的市值正式超越了百年汽車大廠福特(Ford),成為美國第二大汽車製造商。

電動車將成主流?

華爾街日報報導,特斯拉近日公布2017 年第一季銷售數據,受到Model S、Model X 車款交貨量大增帶動,全球銷售量較去年同期大增69%,創下單季銷售量歷史新高,消息激勵股價3 日大漲7.3% 至298.52 美元,特斯拉的市值也來到487 億美元(約1.48 兆元台幣),超過福特的455 億美元(約1.38 兆元台幣)。

隨著車款交貨量提升,特斯拉將有望順利達成2017 上半年的5 萬台銷售目標。儘管整體銷售量仍無法與其他大廠做比較,但有越來越多的投資人相信,在經過數年可觀的成長後,美國汽車的銷售市場已經開始出現衰退,電動車將逐漸成為主流。

這項在1980 年代時日本車廠企圖研發的技術,如今卻可能由矽谷的公司來讓其發揚光大。

特斯拉的專長?

或許是嗅到未來的商機,不僅僅是特斯拉,許多汽車大廠也開始關注電動車及自駕車領域。通用也在日前就推出平價電動車Chevrolet Bolt,想與特斯拉一較高下,然而3 月僅銷售3,000 輛,與特斯拉Model 3的預購盛況相去勝遠。

福特即將上任的執行長費爾茲(Mark Fields)也承諾將在2021 年前推出自駕車,但百年企業轉型談何容易,目前看來仍舊困難重重。

基金公司ARK Invest 的分析師Tasha Keeney 認為,其他汽車大廠若想投入電動車和自駕車領域發展,目前得需付出比特斯拉雙倍的努力才有望達成。

福特的市值和2010 年底時大致相同,但當時新上市的特斯拉市值仍低於20 億美元(約608 億元台幣)。目前全美最大的汽車製造商是通用(General),市值為521 億美元(約1.58 兆元台幣)。

如今看來,特斯拉隨時有機會超越通用,奪下全美市值第一汽車製造商的寶座。

市值被高估?

由於看好特斯拉對自駕車共乘服務的未來發展,摩根史丹利的分析師Adam Jonas 將特斯拉的目標價訂為每股305 美元,部分投資人認為,相較起其他汽車大廠和科技龍頭,特斯拉更有望能將自駕技術真正帶進道路。

然而並非所有人都對特斯拉有信心,儘管已經成立13 年,特斯拉仍有著沉重的負債、未能穩定獲利,自駕車也還在測試階段。底特律車商和汽車研究中心主席David Cole 就認為,特斯拉的市值攀升是靠著炒作和承諾為基礎的。

對於外界的關注,馬斯克3日發推特表示,如果以特斯拉的歷史來看,確實會讓人覺得公司市值過高,但特斯拉現在的股價是反映風險調整後的未來現金流。福特則發聲明指出,營運並不會受股價波動影響,重心一直都放在透過經營來提升價值。

(合作媒體:。圖片出處:Public Domain CC0)

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

【其他文章推薦】

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

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

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

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

※超省錢租車方案