傳蘋果電動汽車將採用韓國公司的電池技術

根據行業消息,蘋果近期與一家韓國電池開發商簽署了保密協議,聯合為代號為“泰坦”的汽車專案開發電池。從今年初開始,他們一直在韓國做行政工作。一名蘋果員工一直在這家韓國公司進行參觀活動,他屬於與蘋果電動汽車電池開發相關的部門。  
  業界認為,這家韓國公司並不是唯一一家負責蘋果電池開發的公司。不過,有消息稱,儘管蘋果從一開始就從完全不同的設計、功能以及性能角度來開發電池,但是他們仍舊一直在挖掘創新技術。業界相信,蘋果專注于開發出只能存在於蘋果自動駕駛汽車的創新電池技術。   這家韓國電池開發商由大約20名電池專家組成,持有空芯電池的國際專利技術。這些電池是圓柱形鋰離子二次電池,有兩根手指那麼厚,不同於其它空芯電池。蘋果並未選擇當前電動汽車普遍使用的標準圓形或矩形電池,但計畫根據韓國公司的空芯電池技術為其電動汽車開發自主電池。   文章來源:鳳凰科技

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

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

蘋果傳將攜手韓廠研發電動車用電池

蘋果公司持續擴大業務範圍,除新成立的蘋果能源(Apple Energy)成功取得售電許可外,市場上關注度十足的蘋果電動車專案「泰坦計畫」(Project Titan)也時常傳出新消息。近期傳言蘋果將與南韓某企業合作,運用該南韓公司的電池專利,攜手開發電動車用電池。

根據日本蘋果情報網站iPhone Mania、南韓媒體ET News 等報導,蘋果看上某家南韓廠商所取得的鋰電池專利,打算與該廠合作開發電動車用電池。被看上的鋰電池專利技術,電池中央部位採中空設計,可使空氣流通來冷卻電池,等同降低冷卻系統的需求,騰出更多空間來增加電池容量。

日、韓媒體並未披露可能將與蘋果合作的韓廠名稱,但美國MacRumors 透剁歐洲專利局得知,這款「中央中空」的電池是由一家稱為Orange Power 的南韓廠商取得。該廠係一小廠,員工人數僅33人,其中多數為研發人員。

蘋果電動車計畫自曝光以來即備受矚目,但至今仍然只聞樓梯響。據了解,目前共有約1,000人參與蘋果電動車企劃,且蘋果已在柏林設立秘密開發實驗室。MoneyDJ引述The Information網站的說法,表示蘋果電動車可能在2021年亮相;但也有分析師認為,蘋果電動車可能會步上蘋果電視的後塵,胎死腹中。

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

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

續航力600公里的特斯拉 即將問世?

續航力是電動車最受關注的性能,而作為全球電動車龍頭廠商的特斯拉(Tesla),似乎也準備好要推出續航力更久的車款了。跟據了解,新的特斯拉電動車可能搭載100kW的電池,續航力最遠可達611公里。

《癮科技》中文版指出,德國監管機關的資料中可查到Model S與Model X的100D與P100D型號的相關資訊;而根據特斯拉為車款型號命名的邏輯,這可能暗示特斯拉將推出搭載100kW電池的車款。

100kW 的電池搭配Model S,預計最高續航里程可來到611公里,比90D的續航里程多了100公里以上。若搭配Model X,續航里程也可來到480 公里之多。這樣的續航力,將能有效減輕美國車主對駕駛特斯拉跨州旅行的疑慮。

(照片來源:Tesla 臉書專頁)

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

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

從零開始搭建前後端分離的NetCore2.2(EF Core CodeFirst+Autofac)+Vue的項目框架之十一Swagger使用一

 一.未使用Swagger狀況

  相信無論是前端開發人員還是後端開發人員,都或多或少都被接口文檔折磨過,前端經常抱怨後端給的接口文檔或與實際情況不一致。後端又覺得編寫及維護接口文檔會耗費不少精力,經常來不及更新。 其實無論是前端調用後端,還是後端調用後端,都期望有一個好的接口文檔。但是這個接口文檔對於程序員來說,就跟註釋一樣,經常會抱怨別人寫的代碼沒有寫註釋,然而自己寫起代碼起來,最討厭的,也是寫註釋。 所以僅僅只通過強制來規範大家是不夠的,隨着時間推移,版本迭代,接口文檔往往很容易就跟不上代碼了

 二.使用Swagger狀況

  Swagger 提供了一個可視化的UI頁面展示描述文件,其中包括接口的調用,接口所需參數(header,body,url.params),接口說明,參數說明等。接口的調用方、測試、項目經理等都可以在該頁面中對相關接口進行查閱和做一些簡單的接口請求。只要在項目框架搭建時,對Swagger 進行了配置,後面持續迭代的時候,只會花很小代價去維護代碼、接口文檔以及Swagger描述文件。因為一旦接口發生改變,程序重新部署,接口文檔會重新生成對應新的文檔。

 三.如何使用?

  在NetCore項目中怎麼去使用Swagger來生成接口文檔呢?

  首先在 webApi 啟動項目 上 右鍵 點擊管理Nuget程序包, 安裝  Swashbuckle.AspNetCore ,然後到  Startup 中添加引用  using Swashbuckle.AspNetCore.Swagger; 

  在ConfigureServices方法中添加以下代碼

            #region Swagger

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "API Doc",
                    Description = "作者:Levy_w_Wang",
                    //服務條款
                    TermsOfService = "None",
                    //作者信息
                    Contact = new Contact
                    {
                        Name = "levy",
                        Email = "levy_w_wang@qq.com",
                        Url = "https://www.cnblogs.com/levywang"
                    },
                    //許可證
                    License = new License
                    {
                        Name = "tim",
                        Url = "https://www.cnblogs.com/levywang"
                    }
                });

                #region XmlComments

                var basePath1 = Path.GetDirectoryName(typeof(Program).Assembly.Location);//獲取應用程序所在目錄(絕對,不受工作目錄(平台)影響,建議採用此方法獲取路徑)
                //獲取目錄下的XML文件 显示註釋等信息
                var xmlComments = Directory.GetFiles(basePath1, "*.xml", SearchOption.AllDirectories).ToList();

                foreach (var xmlComment in xmlComments)
                {
                    options.IncludeXmlComments(xmlComment);
                }
                #endregion

                options.DocInclusionPredicate((docName, description) => true);

                options.IgnoreObsoleteProperties();//忽略 有Obsolete 屬性的方法
                options.IgnoreObsoleteActions();
                options.DescribeAllEnumsAsStrings();
            });
            #endregion

上面寫的循環是因為項目中可能有多個控制器類庫,為的是排除這種情況

接下來,再到 Configure 方法中添加:

            #region Swagger

            app.UseSwagger(c => { c.RouteTemplate = "apidoc/{documentName}/swagger.json"; });
            app.UseSwaggerUI(c =>
            {
                c.RoutePrefix = "apidoc";
                c.SwaggerEndpoint("v1/swagger.json", "ContentCenter API V1");
                c.DocExpansion(DocExpansion.Full);//默認文檔展開方式
            });

            #endregion

這裏使用了 RoutePrefix  屬性,為的是改變原始打開接口文檔目錄,原始路徑為 swagger/index.html ,現在為 /apidoc/index.html 

這個時候在需要輸出註釋的控制器類庫屬性 中設置如下信息,並添加上相關註釋

然後運行起來,打開本地地址加上  /apidoc/index.html  就可以看到效果,

特別提醒:如果打開下面這個界面能正常显示,但是提示  Fetch errorInternal Server Error v1/swagger.json  錯誤,說明有方法未指明請求方式,如 HttpGet HttpPost HttpPut 等,找到並指明,重新運行就正常了

 

  點擊方法右上角的 Try it out ,試下調用接口,然後點擊Exectue,執行查看結果,能得到後端方法返回結果就說明成功。

特別說明:有接口不需要展示出去的時候,可以在方法上添加屬性 Obsolete ,這樣就不會显示出來。 前提:有前面ConfigureServices中 後面的 忽略 有Obsolete 屬性的方法 設置才行!!!

 

 最後可以看到接口返回數據正常,並且也能看到接口響應請求嘛等等信息,一個接口應該返回的信息也都有显示。

 

總結:

本文從為開發人員手寫api文檔的痛楚,從而引申出Swagger根據代碼自動生成出文檔和註釋,

並且還可以將不需要的方法不显示等設置。然後進行了簡單的測試使用 。

但是!!一般後端方法都有token等驗證,需要在header中添加token、sid等字段來驗證用戶,保障安全性,

該設置將在下一章節中寫!

 下一章

以上若有什麼不對或可以改進的地方,望各位指出或提出意見,一起探討學習~

有需要源碼的可通過此 鏈接拉取 覺得還可以的給個 start 和點個 下方的推薦哦~~謝謝!

 

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

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

PostgreSQL空間數據庫創建備份恢復(PostGIS vs ArcGIS)

梯子

PostGIS

創建

安裝就不必介紹了,windows下使用安裝工具Application Stack Builder,選擇空間擴展PostGIS即可自動安裝

然後新建庫后,在庫中執行以下語句創建控件擴展

CREATE EXTENSION postgis

也可以創建數據庫時選擇postgis的模板庫創建

create database postgisdb template postgis_template;

新建數據庫后添加postgis擴展後會發現庫內public模式下函數序列觸發器等都會增加一些postgis相關功能
然後就可以通過PostGIS Shapefile and DBF Loader工具導入shp數據

備份

postgersql的備份恢復主要有

  1. 增量備份和基於時間點恢復(RITR)
  2. pg_dump和pg_dumpall進行轉儲,從SQL轉儲文件恢復
  3. 文件系統級別備份

這裏我們使用簡單,容易掌握的pg_dump命令,一般在安裝目錄bin下
pg_dump備份單庫,不導出角色和表空間相關信息

pg_dump -h localhost -U postgres postgisdb > D:\backup\postgisdb.bak

有一些參數選項可以參考(很多,具體不列了,執行help可以查看到)

pg_dump --help
恢復

恢復可以使用psql

psql -h localhost -U postgres -d postgisdb2 < D:\backup\postgisdb.bak

恢復時可以指定不同的數據庫,如果pg_dump時-C創建數據庫,那也可以不用先新建數據庫

postgis庫的恢復備份還是挺簡單的,所有的東西都在public下

ArcGIS

創建

ArcGIS要連接到postgresql,需要將postgresql安裝目錄lib下的libeay32.dll、libiconv-2.dll、libintl-8.dll、libpq.dll 和 ssleay32.dll拷貝到ArcGIS Desktop的安裝目錄bin下
將ArcGIS Desktop目錄DatabaseSupport\PostgreSQL下的st_geometry.dll拷貝到postgresql的lib下

使用ArcGIS工具箱中Create Enterprise Geodatabase工具創建SDE,完事後會在創建一個sde登陸角色並在庫中創建一個sde模式,包含諸多函數序列管理表等。(注意:ArcGIS雖然可以在系統庫postgres中創建SDE擴展,然並連不上,ArcGIS不允許連接訪問系統數據庫

然後ArcGIS可以連接該數據庫,並且進行空間數據管理操作。(注意:默認ArcGIS創建空間數據,只能創建在和登陸用戶同名的模式下

備份

我們可以向上面PostGIS備份恢復一樣,直接備份整個庫

恢復

如果恢復至同名數據庫,像上面恢復是沒有問題的
但如果數據庫改名了,則會有驚喜發生,ArcGIS管理空間報底層gdb_release之類的錯誤,同樣的問題不止恢復庫時,修改數據庫名稱也不像其他庫那麼隨心所欲,以含SDE擴展的庫為模板創建新庫也會有問題

ArcGIS SDE未見文檔介紹內部結構邏輯,只能猜測大概,或不準確,願聞其詳

ArcSDE空間數據創建時會在SDE管理表裡註冊相關信息,比如空間參考,列啊,表的唯一標識等,便於它做數據管理、版本控制

修改庫名后,ArcSDE管理就出問題,主要是一些註冊項,安裝SDE時也會把該庫的信息註冊到SDE管理表中去,所以新庫名,它就不認識了

如果修改了庫名,我們找到以下錶

select * from sde.gdb_items
you need modify : name physicalname path etc...

update sde.sde_table_registry set database_name='testdb';
update sde.sde_column_registry set database_name='testdb';
update sde.sde_geometry_columns set f_table_catalog='testdb';
update sde.sde_raster_columns set database_name='testdb';
update sde.sde_layers set database_name='testdb';

然後就一切正常

當然我們建議不輕易改庫名

這就是商業軟件,足夠強大不夠靈活,封裝和靈活總會互相博弈

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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

paper sharing :學習特徵演化的數據流

特徵演化的數據流

    數據流學習是近年來機器學習與數據挖掘領域的一個熱門的研究方向,數據流的場景和靜態數據集的場景最大的一個特點就是數據會發生演化,關於演化數據流的研究大多集中於概念漂移檢測(有監督學習),概念/聚類演化分析(無監督學習),然而,人們往往忽略了一個經常出現的演化場景:特徵演化。大多數研究都考慮數據流的特徵空間是固定的,然而,在很多場景下這一假設並不成立:例如,當有限壽命傳感器收集的數據被新的傳感器替代時,這些傳感器對應的特徵將發生變化。

    今天要分享的文章出自周志華的實驗室《Learning with Feature Evolvable Streams》(NIPS 2017),它提出了一個新的場景,即在數據流中會有特徵消亡也會有新特徵出現。當出現新的特徵空間時,我們並不直接拋棄之前學到的模型並在新的數據上重新創建模型,而是嘗試恢復消失的特徵來提升模型的表現。具體來說,通過從恢復的特徵和新的特徵空間中分別學習兩個模型。為了從恢復的特徵中獲得提升,論文中提出了兩種集成策略:第一種方法是合併兩個模型的預測結果;第二種是選擇最佳的預測模型。下面我們具體來理解特徵演化數據流以及論文中提出的一些有趣的方法吧~

paper link:

 

什麼是特徵演化數據流?

    在很多現實的任務中,數據都是源源不斷收集的,關於數據流學習的研究近年來受到越來越多的關注,雖然已經有很多有效的算法針對特定的場景對數據流進行挖掘,但是它們都基於一個假設就是數據流中數據的特徵空間是穩定的。不幸的是,這一假設在很多場景下都不滿足。針對特徵演化的場景,最直接的想法就是利用新的特徵空間的數據學習一個新的模型,但是這一方法有很多問題:首先,當新的特徵剛出現的時候,只有很少的數據樣本來描述這些信息,訓練樣本並不足夠去學習一個新的模型;其次,包含消失特徵的舊模型被直接丟棄了,其中可能包含對當前數據有用的信息。論文中定義了一種特徵演化數據流的場景:一般情況下,特徵不會任意改變,而在一些重疊時期,新特徵和舊特徵都存在,如下圖所示:

    其中,T1階段,原始特徵集都是有效的,B1階段出現了新的特徵集,T2階段原始特徵集消失,只有新的特徵集。

    論文提出的方法是通過使用重疊(B1)階段來發現新舊特徵之間的關係,嘗試學習新特徵到舊特徵的一個映射,這樣就可以通過重構舊特徵並使用舊模型對新數據進行預測

問題描述

    論文中着重解決的是分類和回歸任務,在每一輪學習過程中,對每一個實例進行預測,結合它的真實標籤會得到一個loss(反映預測和真實標籤的差異),我們將上面提到的T1+B1+T的過程稱為一個周期,每個周期中只包含兩個特徵空間,所以,之後的研究主要關注一個周期內的模型的學習,而且,我們假設一個周期內的舊特徵會同時消失。定義Ω1和Ω2分別表示兩個特徵空間S1和S2上的線性模型,並定義映射,定義第i維特徵在第t輪的預測函數為線性模型,。損失函數是凸的,最直接的方式是使用在線梯度下降來求解w,但是在數據流上不適用。

 

方法介紹

    上文提到的基本算法的主要限制是在第1,…T1輪學習的模型在T1+1,…T1+T2時候被忽略了,這是因為T1之後數據的特徵空間改變了,我們無法直接應用原來的模型。為了解決這一問題,我們假設新舊特徵空間之間有一種特定的關係:,我們嘗試通過重疊階段B1來學習這種關係。學習兩組特徵之間的關係的方法很多,如多元回歸,數據流多標籤學習等。但是在當前的場景下,由於重疊階段特別短,學習一個複雜的關係模型是不現實的。所以我們採用線性映射來近似。定義線性映射的係數矩陣為M,那麼在B1階段,M的估計可以基於如下的目標方程:

M的最優解可以解得:

    然後,當我觀測到S2空間得數據,就可以通過M將其轉化到S1空間,並應用舊模型對其進行預測。

除了學習這個關係映射之外,我們得算法主要包括兩個部分:

  1. 在T1-B1+1,…T1階段,我們學習兩個特徵空間之間得關係;

  2. 在T1之後,我們使用新特徵空間的數據轉化后的原特徵空間數據,持續更新舊模型以提升它的預測效果,然後集成兩個模型進行預測。

 

預測結果集成

    論文中提出兩種集成方法,第一種是加權組合,即將兩個模型的預測結果求加權平均,權重是基於exponential of the cumulative loss。

其中

    這種權重的更新規則表明,如果上一輪模型的損失較大,下一輪模型的權值將以指數速度下降,這是合理的,可以得到很好的理論結果。

    第二種集成方法是動態選擇。

    上面提到的組合的方法結合了幾個模型來提升整體性能,通常來說,組合多個分類器的表現會比單分類器的效果要好,但是,這基於一個重要的假設就是每個基分類器的表現不能太差(如,在Adaboost中,基分類器的預測精度不應低於0.5)。然而在這個問題中,由於新特徵空間剛出現的時候訓練集較小,訓練的模型不好,因此可能並不適合用組合的方法來預測,相反,用動態選擇最優模型的方法反而能獲得好的效果。

有趣的靈魂在等你長按二維碼識別

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

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

Go 多變量賦值時注意事項

說到多變量賦值時,先計算所有相關值,然後再從左到右依次賦值,但是這個規則不適用於python
我們來看一例:

package main

import "fmt"

func main() {
    data, i := [3]string{"喬幫主","慕容復","鳩摩智"}, 0
    i, data[i] = 2, "枯榮大師"
    fmt.Println(i, data)
}

輸出結果:

2 [枯榮大師 慕容復 鳩摩智]  

有的朋友會認為,結果不應該是這樣么?(但是python下輸出的結果卻是下面的)?

2 [喬幫主 慕容復 枯榮大師]

事實並如此,我們來看賦值順序這段的理解:

1     data, i := [3]string{"喬幫主","慕容復","鳩摩智"}, 0
2     i, data[i] = 2, "枯榮大師" //注意原則:先計算所有相關值,然後再從左到右依次賦值
3     // 這裏變量i 的順序其實是(i = 0,因為上一行的變量i是0) -> (然後 i = 2), (data[i] 此時取的值是data[0],而不是data[2],也就是data[0] = 枯榮大師)
4     fmt.Println(i, data) //所以這裏最終 輸出 i=2,[枯榮大師 慕容復 鳩摩智]

同樣的多變量賦值卻不適用於python.

data,i=["喬幫主", "慕容復", "鳩摩智"],0
i, data[i] = 2, "枯榮大師" # 注意這裏data[i] 已經是 data[2]了,即data[2]="枯榮大師"
print(i,data) # 輸出 2 ['喬幫主', '慕容復', '枯榮大師']

另外:我們要注意重新賦值與定義新同名變量的區別:再看一例:

package main

func main() {
    name := "喬幫主"
    println(&name)
    name, age := "鳩摩智", 30 // 重新賦值: 與前 name 在同層次的代碼塊中,且有新的變量被定義。
    println(&name, age)    // 通常函數多返回值 err 會被重複使用。
    {
        name, weight := "清風揚", 50 // 定義新同名變量: 不在同層次代碼塊。
        println(&name, weight)
    }
}

輸出:

0xc00002bf78
0xc00002bf78 30
0xc00002bf68 50

注意:因個人機器不同,大家返回的內存引用地址可能和我的不一樣,但是 這步是重點。重點在這裏:
同層級相同變量的賦值,內存地址並不會改變。不同層級相同變量的賦值,其實是定義了一個新同名變量,也就是大家看到的第三行內存地址變了。
接着我們再看有點意思的一段代碼(大家來找茬):

package main

func main() {
    name := "喬幫主"
    println(&name)
    name, age := "鳩摩智", 30 // 重新賦值: 與前 name 在同 層次的代碼塊中,且有新的變量被定義。
    println(&name, age)    // 通常函數多返回值 err 會被重複使用。

    name, weight := 100, 50 // 定義新同名變量: 不在同 層次代碼塊。
    println(&name, weight, age)

}

輸出:

cannot use 100 (type int) as type string in assignment

原因很明顯,因為上面:name := “喬幫主” 已經隱試滴申明了name 是字符串,等同於 var name string. 同層級再次賦值100為整形。這是不允許滴,

但是:重點來了,我們稍改下:

package main

func main() {
    name := "喬幫主"
    println(&name)
    name, age := "鳩摩智", 30 // 重新賦值: 與前 name 在同 層次的代碼塊中,且有新的變量被定義。
    println(&name, age)    // 通常函數多返回值 err 會被重複使用。
    {
        name, weight := 100, 50 // 定義新同名變量: 不在同層次代碼塊。
        println(&name, weight, age)
    }
}

區別就是層級發生了變化,因為{}裏面的name已經是新的變量了。
好啦,到此介紹結束了。博友們有關golang變量使用中遇到的各種奇怪的“坑”,請留下寶貴滴足跡,歡迎拍磚留言.

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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

【併發編程】Java中的原子操作

什麼是原子操作

原子操作是指一個或者多個不可再分割的操作。這些操作的執行順序不能被打亂,這些步驟也不可以被切割而只執行其中的一部分(不可中斷性)。舉個列子:

//就是一個原子操作
int i = 1;

//非原子操作,i++是一個多步操作,而且是可以被中斷的。
//i++可以被分割成3步,第一步讀取i的值,第二步計算i+1;第三部將最終值賦值給i
i++;

Java中的原子操作

在Java中,我們可以通過同步鎖或者CAS操作來實現原子操作。

CAS操作

CAS是Compare and swap的簡稱,這個操作是硬件級別的操作,在硬件層面保證了操作的原子性。CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改為B,否則什麼都不做。Java中的sun.misc.Unsafe類提供了compareAndSwapIntcompareAndSwapLong等幾個方法實現CAS。

另外,在jdk的atomic包下面提供了很多基於CAS實現的原子操作類,見下圖:

下面我們就使用其中的AtomicInteger來看看怎麼使用這些原子操作類。

package com.csx.demo.spring.boot.concurrent.atomic;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerDemo {

    private static int THREAD_COUNT = 100;

    public static void main(String[] args) throws InterruptedException {


        NormalCounter normalCounter = new NormalCounter("normalCounter",0);
        SafeCounter safeCounter = new SafeCounter("safeCounter",0);
        List<Thread> threadList = new ArrayList<>();

        for (int i = 0; i < THREAD_COUNT ; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 10000; j++) {
                        normalCounter.add(1);
                        safeCounter.add(1);
                    }
                }
            });
            threadList.add(thread);
        }

        for (Thread thread : threadList) {
            thread.start();
        }
        for (Thread thread : threadList) {
            thread.join();
        }
        System.out.println("normalCounter:"+normalCounter.getCount());
        System.out.println("safeCounter:"+safeCounter.getCount());
    }


    public static class NormalCounter{
        private String name;
        private Integer count;

        public NormalCounter(String name, Integer count) {
            this.name = name;
            this.count = count;
        }

        public void add(int delta){
            this.count = count+delta;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getCount() {
            return count;
        }

        public void setCount(Integer count) {
            this.count = count;
        }
    }

    public static class SafeCounter{
        private String name;
        private AtomicInteger count;

        public SafeCounter(String name, Integer count) {
            this.name = name;
            this.count = new AtomicInteger(count);
        }

        public void add(int delta){
            count.addAndGet(delta);
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getCount() {
            return count.get();
        }

        public void setCount(Integer count) {
            this.count.set(count);
        }
    }

}

上面的代碼中,我們分別創建了一個普通的計數器和一個原子操作的計數器(使用AtomicInteger進行計數)。然後創建了100個線程,每個線程進行10000次計數。理論上線程執行完之後,計數器的值都是1000000,但是結果如下:

normalCounter:496527
safeCounter:1000000

每次執行,普通計數器的值都是不一樣的,而使用AtomicInteger進行計數的計數器都是1000000。

CAS操作存在的問題

  • ABA問題:因為CAS需要在操作值的時候檢查下值有沒有發生變化,如果沒有發生變化則更新,但是如果一個值原來是A,變成了B,又變成了A,那麼使用CAS進行檢查時會發現它的值沒有發生變化,但是實際上卻變化了。ABA問題的解決思路就是使用版本號。在變量前面追加上版本號,每次變量更新的時候把版本號加一,那麼A-B-A 就會變成1A-2B-3A。

從Java1.5開始JDK的atomic包里提供了一個類AtomicStampedReference來解決ABA問題。這個類的compareAndSet方法作用是首先檢查當前引用是否等於預期引用,並且當前標誌是否等於預期標誌,如果全部相等,則以原子方式將該引用和該標誌的值設置為給定的更新值。

  • 循環時間長開銷大:自旋CAS如果長時間不成功,會給CPU帶來非常大的執行開銷。如果JVM能支持處理器提供的pause指令那麼效率會有一定的提升,pause指令有兩個作用,第一它可以延遲流水線執行指令(de-pipeline),使CPU不會消耗過多的執行資源,延遲的時間取決於具體實現的版本,在一些處理器上延遲時間是零。第二它可以避免在退出循環的時候因內存順序衝突(memory order violation)而引起CPU流水線被清空(CPU pipeline flush),從而提高CPU的執行效率。

  • 只能保證一個共享變量的原子操作:當對一個共享變量執行操作時,我們可以使用循環CAS的方式來保證原子操作,但是對多個共享變量操作時,循環CAS就無法保證操作的原子性,這個時候就可以用鎖,或者有一個取巧的辦法,就是把多個共享變量合併成一個共享變量來操作。比如有兩個共享變量i=2,j=a,合併一下ij=2a,然後用CAS來操作ij。從Java1.5開始JDK提供了AtomicReference類來保證引用對象之間的原子性,你可以把多個變量放在一個對象里來進行CAS操作。

使用鎖來保證原子操作

還是以上面的列子為列,普通的計數器我們只需要在計數方法上加鎖就行了:

public synchronized void  add(int delta){
  this.count = count+delta;
}

執行結果如下:

normalCounter:1000000
safeCounter:1000000

兩個計數器都能拿到正確的結果

CPU是怎麼實現原子操作的

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

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

三個月(敏捷)項目收穫

 

 

項目背景

客戶已有運行多年的官網老站(PC端),想在今年對老站進行一次UI全面更新、功能全部平移的升級,對接新的運營後端,然後建立官網小程序端且與官網PC端進行聯動,使得品牌自有渠道能夠更加全面化。

 

挑戰

  • 時間緊。五月份進行Inception Workshop,確定項目交付範圍與架構方案。官網六月初開始開發,小程序八月份開始開發,整個項目九月中旬必須上線。
  • 系統集成和數據遷移。系統需要對接客戶的CRM,對接3個服務商,需要對老官網歷史數據(訂單、會員等)進行遷移。
  • 多團隊溝通。小程序設計稿由第三方提供,因此多出了溝通、確認的時間,以及把控第三方交付的時間,以避免交付進度的影響。

 

迭代計劃

Inception Workshop一結束,差不多就開始整理整個項目涉及的故事和技術卡,按照兩周一迭代進行迭代計劃安排並與客戶確認,每個迭代第一周周三安排跟客戶showcase上一周的預定的交付結果,得到反饋並安排進行改進。官網項目比較順利,改造自定義了一下SSR框架就能開始進行開發,並且因為歷史原因,還能享受到上一個項目遺留的一些福利,當然也少不了一些坑。

小程序的時間比較緊,相當於整個複製了一遍官網的功能,主要是前端任務,後端可以復用官網後端,因此一開始就給團隊同學同步到整個項目的情況,讓大家有一個大概的心理準備。然後就是與官網類似的處理,整個交付內容進行迭代排期並與客戶確認,前期盡量能多做一些,避免後期怎麼努力都無法完成的囧鏡。

 

項目進行時

整個項目的過程中,PM會根據迭代完成情況靈活的找外援加入項目進行支援,以免交付延期。每日的站會(Standup Meeting)更新,讓團隊能對當前進度有一個大概的了解以及同步一些突發信息。定期的回顧會議(Retrospective Meeting)能暴露團隊內部問題,將風險扼殺於苗頭,鼓勵能為團隊帶來正向幫助的行為,及時停止不好的做法。

迭代會議(IPM)能讓團隊對下一個迭代具體要做的事情有一個詳細的了解,進行大致的估點,以便check開發進度情況。技術人員定期的CodeReview成為一個大家交流的時段,發現風險,指出問題,互相提高,還可以幫助新人快速的融入團隊。

根據團隊內部人員情況,可以定期進行一對一溝通,了解個人訴求或是給與近況反饋都是一個不錯的渠道。TL應考慮團隊內部人員提升自己的訴求,在一些安排上給與傾斜和鼓勵,發現問題也需要提前制止。

 

不足之處

  • 後期對卡牆(Jira)的管理鬆懈。導致有些問題反覆修改,且丟失context
  • 項目對運營後台有一些的定製化配置,沒有提前準備運營需要了解的後台操作資料和培訓,導致後期花費大量精力幫助運營進行後台配置與更新
  • 人員(QA)變動頻繁。公司處於高速發展階段,項目經歷了4個QA,因此有些context可能丟失,測試不到位,導致項目上線出了一些低級問題。比如上線后發現部分瀏覽器有支付兼容問題
  • 甲乙方定位太角色化,不能站在專業角度評估客戶需求(項目做完感覺都一樣,客戶是爸爸)
  • 與第三方合作交付產物管控不到位,導致第三方設計稿的延遲影響到我們的交付計劃
  • 與客戶溝通的需求,後面有一些沒有進行郵件確認,導致交付驗收階段因一些需求上的問題產生不愉快(這個完全沒必要的)
  • 對第三方系統的了解不充分和集成系統的需求整理不清晰導致後續一系列的開發、測試都不到位,以致上線出了不可控的問題

 

項目總結

  • 提前評估項目的風險點,且在項目進行過程中持續維護,後期安排足夠的時間進行調研與分析
  • 與第三方合作一定要有自己的規劃,並且將定好的規劃提前與第三方確認時間,然後派人提前專門細緻的了解第三方需求詳細點,確定好具體的業務場景,再來規劃己方與第三方的具體集成的點。此外,在進行的過程中,還應注意定時檢查合作進度,管控風險
  • 與客戶溝通的所有需求都要進行郵件的二次確認,一個是能夠對所有需求來源有所記錄,另一個是能避免後面的不必要的消耗
  • 開發管理不能鬆懈,盡量做到所有的改動都能有卡,能夠進行追溯
  • 對後期交付時所需要的資料提前準備,對需要進行培訓的人員提前約好時間進行溝通培訓

在前端這塊的管理上,做的還不夠。前期經常codereview,然後效果都還不錯,讓我有了一些錯覺就是當前團隊趨於穩定,中後期即便是加班比較多,大家氣氛這塊我覺得都還好。不過在項目後期的時候,有些疏於管理,然後大家有些人也被分配到了其他項目,和同事們的交流不夠,沒有及時的顧及到一些個人情緒,這塊是可以加強的。

作為一個Lead,不論同事是否還在一個項目都應該及時的去了解近況,給與自己力所能及的幫助,這樣才能產生向心力,以幫助一些比較迷茫的同學找到方向,看見燈塔。

整個項目時間不長,得失還是挺多的,不論是管理還是技術上,都會有一些心得。然後項目的ROI還不錯,得到公司領導的肯定,最後客戶那邊的反饋也還不錯,算是對大家努力的一種認可。

ps: 及時總結,靜心沉澱;如風少年,砥礪前行。

如想了解更多,請移步

歡迎關注我的公眾號 “和F君一起xx”

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

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

附009.Kubernetes永久存儲之GlusterFS獨立部署

一 前期準備

1.1 基礎知識


Heketi提供了一個RESTful管理界面,可以用來管理GlusterFS卷的生命周期。Heketi會動態在集群內選擇bricks構建所需的volumes,從而確保數據的副本會分散到集群不同的故障域內。同時Heketi還支持任意數量的ClusterFS集群。

提示:本實驗基於glusterfs和Kubernetes分開部署,heketi管理glusterfs,Kubernetes使用heketi提供的API,從而實現glusterfs的永久存儲,,而非Kubernetes部署glusterfs。

1.2 架構示意






提示:本實驗Heketi僅管理單zone的glusterfs集群。

1.3 相關規劃

































主機 IP 磁盤 備註
servera 172.24.8.41 sdb glusterfs節點
serverb 172.24.8.42 sdb glusterfs節點
serverc 172.24.8.43 sdb glusterfs節點
heketi 172.24.8.44 Heketi主機










































servera serverb serverc
PV sdb1 sdb1 sdb1
VG vg0 vg0 vg0
LV datalv datalv datalv
bricks目錄 /bricks/data /bricks/data /bricks/data

1.4 其他準備


所有節點NTP配置;

所有節點添加相應主機名解析:

172.24.8.41 servera

172.24.8.42 serverb

172.24.8.43 serverc

172.24.8.44 heketi

注意:若非必要,建議關閉防火牆和SELinux。

二 規劃相應存儲卷

2.1 劃分LVM

  1 [root@servera ~]# fdisk /dev/sdb				#創建lvm的sdb1,過程略
  2 [root@servera ~]# pvcreate /dev/sdb1			#使用/dev/vdb1創建PV
  3 [root@servera ~]# vgcreate vg0 /dev/sdb1			#創建vg
  4 [root@servera ~]# lvcreate -L 15G -T vg0/thinpool		#創建支持thin的lv池
  5 [root@servera ~]# lvcreate -V 10G -T vg0/thinpool -n datalv	#創建相應brick的lv
  6 [root@servera ~]# vgdisplay					#驗證確認vg信息
  7 [root@servera ~]# pvdisplay					#驗證確認pv信息
  8 [root@servera ~]# lvdisplay					#驗證確認lv信息



提示:serverb、serverc類似操作,根據規劃需求創建完所有基於LVM的brick。

三 安裝glusterfs

3.1 安裝相應RPM源

  1 [root@servera ~]# yum -y install centos-release-gluster


提示:serverb、serverc、client類似操作,安裝相應glusterfs源;

安裝相應源之後,會在/etc/yum.repos.d/目錄多出文件CentOS-Storage-common.repo,內容如下:

  1 # CentOS-Storage.repo
  2 #
  3 # Please see http://wiki.centos.org/SpecialInterestGroup/Storage for more
  4 # information
  5 
  6 [centos-storage-debuginfo]
  7 name=CentOS-$releasever - Storage SIG - debuginfo
  8 baseurl=http://debuginfo.centos.org/$contentdir/$releasever/storage/$basearch/
  9 gpgcheck=1
 10 enabled=0
 11 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-Storage


3.2 安裝glusterfs

  1 [root@servera ~]# yum -y install glusterfs-server


提示:serverb、serverc類似操作,安裝glusterfs服務端。

3.3 啟動glusterfs

  1 [root@servera ~]# systemctl start glusterd
  2 [root@servera ~]# systemctl enable glusterd



提示:serverb、serverc類似操作,所有節點啟動glusterfs服務端;

安裝完glusterfs之後建議exit退出終端重新登錄,從而可以補全glusterfs相關命令。

3.4 添加信任池

  1 [root@servera ~]# gluster peer probe serverb
  2 peer probe: success.
  3 [root@servera ~]# gluster peer probe serverc
  4 peer probe: success.
  5 [root@servera ~]# gluster peer status		#查看信任池狀態
  6 [root@servera ~]# gluster pool list			#查看信任池列表




提示:加信任池的操作,只需要在servera、serverb、serverc所有集群節點主機中的任意一台上面執行添加其他三個節點的操作即可。

提示:若未關閉防火牆,在添加信任池之前必須放通防火牆相應規則,操作如下:

  1 [root@servera ~]# firewall­cmd ­­permanent ­­add­service=glusterfs
  2 [root@servera ~]# firewall­cmd ­­permanent ­­add­service=nfs
  3 [root@servera ~]# firewall­cmd ­­permanent ­­add­service=rpc­bind
  4 [root@servera ~]# firewall­cmd ­­permanent ­­add­service=mountd
  5 [root@servera ~]# firewall­cmd ­­permanent ­­add­port=5666/tcp
  6 [root@servera ~]# firewall­cmd ­­reload


四 部署Heketi

4.1 安裝heketi服務

  1 [root@heketi ~]# yum -y install centos-release-gluster
  2 [root@heketi ~]# yum -y install heketi heketi-client


4.2 配置heketi

  1 [root@heketi ~]# vi /etc/heketi/heketi.json
  2 {
  3   "_port_comment": "Heketi Server Port Number",
  4   "port": "8080",					#默認端口
  5 
  6   "_use_auth": "Enable JWT authorization. Please enable for deployment",
  7   "use_auth": true,					#基於安全考慮開啟認證
  8 
  9   "_jwt": "Private keys for access",
 10   "jwt": {
 11     "_admin": "Admin has access to all APIs",
 12     "admin": {
 13       "key": "admin123"					#管理員密碼
 14     },
 15     "_user": "User only has access to /volumes endpoint",
 16     "user": {
 17       "key": "xianghy"					#普通用戶
 18     }
 19   },
 20 
 21   "_glusterfs_comment": "GlusterFS Configuration",
 22   "glusterfs": {
 23     "_executor_comment": [
 24       "Execute plugin. Possible choices: mock, ssh",
 25       "mock: This setting is used for testing and development.",	#用於測試
 26       "      It will not send commands to any node.",
 27       "ssh:  This setting will notify Heketi to ssh to the nodes.",	#ssh方式
 28       "      It will need the values in sshexec to be configured.",
 29       "kubernetes: Communicate with GlusterFS containers over",		#在GlusterFS由kubernetes創建時採用
 30       "            Kubernetes exec api."
 31     ],
 32     "executor": "ssh",
 33 
 34     "_sshexec_comment": "SSH username and private key file information",
 35     "sshexec": {
 36       "keyfile": "/etc/heketi/heketi_key",
 37       "user": "root",
 38       "port": "22",
 39       "fstab": "/etc/fstab"
 40     },
 41 ……
 42 ……
 43     "loglevel" : "warning"
 44   }
 45 }


4.3 配置免秘鑰

  1 [root@heketi ~]# ssh-keygen -t rsa -q -f /etc/heketi/heketi_key -N ""
  2 [root@heketi ~]# chown heketi:heketi /etc/heketi/heketi_key
  3 [root@heketi ~]# ssh-copy-id -i /etc/heketi/heketi_key.pub root@servera
  4 [root@heketi ~]# ssh-copy-id -i /etc/heketi/heketi_key.pub root@serverb
  5 [root@heketi ~]# ssh-copy-id -i /etc/heketi/heketi_key.pub root@serverc


4.4 啟動heketi

  1 [root@heketi ~]# systemctl enable heketi.service
  2 [root@heketi ~]# systemctl start heketi.service
  3 [root@heketi ~]# systemctl status heketi.service
  4 [root@heketi ~]# curl http://localhost:8080/hello		#測試訪問
  5 Hello from Heketi


4.5 配置Heketi拓撲


       拓撲信息用於讓Heketi確認可以使用的存儲節點、磁盤和集群,必須自行確定節點的故障域。故障域是賦予一組節點的整數值,這組節點共享相同的交換機、電源或其他任何會導致它們同時失效的組件。必須確認哪些節點構成一個集群,Heketi使用這些信息來確保跨故障域中創建副本,從而提供數據冗餘能力,Heketi支持多個Gluster存儲集群。

配置Heketi拓撲注意以下幾點:

  • 可以通過topology.json文件定義組建的GlusterFS集群;
  • topology指定了層級關係:clusters –> nodes –> node/devices –> hostnames/zone;
  • node/hostnames字段的manage建議填寫主機ip,指管理通道,注意當heketi服務器不能通過hostname訪問GlusterFS節點時不能填寫hostname;
  • node/hostnames字段的storage建議填寫主機ip,指存儲數據通道,與manage可以不一樣,生產環境管理網絡和存儲網絡建議分離;
  • node/zone字段指定了node所處的故障域,heketi通過跨故障域創建副本,提高數據高可用性質,如可以通過rack的不同區分zone值,創建跨機架的故障域;
  • devices字段指定GlusterFS各節點的盤符(可以是多塊盤),必須是未創建文件系統的裸設備。

  1 [root@heketi ~]# vi /etc/heketi/topology.json
  2 {
  3     "clusters": [
  4         {
  5             "nodes": [
  6                 {
  7                     "node": {
  8                         "hostnames": {
  9                             "manage": [
 10                                 "172.24.8.41"
 11                             ],
 12                             "storage": [
 13                                 "172.24.8.41"
 14                             ]
 15                         },
 16                         "zone": 1
 17                     },
 18                     "devices": [
 19                         "/dev/mapper/vg0-datalv"
 20                     ]
 21                 },
 22                 {
 23                     "node": {
 24                         "hostnames": {
 25                             "manage": [
 26                                 "172.24.8.42"
 27                             ],
 28                             "storage": [
 29                                 "172.24.8.42"
 30                             ]
 31                         },
 32                         "zone": 1
 33                     },
 34                     "devices": [
 35                         "/dev/mapper/vg0-datalv"
 36                     ]
 37                 },
 38                 {
 39                     "node": {
 40                         "hostnames": {
 41                             "manage": [
 42                                 "172.24.8.43"
 43                             ],
 44                             "storage": [
 45                                 "172.24.8.43"
 46                             ]
 47                         },
 48                         "zone": 1
 49                     },
 50                     "devices": [
 51                         "/dev/mapper/vg0-datalv"
 52                     ]
 53                 }
 54             ]
 55         }
 56     ]
 57 }
 58 
 59 [root@heketi ~]# echo "export HEKETI_CLI_SERVER=http://heketi:8080" >> /etc/profile.d/heketi.sh
 60 [root@heketi ~]# echo "alias heketi-cli='heketi-cli --user admin --secret admin123'" >> .bashrc
 61 [root@heketi ~]# source /etc/profile.d/heketi.sh
 62 [root@heketi ~]# source .bashrc
 63 [root@heketi ~]# echo $HEKETI_CLI_SERVER
 64 http://heketi:8080
 65 [root@heketi ~]# heketi-cli --server $HEKETI_CLI_SERVER --user admin --secret admin123 topology load --json=/etc/heketi/topology.json




4.6 集群管理

  1 [root@heketi ~]# heketi-cli cluster list					#集群列表
  2 [root@heketi ~]# heketi-cli cluster info aa83b0045fafa362bfc7a8bfee0c24ad	#集群詳細信息
  3 Cluster id: aa83b0045fafa362bfc7a8bfee0c24ad
  4 Nodes:
  5 189ee41572ebf0bf1e297de2302cfb39
  6 46429de5666fc4c6cc570da4b100465d
  7 be0209387384299db34aaf8377c3964c
  8 Volumes:
  9 
 10 Block: true
 11 
 12 File: true
 13 [root@heketi ~]# heketi-cli topology info aa83b0045fafa362bfc7a8bfee0c24ad	#查看拓撲信息




  1 [root@heketi ~]# heketi-cli node list						#卷信息
  2 Id:189ee41572ebf0bf1e297de2302cfb39     Cluster:aa83b0045fafa362bfc7a8bfee0c24ad
  3 Id:46429de5666fc4c6cc570da4b100465d     Cluster:aa83b0045fafa362bfc7a8bfee0c24ad
  4 Id:be0209387384299db34aaf8377c3964c     Cluster:aa83b0045fafa362bfc7a8bfee0c24ad
  5 [root@heketi ~]# heketi-cli node info 189ee41572ebf0bf1e297de2302cfb39		#節點信息
  6 [root@heketi ~]# heketi-cli volume create --size=2 --replica=2			#默認為3副本的replica模式



  1 [root@heketi ~]# heketi-cli volume list						#卷信息
  2 [root@heketi ~]# heketi-cli volume info 7da55685ebeeaaca60708cd797a5e391
  3 [root@servera ~]# gluster volume info						#通過glusterfs節點查看


4.7 測試驗證

  1 [root@heketi ~]# yum -y install centos-release-gluster
  2 [root@heketi ~]# yum -y install glusterfs-fuse					#安裝glusterfs-fuse
  3 [root@heketi ~]# mount -t glusterfs 172.24.8.41:vol_7da55685ebeeaaca60708cd797a5e391 /mnt



  1 [root@heketi ~]# umount /mnt
  2 [root@heketi ~]# heketi-cli volume delete 7da55685ebeeaaca60708cd797a5e391	#驗證完畢刪除



參考:https://www.jianshu.com/p/1069ddaaea78

https://www.cnblogs.com/panwenbin-logs/p/10231859.html

五 Kubernetes動態掛載glusterfs

5.1 StorageClass動態存儲


kubernetes共享存儲provider模式:

靜態模式(Static):集群管理員手工創建PV,在定義PV時設置後端存儲的特性;

動態模式(Dynamic):集群管理員不需要手工創建PV,而是通過StorageClass的設置對後端存儲進行描述,標記為某種”類型(Class)”;此時要求PVC對存儲的類型進行說明,系統將自動完成PV的創建及與PVC的綁定;PVC可以聲明Class為””,說明PVC禁止使用動態模式。

基於StorageClass的動態存儲供應整體過程如下圖所示:


  1. 集群管理員預先創建存儲類(StorageClass);
  2. 用戶創建使用存儲類的持久化存儲聲明(PVC:PersistentVolumeClaim);
  3. 存儲持久化聲明通知系統,它需要一個持久化存儲(PV: PersistentVolume);
  4. 系統讀取存儲類的信息;
  5. 系統基於存儲類的信息,在後台自動創建PVC需要的PV;
  6. 用戶創建一個使用PVC的Pod;
  7. Pod中的應用通過PVC進行數據的持久化;
  8. 而PVC使用PV進行數據的最終持久化處理。


提示:關於Kubernetes的部署參考《附003.Kubeadm部署Kubernetes》。

5.2 定義StorageClass


關鍵字說明:

  • provisioner:表示存儲分配器,需要根據後端存儲的不同而變更;
  • reclaimPolicy: 默認即”Delete”,刪除pvc后,相應的pv及後端的volume,brick(lvm)等一起刪除;設置為”Retain”時則保留數據,若需刪除則需要手工處理;
  • resturl:heketi API服務提供的url;
  • restauthenabled:可選參數,默認值為”false”,heketi服務開啟認證時必須設置為”true”;
  • restuser:可選參數,開啟認證時設置相應用戶名;
  • secretNamespace:可選參數,開啟認證時可以設置為使用持久化存儲的namespace;
  • secretName:可選參數,開啟認證時,需要將heketi服務的認證密碼保存在secret資源中;
  • clusterid:可選參數,指定集群id,也可以是1個clusterid列表,格式為”id1,id2”;
  • volumetype:可選參數,設置卷類型及其參數,如果未分配卷類型,則有分配器決定卷類型;如”volumetype: replicate:3”表示3副本的replicate卷,”volumetype: disperse:4:2”表示disperse卷,其中‘4’是數據,’2’是冗餘校驗,”volumetype: none”表示distribute卷


提示:關於glusterfs各種不同類型的卷見《004.RHGS-創建volume》。

  1 [root@k8smaster01 ~]# kubectl create ns heketi		#創建命名空間
  2 [root@k8smaster01 ~]# echo -n "admin123" | base64		#將密碼轉換為64位編碼
  3 YWRtaW4xMjM=
  4 [root@k8smaster01 ~]# mkdir -p heketi
  5 [root@k8smaster01 ~]# cd heketi/
  6 [root@k8smaster01 ~]# vi heketi-secret.yaml			#創建用於保存密碼的secret
  7 apiVersion: v1
  8 kind: Secret
  9 metadata:
 10   name: heketi-secret
 11   namespace: heketi
 12 data:
 13   # base64 encoded password. E.g.: echo -n "mypassword" | base64
 14   key: YWRtaW4xMjM=
 15 type: kubernetes.io/glusterfs
 16 [root@k8smaster01 heketi]# kubectl create -f heketi-secret.yaml	#創建heketi
 17 [root@k8smaster01 heketi]# kubectl get secrets -n heketi
 18 NAME                  TYPE                                  DATA   AGE
 19 default-token-5sn5d   kubernetes.io/service-account-token   3      43s
 20 heketi-secret         kubernetes.io/glusterfs               1      5s
 21 [root@kubenode1 heketi]# vim gluster-heketi-storageclass.yaml	#正式創建StorageClass
 22 apiVersion: storage.k8s.io/v1
 23 kind: StorageClass
 24 metadata:
 25   name: gluster-heketi-storageclass
 26 parameters:
 27   resturl: "http://172.24.8.44:8080"
 28   clusterid: "aa83b0045fafa362bfc7a8bfee0c24ad"
 29   restauthenabled: "true"					#若heketi開啟認證此處也必須開啟auth認證
 30   restuser: "admin"
 31   secretName: "heketi-secret"				#name/namespace與secret資源中定義一致
 32   secretNamespace: "heketi"
 33   volumetype: "replicate:3"
 34 provisioner: kubernetes.io/glusterfs
 35 reclaimPolicy: Delete
 36 [root@k8smaster01 heketi]# kubectl create -f gluster-heketi-storageclass.yaml



注意:storageclass資源創建后不可變更,如修改只能刪除后重建。

  1 [root@k8smaster01 heketi]# kubectl get storageclasses		#查看確認
  2 NAME                          PROVISIONER               AGE
  3 gluster-heketi-storageclass   kubernetes.io/glusterfs   85s
  4 [root@k8smaster01 heketi]# kubectl describe storageclasses gluster-heketi-storageclass




5.3 定義PVC

  1 [root@k8smaster01 heketi]# cat gluster-heketi-pvc.yaml
  2 apiVersion: v1
  3 metadata:
  4   name: gluster-heketi-pvc
  5   annotations:
  6     volume.beta.kubernetes.io/storage-class: gluster-heketi-storageclass
  7 spec:
  8   accessModes:
  9   - ReadWriteOnce
 10   resources:
 11     requests:
 12       storage: 1Gi



注意:accessModes可有如下簡寫:

  • ReadWriteOnce:簡寫RWO,讀寫權限,且只能被單個node掛載;
  • ReadOnlyMany:簡寫ROX,只讀權限,允許被多個node掛載;
  • ReadWriteMany:簡寫RWX,讀寫權限,允許被多個node掛載。

  1 [root@k8smaster01 heketi]# kubectl create -f gluster-heketi-pvc.yaml
  2 [root@k8smaster01 heketi]# kubectl get pvc
  3 [root@k8smaster01 heketi]# kubectl describe pvc gluster-heketi-pvc
  4 [root@k8smaster01 heketi]# kubectl get pv
  5 [root@k8smaster01 heketi]# kubectl describe pv pvc-5f7420ef-082d-11ea-badf-000c29fa7a79




  1 [root@k8smaster01 heketi]# kubectl describe endpoints glusterfs-dynamic-5f7420ef-082d-11ea-badf-000c29fa7a79




提示:由上可知:PVC狀態為Bound,Capacity為1G。查看PV詳細信息,除容量,引用storageclass信息,狀態,回收策略等外,同時可知GlusterFS的Endpoint與path。EndpointsName為固定格式:glusterfs-dynamic-PV_NAME,且endpoints資源中指定了掛載存儲時的具體地址。

5.4 確認查看


通過5.3所創建的信息:

  • volume與brick已經創建;
  • 主掛載點(通信)在172.24.8.41節點,其餘兩個節點備選;
  • 三副本的情況下,所有節點都會創建brick。

  1 [root@heketi ~]# heketi-cli topology info			#heketi主機查看
  2 [root@serverb ~]# lsblk						#glusterfs節點查看
  3 [root@serverb ~]# df -hT					#glusterfs節點查看
  4 [root@servera ~]# gluster volume list				#glusterfs節點查看
  5 [root@servera ~]# gluster volume info vol_e4c948687239df9833748d081ddb6fd5




5.5 Pod掛載測試

  1 [root@xxx ~]# yum -y install centos-release-gluster
  2 [root@xxx ~]# yum -y install glusterfs-fuse					#安裝glusterfs-fuse



提示:所有需要使用glusterfs volume的Kubernetes節點都必須安裝glusterfs-fuse以便於正常掛載,同時版本需要和glusterfs節點一致。

  1 [root@k8smaster01 heketi]# vi gluster-heketi-pod.yaml
  2 kind: Pod
  3 apiVersion: v1
  4 metadata:
  5   name: gluster-heketi-pod
  6 spec:
  7   containers:
  8   - name: gluster-heketi-container
  9     image: busybox
 10     command:
 11     - sleep
 12     - "3600"
 13     volumeMounts:
 14     - name: gluster-heketi-volume			#必須和volumes中name一致
 15       mountPath: "/pv-data"
 16       readOnly: false
 17   volumes:
 18   - name: gluster-heketi-volume
 19     persistentVolumeClaim:
 20       claimName: gluster-heketi-pvc			#必須和5.3創建的PVC中的name一致
 21 [root@k8smaster01 heketi]# kubectl create -f gluster-heketi-pod.yaml -n heketi		#創建Pod


5.6 確認驗證

  1 [root@k8smaster01 heketi]# kubectl get pod -n heketi | grep gluster
  2 gluster-heketi-pod          1/1     Running   0          2m43s
  3 [root@k8smaster01 heketi]# kubectl exec -it gluster-heketi-pod /bin/sh		#進入Pod寫入測試文件
  4 / # cd /pv-data/
  5 /pv-data # echo "This is a file!" >> a.txt
  6 /pv-data # echo "This is b file!" >> b.txt
  7 /pv-data # ls
  8 a.txt  b.txt
  9 [root@servera ~]# df -hT					#在glusterfs節點查看Kubernetes節點的測試文件
 10 [root@servera ~]# cd /var/lib/heketi/mounts/vg_47c90d90e03de79696f90bd94cfccdde/brick_721243c3e0cf8a2372f05d5085a4338c/brick/
 11 [root@servera brick]# ls
 12 [root@servera brick]# cat a.txt
 13 [root@servera brick]# cat b.txt




5.7 刪除資源

  1 [root@k8smaster01 heketi]# kubectl delete -f gluster-heketi-pod.yaml
  2 [root@k8smaster01 heketi]# kubectl delete -f gluster-heketi-pvc.yaml
  3 [root@k8smaster01 heketi]# kubectl get pvc
  4 [root@k8smaster01 heketi]# kubectl get pv
  5 [root@servera ~]# gluster volume list
  6 No volumes present in cluster



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

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選