.NET Core前後端分離快速開發框架(Core.3.0+AntdVue)

.NET Core前後端分離快速開發框架(Core.3.0+AntdVue)

目錄

引言

時間真快,轉眼今年又要過去了。回想今年,依次開源發布了Colder.Fx.Net.AdminLTE(254Star)Colder.Fx.Core.AdminLTE(335Star)DotNettySocket(82Star)IdHelper(47Star),這些框架及組件都是本着以實際出發,實事求是的態度,力求提高開發效率(我自己都是第一個使用者),目前來看反響不錯。但是隨着前端和後端技術的不斷變革,尤其是前端,目前大環境已經是前後端完全分離為主的開發模式,在這樣的大環境和必然趨勢之下,傳統的MVC就顯得有些落伍了。在這樣的背景下,一款前後端分離的.NET開發框架就顯得尤為必要,由此便定了框架的升級目標:前後端分離

首先後端技術的選擇,從目前的數據來看,.NET Core的發展遠遠快於.NET Framework,最簡單的分析就是Colder.Fx.Core.AdminLTE發布比Colder.Fx.Net.AdminLTE晚,但是星星卻後來居上而且比前者多30%,並且這個差距在不斷擴大,由點及面的分析可以看出我們廣大.NET開發人員學習的熱情和积極向上的態度,並不是某些人所認為的那麼不堪(走自己的路,讓別人說去吧)。大環境上微軟积極擁抱開源,大力發展.NET Core, 可以說前途一片光明。因此後端決定採用 .NET Core3.0 ,不再浪費精力去支持.NET Framework。

然後是前端技術選擇,首選是三大js框架選擇,也是從實際出發,Vue相對其它而言更加容易上手,並且功能也毫不遜色,深得各種大小公司喜歡,如果偏要說缺點的話,那就是對TS支持不行,但是即將發布Vue3.0肯定會改變這一缺陷。選擇了Vue之後,然後就是UI框架的選擇了,這裏的選擇更多了,我選擇了Ant Design Vue,理由便是簡潔方便,十分符合我的設計理念。

技術選型完畢之後便進入研發,由於鄙人前端比較菜,因此需要從頭學Vue2.x全家桶,從開始到現在差不多經歷3個月,在預期之內。其實學習並使用前端的Vue2.x全家桶並不難,還是比較容易上手的,所以在此給沒有前後端分離開發經驗的老哥打一記預防針,不要退縮,要知難而上,學習永無止境。

某些老哥可能比較直接粗暴,嫌我BBB嘮叨,下面直接上地址
代碼(GitHub):
文檔(GitHub):
代碼(碼雲鏡像):
文檔(碼雲鏡像):
在線預覽地址
由於服務器是阿里雲的86服務器,帶寬1M小水管,因此將前端部署到碼雲上了,在此多謝碼雲,後端部署在阿里雲86服務器CentOS7上。整個技術棧使用.NET Core + PostggreSQL+ Ant Design Vue + CentOS7+Nginx+Dokcer+jenkins,囊括了從快速開發到自動化部署一條龍,開源免費並具有高性能、高移植性、高拓展性(小公司創業選型+個人接單利器

簡介

本框架為.NET Core3.0+Ant Design Vue版

本框架旨在極大的提高開發效率

使用技術棧:
後端:採用.NET Core平台,ASP.NET Core3.0,C#語言(使用反射等高級技術),Entity FrameworkCore(數據庫ORM框架)。
使用數據倉儲模式,抽象化數據庫操作(CRUD等)、支持事務處理以及分佈式事務處理(跨庫)
支持數據庫讀寫分離、分庫分表及事務(僅支持單表操作,不支持多表) 全面採用Autofac作為IOC容器,面向接口編程,全面解耦
集成多種工具類庫以及操作拓展
數據庫:支持SqlServer,PostgreSQL,MySQL,Oracle(框架使用簡單工廠,工廠方法,抽象工廠,可輕鬆更換數據庫),Redis作為分佈式緩存
前端:Vue2.x全家桶+Ant Design Vue,其中集成常用組件,力求方便項目開發。

具體技術實施:
項目採用前後端完全分離模式,並採用嚴格分層模式,極大的增加聚合度,降低耦合度,
提高代碼的健壯性,可維護性。
前後端通過JWT進行身份驗證,通過數據接口操作數據,統一使用JSON作為數據格式,並使用默認接口簽名算法保證接口的安全性。

功能架構部分詳解:
快速開發:此功能為框架的核心,通過選擇數據庫中的表,就能自動生成對應的實體層、業務邏輯層、控制器、前端頁面Vue文件,無需編寫代碼即可生成基本的CRUD操作。
接口密鑰管理:管理接口的密鑰,若開啟接口簽名的規則,則前端需要通過給接口簽名才能夠正常訪問後台接口。
權限管理:使用基本的RBAC權限控制,支持操作權限、接口權限以及數據權限

框架主要功能及特色如下

功能 詳細描述
用戶登錄 用戶登錄、密碼修改
系統用戶管理 系統用戶管理
角1色管理 角色管理
部門管理 部門管理、天然多級
權限管理 使用RBAC權限體系,基於角色的權限管理,支持菜單權限、操作權限(按鈕權限)、接口權限、數據權限
系統日誌 支持多彩控制台、文件、數據庫和ElasticSearch記錄日誌,框架全局異常自動捕捉,多級別記錄
快速開發 通過數據庫直接生成實體層、業務邏輯層、控制器層以及前端頁面Vue代碼,無需編碼即可實現CURD
數據庫操作封裝 使用基於EF的倉儲模式、封裝常用的CURD,支持單庫事物和分佈式事物
多數據庫支持 使用基於EF的倉儲模式,支持各大主流關係型數據庫(SQLServer、MySQL、PostgreSQL和Oracle)
超強移植性 使用抽象工廠封裝數據庫操作層,切換數據庫0代碼修改
支持軟刪除 一鍵切換刪除模式,支持物理刪除和軟刪除,對業務操作透明
緩存支持 支持系統自帶緩存和Redis緩存、封裝操作接口、簡單易用
前後端完全分離 前端使用Vue2.x全家桶+Ant Design Vue,界面簡潔美觀,組件化開發
集成JWT驗證 框架使用JWT作為身份驗證,擺脫Cookie苦海,分佈式拓展毫無壓力
集成對外接口簽名算法 框架對外接口可以開啟超強嚴格簽名校驗(防抵賴、防偽造、防重複調用),保障系統安全性
頁面響應式 前端為單頁應用,無iframe,各大主流瀏覽器支持友好
拓展 其它各種幫助類庫及插件

其相關版本請看下錶:

.NET版本 前端UI 地址
Core3.0 Ant Design Vue
Core2.2 AdminLTE
.NET4.72 AdminLTE
.NET4.52 Easyui
Core2.1 Easyui
.NET4.0 Easyui

後台效果展示如下:

環境搭建

開發環境要求:

操作系統:Windows 10
後端開發工具:Visual Studio 2019+
前端開發工具:Visual Studio Code,安裝nodejs,yarn
SDK:安裝.NET Core SKD 3.0 及以上
數據庫:SQLServer2008 R2及以上

基礎數據庫構建:

  • 數據庫創建
    目錄”/docs/初始化文件”中有所需的數據庫資料

    先手動創建數據庫,然後執行對應的SQL腳本即可

  • 連接字符串配置
    打開src目錄下Colder.Admin.AntdVue的解決方案,如下圖

如下圖所示依次展開05.Coldairarrow.Api/appsettings.json,配置數據庫連接字符串,name不用修改,connectionString改為上述創建的數據庫(若不清楚數據庫連接字符串請自行百度搜索教程)

數據庫設計規範

由於本框架支持自動生成代碼的核心功能,此功能是根據數據庫的表結構來生成代碼的
因此規定每張表都有一個主鍵,列名為Id,類型為字符串,實際添加數據時默認使用SnowflakeId(雪花Id,Twitter設計的分佈式趨勢自增Id,若不清楚請自行百度相關資料),表中的每個列都需要有描述信息(建議這樣操作,若不按照這個標準則需要一些額外的改動才能夠成功運行)。每張表都需要Id、CreateTime、CreatorId、CreatorRealName這幾個必帶字段

運行

後端:打開解決方案=>還原nuget包=>配置數據庫=>運行(05.Coldairarrow.Api設為啟動項目)
後台成功運行後會自動打開swagger

前端: 確保已安裝nodejsyarn
用VS Code 打開文件夾src\Coldairarrow.Web

輸入命令:yarn
輸入命令:yarn run serve
成功運行后即可打開登錄頁面

輸入賬號:Admin,密碼:123456進入後台主頁

使用教程

全局配置

在01.Coldairarrow.Util中的GlobalSwitch類中,設置了各個參數,其中RunModelDatabaseType需要重點關注一下,其它參數請看註釋。

快速開發

此功能為本框架的核心功能,能夠自動生產完整的可運行代碼,具體使用如下:

  • 配置數據源

首選需要有數據庫源,因為代碼生成是根據數據庫表來生成的。
菜單:開發=>數據庫連接

若列表中沒有目標數據源,則添加數據庫連接

數據連接名、連接字符串、數據庫類型即可。添加完成后即可看到連接字符串信息。

  • 生成代碼

有了數據庫連接之後,即可進行代碼生成。
菜單:開發=>代碼生成

選擇數據庫,然後勾選需要生成代碼的數據庫表,點擊生成代碼會彈出生成選項(這裏演示勾選 Base_BuildTest,其餘表全是系統基礎表,不要勾選,否則會被覆蓋,導致異常,請勾選自己的業務表進行生成):

生成選項中可以選擇需要生成的類型,默認生成全部:實體層、業務層、接口層(即控制器)和頁面(Vue前端頁面代碼)。
生成區域請輸入業務模塊名(例如系統叫Base_Manage),請按具體業務填入(必填)
這裏示例填寫TestManage,點擊生成按鈕,即可完成代碼生成。生成后的代碼在項目解決方案中,將代碼文件包括進入項目

默認生成后的文件會被自動包括到解決方案中,若沒有則需要點擊显示所有文件按鈕,即可看到生成后的新文件

生成的實體層、業務邏輯層、控制器層代碼:

前端生成的代碼:

後端代碼添加后需要重新編譯下(F7),編譯后好可以看到有新的接口

前端生成代碼後會自動保存並編譯(別的文件修改保存也會自動編譯,畢竟編譯一次挺慢的),不放心可以Ctrl+C停止,然後再yarn run serve重新運行

代碼生成完畢,但是要展示到菜單上需要進行配置,並且所有業務菜單都是動態的(權限控制)
打開菜單:系統管理=>權限管理=>新建

菜單名:即需要显示的菜單名
上級菜單:菜單是多級樹狀的,可以放在某個菜單下面
類型:可以選擇菜單或頁面,這裡是具體的頁面,所以選頁面
路徑:頁面的路徑,菜單可以不配置,這裏配置為/TestManage/Base_BuildTest/List,這裏設置規則為:views文件夾為根路徑(即”/”),向下展開依次為/TestManage/Base_BuildTest/List,最後真正的列表頁為List.vue文件,表單頁為EditForm.vue文件
是否需要權限:若為“否”,則此頁面不限制權限,即所有人都能看
圖標:菜單显示圖標,具體到開發=>圖標選擇頁進行選擇
排序:若需要需要對菜單進行排序則設置,默認0,類型為int
頁面權限:頁面擁有的權限(權限值唯一,作為操作權限即接口權限的依據),詳見權限管理

確認保存,然後刷新整個頁面(F5),即可看到全新生成的菜單“生成測試”

整個代碼生成過程,無需編寫代碼即可完成一張表的CRUD,當然需要根據具體業務中進行相應的修改,本次示例中字段比較少,但是當一張表的字段很多時,那麼此功能能夠將開發效率提高几個檔次。

管理員登錄

默認超級管理員賬號為:Admin
密碼為:123456

系統用戶管理

管理系統登錄的用戶
菜單:系統=>用戶管理
點擊右側設置權限

系統角色管理

管理系統角色,角色是權限的載體,合理分配角色有利於權限管理
菜單:系統=>角色管理
操作中可以設置角色的權限,詳情見 模塊

權限管理

一般情況下,後台管理系統多少會涉及權限管理,因此本框架提供了一個靈活、高效、簡潔的權限管理系統。

首先,權限分為兩種,即操作權限數據權限,其中操作權限主要包括菜單權限和按鈕權限,在角色編輯表單中,給角色勾選需要的權限即可,用戶可以分配多個角色,繼承所有角色的權限。

如上圖,按需勾選,有人會疑問為什麼只有增、改和刪的權限而沒有查的權限,其實這裏考慮到了當勾選“用戶管理”時,就已經默認擁有“查”的權限了,這裏再設置“查”權限豈不是多此一舉,可以根據實際業務需求添加諸如申請、審核等權限,靈活應用。
這裏的樹狀是和菜單一一對應的,勾選哪些菜單就擁有哪些菜單

下面介紹下最常用的按鈕權限

如上圖,在需要控制權限的按鈕使用v-if=”hasPerm(‘Base_User.Add’)”,表示只有當用戶擁有權限值Base_User.Add才显示此按鈕,權限值就是權限表單中配置的權限值

這裏的按鈕級權限控制只能夠在前端控制操作入口,若系統對安全性要求較高,則需要控制接口權限

如上圖,在需要權限控制的接口加上ApiPermission特性即可,參數也為權限值,只有擁有此權限才能訪問此接口

數據權限比較複雜,若採用純SQL方式,那麼會更加複雜,本框架全程採用EF作為ORM框架,通過對IQueryable< T >進行過濾,即可完成數據權限控制,詳細使用方式見用戶管理

更詳細的使用方式,請參考源代碼中的用戶管理模塊(菜單權限、操作權限、數據權限、聯表查詢、業務層AOP等使用方式均可參考此模塊)

接口秘鑰管理

作為對外接口簽名的AppId和AppSecret管理
菜單:系統=>接口秘鑰管理

系統日誌

菜單:系統=>系統日誌

單庫事務

使用方式如下:

BaseBusiness<Base_UnitTest> _baseBus  = new BaseBusiness<Base_UnitTest>();
/*RunTransaction傳入執行具體數據庫操作的Action,操作中若出現異常會自動回滾事務,業務只需根據返回的transActionRes進行處理,返回類型為元組(bool Success, Exception ex),Success表示事務是否成功,ex為事務失敗異常信息*/
var transActionRes = _baseBus.RunTransaction(() =>
{
    var newData = _newData.DeepClone();
    newData.Id = Guid.NewGuid().ToString();
    newData.UserId = IdHelper.GetId();
    newData.UserName = IdHelper.GetId();
    _baseBus.Insert(_newData);
    _baseBus.Insert(newData);
});

跨庫事務

使用方式如下:

//第一個數據庫
IRepository _bus1 = DbFactory.GetRepository();
//另一個數據庫
IRepository _bus2 = DbFactory.GetRepository("BaseDb_Test");
_bus1.DeleteAll<Base_UnitTest>();
_bus2.DeleteAll<Base_UnitTest>();
Base_UnitTest data1 = new Base_UnitTest
{
    Id = Guid.NewGuid().ToString(),
    UserId = "1",
    UserName = Guid.NewGuid().ToString()
};
Base_UnitTest data2 = new Base_UnitTest
{
    Id = data1.Id,
    UserId = "1",
    UserName = Guid.NewGuid().ToString()
};
Base_UnitTest data3 = new Base_UnitTest
{
    Id = Guid.NewGuid().ToString(),
    UserId = "2",
    UserName = Guid.NewGuid().ToString()
};

new Action(() =>
{
    //創建並執行事務,使用方式與單庫一致
    var succcess = DistributedTransactionFactory.GetDistributedTransaction(_bus1, _bus2)
        .RunTransaction(() =>
        {
            _bus1.ExecuteSql("insert into Base_UnitTest(Id) values('10') ");
            _bus1.Insert(data1);
            _bus1.Insert(data2);
            _bus2.Insert(data1);
            _bus2.Insert(data3);
        });
    Assert.AreEqual(succcess.Success, false);
    Assert.AreEqual(_bus1.GetIQueryable<Base_UnitTest>().Count(), 0);
    Assert.AreEqual(_bus2.GetIQueryable<Base_UnitTest>().Count(), 0);
})();

讀寫分離分庫分表

本框架支持數據庫讀寫分離分庫分表(即Sharding),並且支持主流關係型數據庫(SQLServer、Oracle、MySQL、PostgreSQL),理論上只要EF支持那麼本框架支持。
由於技術原因以及結合實際情況,目前本框架僅支持單表的Sharding,即支持單表的CRUD、分頁、統計(數量、最大值、最小值、平均值),支持跨庫(表分散在不同的數據庫中,不同類型數據庫也支持)。具體如何使用如下:

  • Sharding配置
    首先、要進行分庫分表操作,那麼必要的配置必不可少。配置代碼如下:
ShardingConfigBootstrapper.Bootstrap()
    //添加數據源
    .AddDataSource("BaseDb", DatabaseType.SqlServer, dbBuilder =>
    {
        //添加物理數據庫
        dbBuilder.AddPhsicDb("BaseDb", ReadWriteType.ReadAndWrite);
    })
    //添加抽象數據庫
    .AddAbsDb("BaseDb", absTableBuilder =>
    {
        //添加抽象數據表
        absTableBuilder.AddAbsTable("Base_UnitTest", tableBuilder =>
        {
            //添加物理數據表
            tableBuilder.AddPhsicTable("Base_UnitTest_0", "BaseDb");
            tableBuilder.AddPhsicTable("Base_UnitTest_1", "BaseDb");
            tableBuilder.AddPhsicTable("Base_UnitTest_2", "BaseDb");
        }, new ModShardingRule("Base_UnitTest", "Id", 3));
    });

上述代碼中完成了Sharding的配置:
ShardingConfigBootstrapper.Bootstrap()在一個項目中只能執行一次,所以建議放到Application_Start中(ASP.NET Core中的Startup)
AddDataSource是指添加數據源,數據源可以看做抽象數據庫,一個數據源包含了一組同類型的物理數據庫,即實際的數據庫。一個數據源至少包含一個物理數據庫,多個物理數據庫需要開啟主從複製或主主複製,通過ReadWriteType(寫、讀、寫和讀)參數來指定數據庫的操作類型,通常將寫庫作為主庫,讀庫作為從庫。同一個數據源中的物理數據庫類型相同,表結構也相同。
配置好數據源后就可以通過AddAbsDb來添加抽象數據庫,抽象數據庫中需要添加抽象數據表。如上抽象表Base_UnitTest對應的物理表就是Base_UnitTest_0、Base_UnitTest_1與Base_UnitTest_2,並且這三張表都屬於數據源BaseDb。分表配置當然需要分表規則(即通過一種規則找到具體數據在哪張表中)。
上述代碼中使用了最簡單的取模分片規則
源碼如下:

可以看到其使用方式及優缺點。
另外還有一致性HASH分片規則

雪花Id的mod分片規則

上述的分片規則各有優劣,都實現IShardingRule接口,實際上只需要實現FindTable方法即可實現自定義分片規則。
實際使用中個人推薦使用雪花Id的mod分片規,這也是為什麼前面數據庫設計規範中默認使用雪花Id作為數據庫主鍵的原因(PS,之前版本使用GUID作為主鍵被各種嫌棄,這次看你們怎麼說)

  • 使用方式
    配置完成,下面開始使用,使用方式非常簡單,與平常使用基本一致
    首先獲取分片倉儲接口IShardingRepository
IShardingRepository _db = DbFactory.GetRepository().ToSharding();

然後即可進行數據操作:

Base_UnitTest _newData  = new Base_UnitTest
{
    Id = Guid.NewGuid().ToString(),
    UserId = "Admin",
    UserName = "超級管理員",
    Age = 22
};
List<Base_UnitTest> _insertList = new List<Base_UnitTest>
{
    new Base_UnitTest
    {
        Id = Guid.NewGuid().ToString(),
        UserId = "Admin1",
        UserName = "超級管理員1",
        Age = 22
    },
    new Base_UnitTest
    {
        Id = Guid.NewGuid().ToString(),
        UserId = "Admin2",
        UserName = "超級管理員2",
        Age = 22
    }
};
//添加單條數據
_db.Insert(_newData);
//添加多條數據
_db.Insert(_insertList);
//清空表
_db.DeleteAll<Base_UnitTest>();
//刪除單條數據
_db.Delete(_newData);
//刪除多條數據
_db.Delete(_insertList);
//刪除指定數據
_db.Delete<Base_UnitTest>(x => x.UserId == "Admin2");
//更新單條數據
_db.Update(_newData);
//更新多條數據
_db.Update(_insertList);
//更新單條數據指定屬性
_db.UpdateAny(_newData, new List<string> { "UserName", "Age" });
//更新多條數據指定屬性
_db.UpdateAny(_insertList, new List<string> { "UserName", "Age" });
//更新指定條件數據
_db.UpdateWhere<Base_UnitTest>(x => x.UserId == "Admin", x =>
{
    x.UserId = "Admin2";
});
//GetList獲取表的所有數據
var list=_db.GetList<Base_UnitTest>();
//GetIQPagination獲取分頁后的數據
var list=_db.GetIShardingQueryable<Base_UnitTest>().GetPagination(pagination);
//Max
var max=_db.GetIShardingQueryable<Base_UnitTest>().Max(x => x.Age);
//Min
var min=_db.GetIShardingQueryable<Base_UnitTest>().Min(x => x.Age);
//Average
var min=_db.GetIShardingQueryable<Base_UnitTest>().Average(x => x.Age);
//Count
var min=_db.GetIShardingQueryable<Base_UnitTest>().Count();
//事務,使用方式與普通事務一致
bool succcess = _db.RunTransaction(() =>
{
    _db.Insert(_newData);
    var newData2 = _newData.DeepClone();
    _db.Insert(newData2);
}).Success;
Assert.AreEqual(succcess, false);

上述操作中表面上是操作Base_UnitTest表,實際上卻在按照一定規則使用Base_UnitTest_0~2三張表,使分片對業務操作透明,極大提高開發效率
具體使用方式請參考單元測試源碼:
“\src\Coldairarrow.UnitTests\DataRepository\ShardingTest.cs”

常見疑問

如何進行聯表查詢

框架使用EF+LINQ進行聯表操作,核心在於對IQueryable< T >的使用,另可網上搜EF+LINQ的相關教程。

示例如下:
Base_User表左連接Base_Department表獲取DepartmentName屬性

//定義數據模型類
public class Base_UserTestDTO : Base_User
{
    public string DepartmentName { get; set; }
}

//即BaseBusiness中的Service
var db = DbFactory.GetRepository();
Expression<Func<Base_User, Base_Department, Base_UserTestDTO>> select = (a, b) => new Base_UserTestDTO
{
    DepartmentName = b.Name
};
select = select.BuildExtendSelectExpre();
var q = from a in db.GetIQueryable<Base_User>().AsExpandable()
        join b in db.GetIQueryable<Base_Department>() on a.DepartmentId equals b.Id into ab
        from b in ab.DefaultIfEmpty()
        select @select.Invoke(a, b);
//篩選
var where = LinqHelper.True<Base_UserTestDTO>();
where = where.And(x => x.UserName == "Admin");

//篩選並獲取分頁數據
var list = q.Where(where).GetPagination(new Pagination()).ToList();

源碼可參考Base_UserBusiness.GetDataList

如何切換數據庫類型

在01.Coldairarrow.Util項目中的GlobalSwitch,將DatabaseType改為需要的即可,對應的數據庫連接字符串當然也要改為對應數據庫的

如何使用多個數據庫

在具體的Business類中重寫父類BaseBusiness的構造函數即可,按照自己的需求重寫對應的構造函數,同時需要確保數據庫連接字符串已添加

若需要同時使用多個數據庫,或者需要多線程操作數據庫,需要使用

結語

歡迎使用本框架,若覺得不錯,請比心

Github歡迎星星:

博客園歡迎點贊:

QQ群2:579202910
個人QQ:862520575(歡迎技術支持及商務合作,提供.NET Core + Linux + Nginx+ jenkins + git整套持續集成快速開發平台

本人將會對這個快速開發框架不斷完善與維護,希望能夠幫助到各位

若遇到任何問題或需要技術支持,請聯繫我。

——學習永無止境,技術永無上限,代碼就是藝術——

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

【其他文章推薦】

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

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

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

※評比南投搬家公司費用收費行情懶人包大公開

[UWP]使用Win2D的BorderEffect實現圖片的平鋪功能

1. WPF有,而UWP沒有的圖片平鋪功能

在WPF中只要將ImageSource的TileMode屬性設置為Tile即可實現圖片的平鋪,具體可見WPF的這些文檔:

WPF圖片平鋪功能我幾乎沒用過,只是作為基礎中的基礎知識記住了用法。我以為那麼基礎的功能在UWP肯定有,根本不用懷疑,所以當我在UWP中發現這麼基礎的東西居然沒有時真的嚇了一跳。

上圖左面是WPF版本的TileBrush,右邊是UWP版本,可以看到UWP版本功能少了一大半。

這麼小的一個類,我覺得沒必要在這裏做簡化吧。幸好圖片平鋪可以使用Win2D里的實現。

2. UWP中的圖片平鋪功能

<Grid>
    <Rectangle x:Name="Background" />
</Grid>

假設有以上的XAML,要在名為Background的元素上應用合成畫筆,首先引用 nuget包,然後參考官方文檔中 的部分使用圖片創建一個合成畫筆:

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var imageBrush = compositor.CreateSurfaceBrush();
var loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///110Strawberry.png"));
imageBrush.Surface = loadedSurface;
imageBrush.Stretch = CompositionStretch.None;

現在就差創建一個SpriteVisual並把它應用到Background的VisualTree上了,順便一提,是這張圖片:

不過要實現平鋪功能還需要創建一個BorderEffect:

var borderEffect = new BorderEffect
{
    Source = new CompositionEffectSourceParameter("source")
};


var effectFactory = compositor.CreateEffectFactory(borderEffect);
var effectBrush = effectFactory.CreateBrush();
effectBrush.SetSourceParameter("source", imageBrush);


var sprite = compositor.CreateSpriteVisual();
sprite.Brush = effectBrush;

var backgroundVisual = ElementCompositionPreview.GetElementVisual(Background);
var bindSizeAnimation = compositor.CreateExpressionAnimation("backgroundVisual.Size");
bindSizeAnimation.SetReferenceParameter("backgroundVisual", backgroundVisual);
sprite.StartAnimation("Size", bindSizeAnimation);

ElementCompositionPreview.SetElementChildVisual(Background, sprite);

總之BorderEffect以imageBrush為Source,其它都保留默認值,將它它應用到Background的VisualTree上後效果如下:

這還不是我想要的平鋪效果。這是因為這時候ExtendXExtendY保持默認值的Clamp,這個類型會讓BorderEffect重複圖像邊緣的屬性。如果要實現我想要的平鋪需要將這兩個屬性設置為Wrap

borderEffect.ExtendX = CanvasEdgeBehavior.Wrap;
borderEffect.ExtendY = CanvasEdgeBehavior.Wrap;

居然不是從左上角開始平鋪的,和我的想法還是有出入,不過這種細節就算了。順便一提ExtendXExtendY還可以設置為Mirror,效果如下:

3. 綁定Size

var backgroundVisual = ElementCompositionPreview.GetElementVisual(Background);
var bindSizeAnimation = compositor.CreateExpressionAnimation("backgroundVisual.Size");
bindSizeAnimation.SetReferenceParameter("backgroundVisual", backgroundVisual);
sprite.StartAnimation("Size", bindSizeAnimation);

最後順便提一下,上面的代碼中有這麼一段代碼沒介紹到,這是用來動態地設置SpriteVisual的尺寸。ExpressionAnimation有一直運行和永不停止這兩個特性,創建ExpressionAnimation並在SpriteVisual上運行動畫,實際上將SpriteVisual的Size永遠地綁定為backgroundVisual 的Size的值。其實簡單地訂閱SizeChanged事件也能達到這個效果,代碼好像還少些。

4. 結語

這麼簡單的功能居然都要這麼多代碼,或者有更簡單的實現?不過凡事都有要辯證地看,幸好它這麼複雜,又讓我水了一篇博客。

有給出其它的方案,可以參考一下。

5. 參考

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

【其他文章推薦】

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

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

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

※評比南投搬家公司費用收費行情懶人包大公開

印尼環保英雄 扮蜘蛛人清垃圾獲民眾回響

摘錄自2020年2月17日公視報導

印尼的南蘇拉威西省,有一位超級環保英雄「蜘蛛人」,天天穿梭在各種下水道、海灘跟街道,做環境清潔工作。他的努力終於成功讓印尼民眾開始關注垃圾問題。

印尼環保人士魯迪哈托諾平時在咖啡館工作,因為希望居住環境乾淨,常常會默默穿梭在大街小巷中,清理塑膠垃圾。一開始,他的善行並沒有引發別人注意,直到他為了逗小侄子開心,買了蜘蛛人的衣服,角色扮演後,他才突發奇想,打扮成蜘蛛人清潔街道,希望引發更多人、投入清掃環境的行動。

魯迪說:「儘量減少塑膠垃圾是最重要的事情。因為塑膠很難分解。我們政府解決的方案之一,是對一次性塑膠袋進行規限。但實際上,應該要有更嚴格的規定。」

根據美國科學雜誌的研究顯示,身為全球第四人口大國,印尼每年都會產出320萬垃圾,但因為國家特殊的島嶼地形,幾乎有一半垃圾,都漂流到海裡,也讓印尼成為中國之外,世界最大的塑膠垃圾生產國。

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

【其他文章推薦】

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

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

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

※評比南投搬家公司費用收費行情懶人包大公開

SpringBoot 源碼解析 (三)—– Spring Boot 精髓:啟動時初始化數據

在我們用 springboot 搭建項目的時候,有時候會碰到在項目啟動時初始化一些操作的需求 ,針對這種需求 spring boot為我們提供了以下幾種方案供我們選擇:

  • ApplicationRunner 與 CommandLineRunner 接口

  • Spring容器初始化時InitializingBean接口和@PostConstruct

  • Spring的事件機制

ApplicationRunner與CommandLineRunner

我們可以實現 ApplicationRunner 或 CommandLineRunner 接口, 這兩個接口工作方式相同,都只提供單一的run方法,該方法在SpringApplication.run(…)完成之前調用,不知道大家還對我上一篇文章結尾有沒有印象,我們先來看看這兩個接口

public interface ApplicationRunner {
    void run(ApplicationArguments var1) throws Exception;
}

public interface CommandLineRunner {
    void run(String... var1) throws Exception;
}

都只提供單一的run方法,接下來我們來看看具體的使用

ApplicationRunner

構造一個類實現ApplicationRunner接口

//需要加入到Spring容器中
@Component public class ApplicationRunnerTest implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner");
    }
}

很簡單,首先要使用@Component將實現類加入到Spring容器中,為什麼要這樣做我們待會再看,然後實現其run方法實現自己的初始化數據邏輯就可以了

CommandLineRunner

對於這兩個接口而言,我們可以通過Order註解或者使用Ordered接口來指定調用順序, @Order() 中的值越小,優先級越高

//需要加入到Spring容器中
@Component
@Order(1)
public class CommandLineRunnerTest implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("CommandLineRunner...");
    }
}

同樣需要加入到Spring容器中,CommandLineRunner的參數是最原始的參數,沒有進行任何處理,ApplicationRunner的參數是ApplicationArguments,是對原始參數的進一步封裝

源碼分析

大家回顧一下我上一篇文章,也就是的最後一步,這裏我直接把代碼複製過來

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<Object>();
    //獲取容器中所有的ApplicationRunner的Bean實例
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); //獲取容器中所有的CommandLineRunner的Bean實例
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    for (Object runner : new LinkedHashSet<Object>(runners)) {
        if (runner instanceof ApplicationRunner) {
            //執行ApplicationRunner的run方法
 callRunner((ApplicationRunner) runner, args);
        }
        if (runner instanceof CommandLineRunner) {
            //執行CommandLineRunner的run方法
 callRunner((CommandLineRunner) runner, args);
        }
    }
}

很明顯,是直接從Spring容器中獲取ApplicationRunner和CommandLineRunner的實例,並調用其run方法,這也就是為什麼我要使用@Component將ApplicationRunner和CommandLineRunner接口的實現類加入到Spring容器中了。

InitializingBean

在spring初始化bean的時候,如果bean實現了 InitializingBean 接口,在對象的所有屬性被初始化后之後才會調用afterPropertiesSet()方法

@Component public class InitialingzingBeanTest implements InitializingBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean..");
    }
}

我們可以看出spring初始化bean肯定會在 ApplicationRunner和CommandLineRunner接口調用之前。

@PostConstruct

@Component public class PostConstructTest {

    @PostConstruct public void postConstruct() {
        System.out.println("init...");
    }
}

我們可以看到,只用在方法上添加@PostConstruct註解,並將類注入到Spring容器中就可以了。我們來看看@PostConstruct註解的方法是何時執行的

在Spring初始化bean時,對bean的實例賦值時,populateBean方法下面有一個initializeBean(beanName, exposedObject, mbd)方法,這個就是用來執行用戶設定的初始化操作。我們看下方法體:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            // 激活 Aware 方法
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        // 對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAware
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 后處理器
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 激活用戶自定義的 init 方法
 invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 后處理器
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

我們看到會先執行后處理器然後執行invokeInitMethods方法,我們來看下applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  
        throws BeansException {  

    Object result = existingBean;  
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessBeforeInitialization(result, beanName);  
        if (result == null) {  
            return result;  
        }  
    }  
    return result;  
}

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
        throws BeansException {  

    Object result = existingBean;  
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
        result = beanProcessor.postProcessAfterInitialization(result, beanName);  
        if (result == null) {  
            return result;  
        }  
    }  
    return result;  
}

獲取容器中所有的後置處理器,循環調用後置處理器的postProcessBeforeInitialization方法,這裏我們來看一個BeanPostProcessor

public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {
    public CommonAnnotationBeanPostProcessor() {
        this.setOrder(2147483644);
        //設置初始化參數為PostConstruct.class
        this.setInitAnnotationType(PostConstruct.class); this.setDestroyAnnotationType(PreDestroy.class);
        this.ignoreResourceType("javax.xml.ws.WebServiceContext");
    }
    //略...
}

在構造器中設置了一個屬性為PostConstruct.class,再次觀察CommonAnnotationBeanPostProcessor這個類,它繼承自InitDestroyAnnotationBeanPostProcessor。InitDestroyAnnotationBeanPostProcessor顧名思義,就是在Bean初始化和銷毀的時候所作的一個前置/後置處理器。查看InitDestroyAnnotationBeanPostProcessor類下的postProcessBeforeInitialization方法:

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
  LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());  
   try {  
      metadata.invokeInitMethods(bean, beanName);  
   }  
   catch (InvocationTargetException ex) {  
       throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());  
   }  
   catch (Throwable ex) {  
       throw new BeanCreationException(beanName, "Couldn't invoke init method", ex);  
   }  
    return bean;  
}  

private LifecycleMetadata buildLifecycleMetadata(final Class clazz) {  
       final LifecycleMetadata newMetadata = new LifecycleMetadata();  
       final boolean debug = logger.isDebugEnabled();  
       ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() {  
           public void doWith(Method method) {  
              if (initAnnotationType != null) {  
                   //判斷clazz中的methon是否有initAnnotationType註解,也就是PostConstruct.class註解
                  if (method.getAnnotation(initAnnotationType) != null) { //如果有就將方法添加進LifecycleMetadata中
 newMetadata.addInitMethod(method);  
                     if (debug) {  
                         logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);  
                     }  
                  }  
              }  
              if (destroyAnnotationType != null) {  
                    //判斷clazz中的methon是否有destroyAnnotationType註解
                  if (method.getAnnotation(destroyAnnotationType) != null) {  
                     newMetadata.addDestroyMethod(method);  
                     if (debug) {  
                         logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);  
                     }  
                  }  
              }  
           }  
       });  
       return newMetadata;  
} 

在這裡會去判斷某方法是否有PostConstruct.class註解,如果有,則添加到init/destroy隊列中,後續一一執行。@PostConstruct註解的方法會在此時執行,我們接着來看invokeInitMethods

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {

    // 是否實現 InitializingBean // 如果實現了 InitializingBean 接口,則只掉調用bean的 afterPropertiesSet()
    boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 直接調用 afterPropertiesSet()
 ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        // 判斷是否指定了 init-method(),
        // 如果指定了 init-method(),則再調用制定的init-method
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 利用反射機制執行
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

首先檢測當前 bean 是否實現了 InitializingBean 接口,如果實現了則調用其 afterPropertiesSet(),然後再檢查是否也指定了 init-method(),如果指定了則通過反射機制調用指定的 init-method()

我們也可以發現@PostConstruct會在實現 InitializingBean 接口的afterPropertiesSet()方法之前執行

Spring的事件機制

基礎概念

Spring的事件驅動模型由三部分組成

  • 事件: ApplicationEvent ,繼承自JDK的 EventObject ,所有事件都要繼承它,也就是被觀察者
  • 事件發布者: ApplicationEventPublisher 及 ApplicationEventMulticaster 接口,使用這個接口,就可以發布事件了
  • 事件監聽者: ApplicationListener ,繼承JDK的 EventListener ,所有監聽者都繼承它,也就是我們所說的觀察者,當然我們也可以使用註解 @EventListener ,效果是一樣的

事件

在Spring框架中,默認對ApplicationEvent事件提供了如下支持:

  • ContextStartedEvent:ApplicationContext啟動后觸發的事件
  • ContextStoppedEvent:ApplicationContext停止后觸發的事件
  • ContextRefreshedEvent: ApplicationContext初始化或刷新完成后觸發的事件 ;(容器初始化完成后調用,所以我們可以利用這個事件做一些初始化操作)
  • ContextClosedEvent:ApplicationContext關閉后觸發的事件;(如 web 容器關閉時自動會觸發spring容器的關閉,如果是普通 java 應用,需要調用ctx.registerShutdownHook();註冊虛擬機關閉時的鈎子才行) 

構造一個類繼承ApplicationEvent

public class TestEvent extends ApplicationEvent {

    private String message;
    
    public TestEvent(Object source) {
        super(source);
    }

    public void getMessage() {
        System.out.println(message);
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

創建事件監聽者

有兩種方法可以創建監聽者,一種是直接實現ApplicationListener的接口,一種是使用註解 @EventListener , 註解是添加在監聽方法上的 ,下面的例子是直接實現的接口

@Component
public class ApplicationListenerTest implements ApplicationListener<TestEvent> {
    @Override
    public void onApplicationEvent(TestEvent testEvent) {
        testEvent.getMessage();
    }
}

事件發布

對於事件發布,代表者是 ApplicationEventPublisher 和 ApplicationEventMulticaster ,ApplicationContext接口繼承了ApplicationEventPublisher,並在AbstractApplicationContext實現了具體代碼,實際執行是委託給ApplicationEventMulticaster(可以認為是多播)

下面是一個事件發布者的測試實例:

@RunWith(SpringRunner.class)
@SpringBootTest
public class EventTest {
    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void publishTest() {
        TestEvent testEvent = new TestEvent("");
        testEvent.setMessage("hello world");
       applicationContext.publishEvent(testEvent);
    }
}

利用ContextRefreshedEvent事件進行初始化操作

利用 ContextRefreshedEvent 事件進行初始化,該事件是 ApplicationContext 初始化完成后調用的事件,所以我們可以利用這個事件,對應實現一個 監聽器 ,在其 onApplicationEvent() 方法里初始化操作

@Component public class ApplicationListenerTest implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("容器刷新完成后,我被調用了..");
    }
}

 

 

 

 

 

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

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

奇瑞新建輕量電動車生產線 年產能可達6萬輛

據報導,奇瑞新工廠將投產鋁車身骨架純電動乘用車,年產能可達6萬輛,主要生產S51EV、小螞蟻、AOEV等系列電動車。此外新工廠投產後,將成為奇瑞兌現年產20萬輛新能源車產能目標的重要一環。

奇瑞新電動車生產項目位於蕪湖弋江區高新技術開發區,項目總投資15.6億元人民幣,由奇瑞汽車股份有限公司獨資建設,有望於年內正式投產。

奇瑞汽車股份有限公司總經理助理劉志佳此前表示,奇瑞後續的新能源汽車產品,都是以鋁合金框架(含電池鋁合金框架)和分體式碳纖維於一體的輕量化產品構架平臺。今年10月,奇瑞將推出該輕量化平臺打造的首款車型,車身減重將達到30%,該車型的推出會為減排起到很大作用,同時新車的製造過程對於傳統四大工藝(衝壓、焊裝、塗裝、總裝)也將是很大的挑戰。

據劉志佳介紹,2016年奇瑞將新能源車銷量目標定為3.3萬輛,其中純電車目標為28,000輛,插電式混合動力車目標是5,000輛。與2015年銷量表現相比,其今年銷量將實現133%的增幅。

按照奇瑞此前公佈的消息,奇瑞目前已形成全系列的新能源乘用車研發體系和集成平臺,包括四大新能源整車平臺(小型純電動平臺、中型純電動平臺、插電式混動平臺、電四驅平臺);五大通用子系統(動力電池系統、電驅動系統、整車控制系統、PHEV動力總成、電驅動後橋);七大核心技術(電池管理技術、電池系統設計、整車控制技術、PHEV系統設計、智慧互聯設計、輕量化技術、新能源整車集成)。

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

【其他文章推薦】

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

Docker學習(五)-Kubernetes 集群搭建 – Spring Boot 應用,Docker學習-Docker搭建Consul集群,Docker學習-簡單的私有DockerHub搭建,Docker學習-Spring Boot on Docker,Docker學習-Kubernetes – 集群部署,Docker學習-Kubernetes – Spring Boot 應用,Docker學習-Kubernetes – Spring Boot 應用

 

Docker學習

 

 

簡介

kubernetes,簡稱K8s,是用8代替8個字符“ubernete”而成的縮寫。是一個開源的,用於管理雲平台中多個主機上的容器化的應用,Kubernetes的目標是讓部署容器化的應用簡單並且高效(powerful),Kubernetes提供了應用部署,規劃,更新,維護的一種機制。

Kubernetes是Google開源的一個容器編排引擎,它支持自動化部署、大規模可伸縮、應用容器化管理。在生產環境中部署一個應用程序時,通常要部署該應用的多個實例以便對應用請求進行負載均衡。 在Kubernetes中,我們可以創建多個容器,每個容器裏面運行一個應用實例,然後通過內置的負載均衡策略,實現對這一組應用實例的管理、發現、訪問,而這些細節都不需要運維人員去進行複雜的手工配置和處理。  

基本概念

Kubernetes 中的絕大部分概念都抽象成 Kubernetes 管理的一種資源對象

  • Master:Master 節點是 Kubernetes 集群的控制節點,負責整個集群的管理和控制。Master 節點上包含以下組件:
  • kube-apiserver:集群控制的入口,提供 HTTP REST 服務
  • kube-controller-manager:Kubernetes 集群中所有資源對象的自動化控制中心
  • kube-scheduler:負責 Pod 的調度
  • Node:Node 節點是 Kubernetes 集群中的工作節點,Node 上的工作負載由 Master 節點分配,工作負載主要是運行容器應用。Node 節點上包含以下組件:

    • kubelet:負責 Pod 的創建、啟動、監控、重啟、銷毀等工作,同時與 Master 節點協作,實現集群管理的基本功能。
    • kube-proxy:實現 Kubernetes Service 的通信和負載均衡
    • 運行容器化(Pod)應用
  • Pod: Pod 是 Kubernetes 最基本的部署調度單元。每個 Pod 可以由一個或多個業務容器和一個根容器(Pause 容器)組成。一個 Pod 表示某個應用的一個實例

  • ReplicaSet:是 Pod 副本的抽象,用於解決 Pod 的擴容和伸縮
  • Deployment:Deployment 表示部署,在內部使用ReplicaSet 來實現。可以通過 Deployment 來生成相應的 ReplicaSet 完成 Pod 副本的創建
  • Service:Service 是 Kubernetes 最重要的資源對象。Kubernetes 中的 Service 對象可以對應微服務架構中的微服務。Service 定義了服務的訪問入口,服務的調用者通過這個地址訪問 Service 後端的 Pod 副本實例。Service 通過 Label Selector 同後端的 Pod 副本建立關係,Deployment 保證後端Pod 副本的數量,也就是保證服務的伸縮性。

Kubernetes 主要由以下幾個核心組件組成:

  • etcd 保存了整個集群的狀態,就是一個數據庫;
  • apiserver 提供了資源操作的唯一入口,並提供認證、授權、訪問控制、API 註冊和發現等機制;
  • controller manager 負責維護集群的狀態,比如故障檢測、自動擴展、滾動更新等;
  • scheduler 負責資源的調度,按照預定的調度策略將 Pod 調度到相應的機器上;
  • kubelet 負責維護容器的生命周期,同時也負責 Volume(CSI)和網絡(CNI)的管理;
  • Container runtime 負責鏡像管理以及 Pod 和容器的真正運行(CRI);
  • kube-proxy 負責為 Service 提供 cluster 內部的服務發現和負載均衡;

當然了除了上面的這些核心組件,還有一些推薦的插件:

  • kube-dns 負責為整個集群提供 DNS 服務
  • Ingress Controller 為服務提供外網入口
  • Heapster 提供資源監控
  • Dashboard 提供 GUI

組件通信

Kubernetes 多組件之間的通信原理:

  • apiserver 負責 etcd 存儲的所有操作,且只有 apiserver 才直接操作 etcd 集群
  • apiserver 對內(集群中的其他組件)和對外(用戶)提供統一的 REST API,其他組件均通過 apiserver 進行通信

    • controller manager、scheduler、kube-proxy 和 kubelet 等均通過 apiserver watch API 監測資源變化情況,並對資源作相應的操作
    • 所有需要更新資源狀態的操作均通過 apiserver 的 REST API 進行
  • apiserver 也會直接調用 kubelet API(如 logs, exec, attach 等),默認不校驗 kubelet 證書,但可以通過 --kubelet-certificate-authority 開啟(而 GKE 通過 SSH 隧道保護它們之間的通信)

比如最典型的創建 Pod 的流程:​​

  • 用戶通過 REST API 創建一個 Pod
  • apiserver 將其寫入 etcd
  • scheduluer 檢測到未綁定 Node 的 Pod,開始調度並更新 Pod 的 Node 綁定
  • kubelet 檢測到有新的 Pod 調度過來,通過 container runtime 運行該 Pod
  • kubelet 通過 container runtime 取到 Pod 狀態,並更新到 apiserver 中

 

集群部署

 

使用kubeadm工具安裝

1. master和node 都用yum 安裝kubelet,kubeadm,docker
2. master 上初始化:kubeadm init
3. master 上啟動一個flannel的pod
4. node上加入集群:kubeadm join

 

準備環境

Centos7  192.168.50.21 k8s-master  
Centos7  192.168.50.22 k8s-node01
Centos7  192.168.50.23 k8s-node02

修改主機名(3台機器都需要修改)

hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-node01
hostnamectl set-hostname k8s-node02

關閉防火牆

systemctl stop firewalld.service

配置docker yum源

yum install -y yum-utils device-mapper-persistent-data lvm2 wget
cd /etc/yum.repos.d
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

配置kubernetes yum 源

cd /opt/
wget https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
wget https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
rpm --import yum-key.gpg
rpm --import rpm-package-key.gpg
cd /etc/yum.repos.d
vi kubernetes.repo 
輸入以下內容
[kubernetes]
name=Kubernetes Repo
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
enabled=1

yum repolist

master和node 安裝kubelet,kubeadm,docker

yum install docker 
yum install kubelet-1.13.1
yum install kubeadm-1.13.1

master 上安裝kubectl

yum install kubectl-1.13.1

docker的配置

配置私有倉庫和鏡像加速地址,私有倉庫配置參見 

vi /etc/docker/daemon.json

 

{
    "registry-mirror":[
        "http://hub-mirror.c.163.com"
    ],
    "insecure-registries":[
        "192.168.50.24:5000"
    ]
}

 

啟動docker

systemctl daemon-reload
systemctl start docker 
docker info

master 上初始化:kubeadm init 

vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
kubeadm init \
    --apiserver-advertise-address=192.168.50.21 \
    --image-repository registry.aliyuncs.com/google_containers \
    --kubernetes-version v1.13.1 \
    --pod-network-cidr=10.244.0.0/16

初始化命令說明:

--apiserver-advertise-address

指明用 Master 的哪個 interface 與 Cluster 的其他節點通信。如果 Master 有多個 interface,建議明確指定,如果不指定,kubeadm 會自動選擇有默認網關的 interface。

--pod-network-cidr

指定 Pod 網絡的範圍。Kubernetes 支持多種網絡方案,而且不同網絡方案對 –pod-network-cidr 有自己的要求,這裏設置為 10.244.0.0/16 是因為我們將使用 flannel 網絡方案,必須設置成這個 CIDR。

--image-repository

Kubenetes默認Registries地址是 k8s.gcr.io,在國內並不能訪問 gcr.io,在1.13版本中我們可以增加–image-repository參數,默認值是 k8s.gcr.io,將其指定為阿里雲鏡像地址:registry.aliyuncs.com/google_containers。

--kubernetes-version=v1.13.1 

關閉版本探測,因為它的默認值是stable-1,會導致從https://dl.k8s.io/release/stable-1.txt下載最新的版本號,我們可以將其指定為固定版本(最新版:v1.13.1)來跳過網絡請求。

初始化過程中

[preflight] You can also perform this action in beforehand using 'kubeadm config images pull' 是在下載鏡像文件,過程比較慢。
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 24.002300 seconds 這個過程也比較慢 可以忽略
 
[init] Using Kubernetes version: v1.13.1
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [k8s-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.50.21]
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [k8s-master localhost] and IPs [192.168.50.21 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [k8s-master localhost] and IPs [192.168.50.21 127.0.0.1 ::1]
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 24.002300 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.13" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-master" as an annotation
[mark-control-plane] Marking the node k8s-master as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node k8s-master as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: 7ax0k4.nxpjjifrqnbrpojv
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 192.168.50.21:6443 --token 7ax0k4.nxpjjifrqnbrpojv --discovery-token-ca-cert-hash sha256:95942f10859a71879c316e75498de02a8b627725c37dee33f74cd040e1cd9d6b

初始化過程說明:

1) [preflight] kubeadm 執行初始化前的檢查。
2) [kubelet-start] 生成kubelet的配置文件”/var/lib/kubelet/config.yaml”
3) [certificates] 生成相關的各種token和證書
4) [kubeconfig] 生成 KubeConfig 文件,kubelet 需要這個文件與 Master 通信
5) [control-plane] 安裝 Master 組件,會從指定的 Registry 下載組件的 Docker 鏡像。
6) [bootstraptoken] 生成token記錄下來,後邊使用kubeadm join往集群中添加節點時會用到
7) [addons] 安裝附加組件 kube-proxy 和 kube-dns。
8) Kubernetes Master 初始化成功,提示如何配置常規用戶使用kubectl訪問集群。
9) 提示如何安裝 Pod 網絡。
10) 提示如何註冊其他節點到 Cluster。

 

異常情況:

 [WARNING Service-Docker]: docker service is not enabled, please run 'systemctl enable docker.service'
        [WARNING Swap]: running with swap on is not supported. Please disable swap
        [WARNING Hostname]: hostname "k8s-master" could not be reached
        [WARNING Hostname]: hostname "k8s-master": lookup k8s-master on 114.114.114.114:53: no such host
        [WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'

運行

systemctl enable docker.service
systemctl enable kubelet.service

會提示以下錯誤

  [WARNING Hostname]: hostname "k8s-master" could not be reached
        [WARNING Hostname]: hostname "k8s-master": lookup k8s-master on 114.114.114.114:53: no such host
error execution phase preflight: [preflight] Some fatal errors occurred:

配置host

cat >> /etc/hosts << EOF
192.168.50.21 k8s-master
192.168.50.22 k8s-node01
192.168.50.23 k8s-node02
EOF

再次運行初始化命令會出現

  [ERROR NumCPU]: the number of available CPUs 1 is less than the required 2   --設置虛擬機CPU個數大於2
        [ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables

設置好虛擬機CPU個數,重啟后再次運行:

kubeadm init \
    --apiserver-advertise-address=192.168.50.21 \
    --image-repository registry.aliyuncs.com/google_containers \
    --kubernetes-version v1.13.1 \
    --pod-network-cidr=10.244.0.0/16

 

[init] Using Kubernetes version: v1.13.1
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull

解決辦法:docker.io倉庫對google的容器做了鏡像,可以通過下列命令下拉取相關鏡像

先看下需要用到哪些

kubeadm config images list

配置yum源

[root@k8s-master opt]# vi kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.13.1
imageRepository: registry.aliyuncs.com/google_containers
apiServer:
  certSANs:
  - 192.168.50.21
controlPlaneEndpoint: "192.168.50.20:16443"
networking:
  # This CIDR is a Calico default. Substitute or remove for your CNI provider.
  podSubnet: "172.168.0.0/16"
 kubeadm config images pull --config /opt/kubeadm-config.yaml

初始化master

kubeadm init --config=kubeadm-config.yaml  --upload-certs

 

xecution phase preflight: [preflight] Some fatal errors occurred:
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
        [ERROR FileAvailable--etc-kubernetes-manifests-etcd.yaml]: /etc/kubernetes/manifests/etcd.yaml already exists
        [ERROR Port-10250]: Port 10250 is in use

kubeadm會自動檢查當前環境是否有上次命令執行的“殘留”。如果有,必須清理后再行執行init。我們可以通過”kubeadm reset”來清理環境,以備重來。

[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[kubelet-check] Initial timeout of 40s passed.

==原因==

這是因為kubelet沒啟動

==解決==

systemctl restart kubelet

如果啟動不了kubelet

kubelet.service - kubelet: The Kubernetes Node Agent

 

則可能是swap交換分區還開啟的原因
-關閉swap

swapoff -a

-配置kubelet

vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

 再次運行

kubeadm init \
    --apiserver-advertise-address=192.168.50.21 \
    --image-repository registry.aliyuncs.com/google_containers \
    --kubernetes-version v1.13.1 \
    --pod-network-cidr=10.244.0.0/16

 

 

配置 kubectl

kubectl 是管理 Kubernetes Cluster 的命令行工具,前面我們已經在所有的節點安裝了 kubectl。Master 初始化完成后需要做一些配置工作,然後 kubectl 就能使用了。
依照 kubeadm init 輸出的最後提示,推薦用 Linux 普通用戶執行 kubectl。

  • 創建普通用戶centos
#創建普通用戶並設置密碼123456
useradd centos && echo "centos:123456" | chpasswd centos

#追加sudo權限,並配置sudo免密
sed -i '/^root/a\centos  ALL=(ALL)       NOPASSWD:ALL' /etc/sudoers

#保存集群安全配置文件到當前用戶.kube目錄
su - centos
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

#啟用 kubectl 命令自動補全功能(註銷重新登錄生效)
echo "source <(kubectl completion bash)" >> ~/.bashrc

需要這些配置命令的原因是:Kubernetes 集群默認需要加密方式訪問。所以,這幾條命令,就是將剛剛部署生成的 Kubernetes 集群的安全配置文件,保存到當前用戶的.kube 目錄下,kubectl 默認會使用這個目錄下的授權信息訪問 Kubernetes 集群。
如果不這麼做的話,我們每次都需要通過 export KUBECONFIG 環境變量告訴 kubectl 這個安全配置文件的位置。
配置完成后centos用戶就可以使用 kubectl 命令管理集群了。

查看集群狀態:

kubectl get cs

 

 

 

 

 

 部署網絡插件

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

  

kubectl get 重新檢查 Pod 的狀態

 

 

部署worker節點

 在master機器保存生成號的鏡像文件

docker save -o master.tar registry.aliyuncs.com/google_containers/kube-proxy:v1.13.1 registry.aliyuncs.com/google_containers/kube-apiserver:v1.13.1 registry.aliyuncs.com/google_containers/kube-controller-manager:v1.13.1 registry.aliyuncs.com/google_containers/kube-scheduler:v1.13.1  registry.aliyuncs.com/google_containers/coredns:1.2.6  registry.aliyuncs.com/google_containers/etcd:3.2.24 registry.aliyuncs.com/google_containers/pause:3.1

注意對應的版本號

將master上保存的鏡像同步到節點上

scp master.tar node01:/root/
scp master.tar node02:/root/

將鏡像導入本地,node01,node02

 docker load< master.tar

配置host,node01,node02

cat >> /etc/hosts << EOF
192.168.50.21 k8s-master
192.168.50.22 k8s-node01
192.168.50.23 k8s-node02
EOF

配置iptables,node01,node02

echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables

-關閉swap,node01,node02

swapoff -a

-配置kubelet,node01,node02

vi /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false" 
systemctl enable docker.service
systemctl enable kubelet.service

啟動docker,node01,node02

service docker strat

部署網絡插件,node01,node02

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

獲取join指令,master

kubeadm token create --print-join-command
kubeadm token create --print-join-command
kubeadm join 192.168.50.21:6443 --token n9g4nq.kf8ppgpgb3biz0n5 --discovery-token-ca-cert-hash sha256:95942f10859a71879c316e75498de02a8b627725c37dee33f74cd040e1cd9d6b

 

在子節點運行指令 ,node01,node02

kubeadm join 192.168.50.21:6443 --token n9g4nq.kf8ppgpgb3biz0n5 --discovery-token-ca-cert-hash sha256:95942f10859a71879c316e75498de02a8b627725c37dee33f74cd040e1cd9d6b
[preflight] Running pre-flight checks
[discovery] Trying to connect to API Server "192.168.50.21:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://192.168.50.21:6443"
[discovery] Requesting info from "https://192.168.50.21:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "192.168.50.21:6443"
[discovery] Successfully established connection with API Server "192.168.50.21:6443"
[join] Reading configuration from the cluster...
[join] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] WARNING: unable to stop the kubelet service momentarily: [exit status 4]
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.13" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "k8s-node01" as an annotation

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the master to see this node join the cluster.

在master上查看節點狀態

kubectl get nodes

 

 這種狀態是錯誤的 ,只有一台聯機正確

查看node01,和node02發現 node01有些進程沒有完全啟動

刪除node01所有運行的容器,node01

docker stop $(docker ps -q) & docker rm $(docker ps -aq)

重置 kubeadm ,node01

kubeadm reset

獲取join指令,master

kubeadm token create --print-join-command

再次在node01上運行join

 

 

 

查看node01鏡像運行狀態

  

查看master狀態

  

nodes狀態全部為ready,由於每個節點都需要啟動若干組件,如果node節點的狀態是 NotReady,可以查看所有節點pod狀態,確保所有pod成功拉取到鏡像並處於running狀態:

kubectl get pod --all-namespaces -o wide

  

配置kubernetes UI圖形化界面

創建kubernetes-dashboard.yaml

# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ------------------- Dashboard Secret ------------------- #

apiVersion: v1
kind: Secret
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard-certs
  namespace: kube-system
type: Opaque

---
# ------------------- Dashboard Service Account ------------------- #

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system

---
# ------------------- Dashboard Role & Role Binding ------------------- #

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
rules:
  # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create"]
  # Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["create"]
  # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
  verbs: ["get", "update", "delete"]
  # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["kubernetes-dashboard-settings"]
  verbs: ["get", "update"]
  # Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
  resources: ["services"]
  resourceNames: ["heapster"]
  verbs: ["proxy"]
- apiGroups: [""]
  resources: ["services/proxy"]
  resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: kubernetes-dashboard-minimal
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
  name: kubernetes-dashboard
  namespace: kube-system

---
# ------------------- Dashboard Deployment ------------------- #

kind: Deployment
apiVersion: apps/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: kubernetes-dashboard
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
    spec:
      containers:
      - name: kubernetes-dashboard
        image: registry.cn-hangzhou.aliyuncs.com/rsqlh/kubernetes-dashboard:v1.10.1  
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8443
          protocol: TCP
        args:
          - --auto-generate-certificates
          # Uncomment the following line to manually specify Kubernetes API server Host
          # If not specified, Dashboard will attempt to auto discover the API server and connect
          # to it. Uncomment only if the default does not work.
          # - --apiserver-host=http://my-address:port
        volumeMounts:
        - name: kubernetes-dashboard-certs
          mountPath: /certs
          # Create on-disk volume to store exec logs
        - mountPath: /tmp
          name: tmp-volume
        livenessProbe:
          httpGet:
            scheme: HTTPS
            path: /
            port: 8443
          initialDelaySeconds: 30
          timeoutSeconds: 30
      volumes:
      - name: kubernetes-dashboard-certs
        secret:
          secretName: kubernetes-dashboard-certs
      - name: tmp-volume
        emptyDir: {}
      serviceAccountName: kubernetes-dashboard
      # Comment the following tolerations if Dashboard must not be deployed on master
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule

---
# ------------------- Dashboard Service ------------------- #

kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kube-system
spec:
  type: NodePort
  ports:
  - port: 443
    targetPort: 8443
    nodePort: 30000
  selector:
    k8s-app: kubernetes-dashboard

 

執行以下命令創建kubernetes-dashboard:

kubectl create -f kubernetes-dashboard.yaml

如果出現

Error from server (AlreadyExists): error when creating "kubernetes-dashboard.yaml": secrets "kubernetes-dashboard-certs" already exists
Error from server (AlreadyExists): error when creating "kubernetes-dashboard.yaml": serviceaccounts "kubernetes-dashboard" already exists
Error from server (AlreadyExists): error when creating "kubernetes-dashboard.yaml": roles.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" already exists
Error from server (AlreadyExists): error when creating "kubernetes-dashboard.yaml": rolebindings.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" already exists
Error from server (AlreadyExists): error when creating "kubernetes-dashboard.yaml": deployments.apps "kubernetes-dashboard" already exists

運行delete清理

kubectl delete -f kubernetes-dashboard.yaml

查看組件運行狀態

kubectl get pods --all-namespaces

 

 

 ErrImagePull 拉取鏡像失敗

手動拉取 並重置tag

docker pull registry.cn-hangzhou.aliyuncs.com/rsqlh/kubernetes-dashboard:v1.10.1
docker tag registry.cn-hangzhou.aliyuncs.com/rsqlh/kubernetes-dashboard:v1.10.1 k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.1

重新創建

  

 

ImagePullBackOff

默認情況是會根據配置文件中的鏡像地址去拉取鏡像,如果設置為IfNotPresent 和Never就會使用本地鏡像。

IfNotPresent :如果本地存在鏡像就優先使用本地鏡像。
Never:直接不再去拉取鏡像了,使用本地的;如果本地不存在就報異常了。

 spec:
      containers:
      - name: kubernetes-dashboard
        image: registry.cn-hangzhou.aliyuncs.com/rsqlh/kubernetes-dashboard:v1.10.1  
        imagePullPolicy: IfNotPresent

 

查看映射狀態 

 kubectl get service  -n kube-system

 

 

 

 

創建能夠訪問 Dashboard 的用戶

 新建文件 account.yaml ,內容如下:

# Create Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kube-system
---
# Create ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kube-system
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

 

 複製token登陸

 

 

configmaps is forbidden: User "system:serviceaccount:kube-system:admin-user" cannot list resource "configmaps" in API group "" in the namespace "default" 

 授權用戶

kubectl create clusterrolebinding test:admin-user --clusterrole=cluster-admin --serviceaccount=kube-system:admin-user

 

 

 NodePort方式,可以到任意一個節點的XXXX端口查看

 

 

本文參考:

 

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

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

016.Kubernetes二進制部署所有節點kube-proxy

一 部署 kube-proxy


kube-proxy 運行在所有節點上,它監聽 apiserver 中 service 和 endpoint 的變化情況,創建路由規則以提供服務 IP 和負載均衡功能。

1.1 安裝kube-proxy


提示:k8smaster01節點已下載相應二進制,可直接分發至node節點。

1.2 分發kube-proxy

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for all_ip in ${ALL_IPS[@]}
  4   do
  5     echo ">>> ${all_ip}"
  6     scp kubernetes/server/bin/kube-proxy root@${all_ip}:/opt/k8s/bin/
  7     ssh root@${all_ip} "chmod +x /opt/k8s/bin/*"
  8   done


1.3 創建kube-scheduler證書和私鑰

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cat > kube-proxy-csr.json <<EOF
  3 {
  4   "CN": "system:kube-proxy",
  5   "key": {
  6     "algo": "rsa",
  7     "size": 2048
  8   },
  9   "names": [
 10     {
 11       "C": "CN",
 12       "ST": "Shanghai",
 13       "L": "Shanghai",
 14       "O": "k8s",
 15       "OU": "System"
 16     }
 17   ]
 18 }
 19 EOF
 20 #創建kube-scheduler的CA證書請求文件



解釋:

  • CN:指定該證書的 User 為 system:kube-proxy;
  • 預定義的 RoleBinding system:node-proxier 將User system:kube-proxy 與 Role system:node-proxier 綁定,該 Role 授予了調用 kube-apiserver Proxy 相關 API 的權限;
  • 該證書只會被 kube-proxy 當做 client 證書使用,所以 hosts 字段為空。




  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cfssl gencert -ca=/opt/k8s/work/ca.pem \
  3 -ca-key=/opt/k8s/work/ca-key.pem -config=/opt/k8s/work/ca-config.json \
  4 -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy		#生成CA密鑰(ca-key.pem)和證書(ca.pem)


1.4 創建和分發kubeconfig


kube-proxy 使用 kubeconfig 文件訪問 apiserver,該文件提供了 apiserver 地址、嵌入的 CA 證書和 kube-proxy 證書:

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# kubectl config set-cluster kubernetes \
  4   --certificate-authority=/opt/k8s/work/ca.pem \
  5   --embed-certs=true \
  6   --server=${KUBE_APISERVER} \
  7   --kubeconfig=kube-proxy.kubeconfig
  8 
  9 [root@k8smaster01 work]# kubectl config set-credentials kube-proxy \
 10   --client-certificate=kube-proxy.pem \
 11   --client-key=kube-proxy-key.pem \
 12   --embed-certs=true \
 13   --kubeconfig=kube-proxy.kubeconfig
 14 
 15 [root@k8smaster01 work]# kubectl config set-context default \
 16   --cluster=kubernetes \
 17   --user=kube-proxy \
 18   --kubeconfig=kube-proxy.kubeconfig
 19 
 20 [root@k8smaster01 work]# kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
 21 
 22 [root@k8smaster01 ~]# cd /opt/k8s/work
 23 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
 24 [root@k8smaster01 work]# for node_name in ${NODE_NAMES[@]}
 25   do
 26     echo ">>> ${node_name}"
 27     scp kube-proxy.kubeconfig root@${node_name}:/etc/kubernetes/
 28   done


1.5 創建kube-proxy 配置文件


從 v1.10 開始,kube-proxy 部分參數可以配置文件中配置。可以使用 –write-config-to 選項生成該配置文件。

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# cat > kube-proxy-config.yaml.template <<EOF
  3 kind: KubeProxyConfiguration
  4 apiVersion: kubeproxy.config.k8s.io/v1alpha1
  5 clientConnection:
  6   burst: 200
  7   kubeconfig: "/etc/kubernetes/kube-proxy.kubeconfig"
  8   qps: 100
  9 bindAddress: ##ALL_IP##
 10 healthzBindAddress: ##ALL_IP##:10256
 11 metricsBindAddress: ##ALL_IP##:10249
 12 enableProfiling: true
 13 clusterCIDR: ${CLUSTER_CIDR}
 14 hostnameOverride: ##ALL_NAME##
 15 mode: "ipvs"
 16 portRange: ""
 17 kubeProxyIPTablesConfiguration:
 18   masqueradeAll: false
 19 kubeProxyIPVSConfiguration:
 20   scheduler: rr
 21   excludeCIDRs: []
 22 EOF



解釋:

  • bindAddress: 監聽地址;
  • clientConnection.kubeconfig: 連接 apiserver 的 kubeconfig 文件;
  • clusterCIDR: kube-proxy 根據 –cluster-cidr 判斷集群內部和外部流量,指定 –cluster-cidr 或 –masquerade-all 選項后 kube-proxy 才會對訪問 Service IP 的請求做 SNAT;
  • hostnameOverride: 參數值必須與 kubelet 的值一致,否則 kube-proxy 啟動後會找不到該 Node,從而不會創建任何 ipvs 規則;
  • mode: 使用 ipvs 模式。

1.6 分發配置文件

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for (( i=0; i < 6; i++ ))
  4   do
  5     echo ">>> ${ALL_NAMES[i]}"
  6     sed -e "s/##ALL_NAME##/${ALL_NAMES[i]}/" -e "s/##ALL_IP##/${ALL_IPS[i]}/" kube-proxy-config.yaml.template > kube-proxy-config-${ALL_NAMES[i]}.yaml.template
  7     scp kube-proxy-config-${ALL_NAMES[i]}.yaml.template root@${ALL_NAMES[i]}:/etc/kubernetes/kube-proxy-config.yaml
  8   done


1.7 創建kube-proxy的systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# cat > kube-proxy.service <<EOF
  4 [Unit]
  5 Description=Kubernetes Kube-Proxy Server
  6 Documentation=https://github.com/GoogleCloudPlatform/kubernetes
  7 After=network.target
  8 
  9 [Service]
 10 WorkingDirectory=${K8S_DIR}/kube-proxy
 11 ExecStart=/opt/k8s/bin/kube-proxy \\
 12   --config=/etc/kubernetes/kube-proxy-config.yaml \\
 13   --logtostderr=true \\
 14   --v=2
 15 Restart=on-failure
 16 RestartSec=5
 17 LimitNOFILE=65536
 18 
 19 [Install]
 20 WantedBy=multi-user.target
 21 EOF


1.8 分發kube-proxy systemd

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for all_name in ${ALL_NAMES[@]}
  4   do
  5     echo ">>> ${all_name}"
  6     scp kube-proxy.service root@${all_name}:/etc/systemd/system/
  7   done						#分發system


二 啟動並驗證

2.1 啟動kube-proxy 服務

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for all_ip in ${ALL_IPS[@]}
  4   do
  5     echo ">>> ${all_ip}"
  6     ssh root@${all_ip} "mkdir -p ${K8S_DIR}/kube-proxy"
  7     ssh root@${all_ip} "modprobe ip_vs_rr"
  8     ssh root@${all_ip} "systemctl daemon-reload && systemctl enable kube-proxy && systemctl restart kube-proxy"
  9   done						#啟動服務前必須先創建工作目錄


2.2 檢查kube-proxy 服務

  1 [root@k8smaster01 ~]# source /opt/k8s/bin/environment.sh
  2 [root@k8smaster01 ~]# for all_ip in ${ALL_IPS[@]}
  3   do
  4     echo ">>> ${all_ip}"
  5     ssh root@${all_ip} "systemctl status kube-proxy|grep Active"
  6   done


2.3 查看監聽端口


kube-proxy 監聽 10249 和 10256 端口:

  • 10249:對外提供 /metrics;
  • 10256:對外提供 /healthz 的訪問。

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for all_ip in ${ALL_IPS[@]}
  4   do
  5     echo ">>> ${all_ip}"
  6     ssh root@${all_ip} "sudo netstat -lnpt|grep kube-prox"
  7   done



2.4 查看ipvs 路由規則

  1 [root@k8smaster01 ~]# cd /opt/k8s/work
  2 [root@k8smaster01 work]# source /opt/k8s/bin/environment.sh
  3 [root@k8smaster01 work]# for all_ip in ${ALL_IPS[@]}
  4   do
  5     echo ">>> ${all_ip}"
  6     ssh root@${all_ip} "/usr/sbin/ipvsadm -ln"
  7   done



可見所有通過 https 訪問 K8S SVC kubernetes 的請求都轉發到 kube-apiserver 節點的 6443 端口。本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

初識web API接口及Restful接口規範

一、web API接口

什麼是web API接口?:

明確了請求方式,提供對應後台所需參數,請求url鏈接可以得到後台的響應數據
url : 返回數據的url

請求方式:
get,post,put,patch….

請求參數:json或xml格式的key-value類型數據

  • ak:6E823f587c95f0148c19993539b99295
  • region:上海
  • query:肯德基
  • output:json

響應結果:
​ 返回json或xml格式的key-value類型數據

  • 上方請求參數的output參數值決定了響應數據的格式

  • {
        "status":0,
        "message":"ok",
        "results":[
            {
                "name":"肯德基(羅餐廳)",
                "location":{
                    "lat":31.415354,
                    "lng":121.357339
                },
                "address":"月羅路2380號",
                "province":"上海市",
                "city":"上海市",
                "area":"寶山區",
                "street_id":"339ed41ae1d6dc320a5cb37c",
                "telephone":"(021)56761006",
                "detail":1,
                "uid":"339ed41ae1d6dc320a5cb37c"
            }
            ...
            ]
    }

怎麼寫接口?:

​ 參照某種規則(規範)書寫url鏈接,同時根據規則制定請求方式,請求數據與響應結果

接口文檔:

​ 提供給前後台開發人員與測試人員查看

接口工具:

YAPI平台

​ 專門寫接口文檔的YAPI平台

​ YApi是去哪兒網的前端技術中心的一個開源可視化接口管理平台

  • 創建接口項目
  • 創建接口
  • 編寫接口

接口測試工具:Postman

Postman是一款接口調試工具,是一款免費的可視化軟件,同時支持各種操作系統平台,是測試接口的首選工具。

Postman可以直接從下載獲得,然後進行傻瓜式安裝。

  • 工作面板
  • 簡易的get請求
  • 簡易的post請求
  • 案例:請求百度地圖接口

接口規範:

​ webapi接口規範:restful

RESTful API介紹

RESTful介紹

REST與技術無關,代表的是一種軟件架構風格,REST是Representational State Transfer的簡稱,中文翻譯為“表徵狀態轉移”或“表現層狀態轉化”。

推薦閱讀

RESTful API設計指南

推薦閱讀

API與用戶的通信協議

總是使用。

域名

用api關鍵字來標識接口url

注:看到api字眼,就代表該請求url鏈接是完成前後台數據交互的

版本

\1. 將版本信息放在URL中,如:

​ v1,v2代表不同數據版本的提現,前提是一種數據資源有多個版本

\2. 將版本信息放在請求頭中。

url路徑

視網絡上任何東西都是資源,均使用名詞表示(一般為複數形式)

在url鏈接中獎勵不要出現操作資源的動詞

​ 錯誤示範:

特殊的接口可以出現動詞,因為這些接口一般沒有一個明確的資源,或是動詞就是接口的核心含義

method請求方式

GET :從服務器取出資源(一項或多項)

POST :在服務器新建一個資源

PUT :在服務器更新資源(客戶端提供改變后的完整資源)

PATCH :在服務器更新資源(客戶端提供改變的屬性)

DELETE :從服務器刪除資源

過濾

通過在url上傳參的形式傳遞搜索條件

狀態碼

200 OK - [GET]:服務器成功返回用戶請求的數據,該操作是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
202 Accepted - [*]:表示一個請求已經進入後台排隊(異步任務)
204 NO CONTENT - [DELETE]:用戶刪除數據成功。


301:永久重定向
302:暫時重定向


400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作,該操作是冪等的。
401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。
404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的。
406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤。


500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將無法判斷髮出的請求是否成功。

錯誤處理

狀態碼是4xx時,應返回錯誤信息,error當做key。    

{
    error: "Invalid API key"
}

返回結果

針對不同操作,服務器向用戶返回的結果應該符合以下規範

GET     /collection:返回資源對象的列表(數組)
GET     /collection/resource:返回單個資源對象
POST    /collection:返回新生成的資源對象
PUT     /collection/resource:返回完整的資源對象
PATCH   /collection/resource:返回完整的資源對象
DELETE  /collection/resource:返回一個空文檔
{
    "status": 0,
    "msg": "ok",
    "results":[
        {
            "name":"肯德基(羅餐廳)",
            "location":{
                "lat":31.415354,
                "lng":121.357339
            },
            "address":"月羅路2380號",
            "province":"上海市",
            "city":"上海市",
            "area":"寶山區",
            "street_id":"339ed41ae1d6dc320a5cb37c",
            "telephone":"(021)56761006",
            "detail":1,
            "uid":"339ed41ae1d6dc320a5cb37c"
        }
        ...
        ]
}

Hypermedia API

RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什麼。

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

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

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

第六屆中國國際新能源汽車論壇2016-頒獎典禮已開啟評獎模式

由希邁商務諮詢(上海)有限公司主辦的2016年第六屆中國國際新能源汽車論壇即將於4月20日-4月22日在上海隆重舉行。此次論壇獲得了亞太電動車學會、國家新能源機動車產品品質監督檢驗中心、上海交大密西根學院、賽迪顧問及中國綠色能源產業技術創新戰略聯盟的大力支持。截止2月19日,論壇已經確認39位演講嘉賓出席本次論壇並做高品質學術演講。演講嘉賓分別來自菲律賓電動車協會、國家新能源機動車產品品質監督檢驗中心、美國國家能源局、中國工程院等在內的政府單位與研究機構,以及包括寶馬、通用汽車、特斯拉、長安汽車、長城汽車、比亞迪戴姆勒、上汽、北汽、觀致等在內的多個知名整車商,將在論壇上共同研討新能源汽車行業政策趨勢、技術路線及難點、基礎設施建設、商業模式,延續以往的豐碩成果,繼續為新能源汽車行業作出貢獻。

此外,為了表彰各類汽車企業在行業內的傑出貢獻,第六屆中國國際新能源汽車論壇還將舉辦頒獎典禮,並設立了多個獎項,將由中國工程院院士陳清泉領銜的多個知名業內專家作為頒獎嘉賓為這些企業授予頒獎,已經有多家企業提交了獎項申請表及資料,參與反響積極。

本屆論壇相比歷屆舉辦規模最大的第六屆新能源汽車論壇,涉及主論壇及三個分論壇、考察活動、頒獎典禮和交流晚宴。屆時將誠邀全球範圍內的整車製造商、電網電力公司、電池廠商、零部件供應商、核心技術提供商和政府官員近500位行業人士一起,對新能源汽車產業面臨的挑戰,機遇與對策各方面進行為期三天更深層次並具有建設和戰略性的探討。

會議結構

會議亮點

豐富的內容:

9大板塊的深度解析

參會嘉賓:

500+高度滿意的企業決策者,120+業內知名企業,30+國家和地區

參會嘉賓分析:

17%+來自各國政府部門及權威機構,25%+來自知名整車商

演講嘉賓:

40+世界新能源汽車行業知名發言嘉賓

交流機會:

24+小時的交流機會:考察討論、VIP晚宴和開放式問答

會議形式

1個主論壇,3個分論壇,1個晚宴,1個頒獎典禮以及1天考察活動

若您對峰會有更多要求,請撥打021-6045 1760與我們聯繫,謝謝理解和支持!
我們期待與貴單位一起出席於2016年4月20-22日在上海舉辦的第六屆中國國際新能源汽車論壇2016,以利決策!
想瞭解詳細內容,請登陸官方網站:  
連絡人:Hill ZENG(曾先生)
電話:0086 21-6045 1760
傳真:0086 21-6047 5887
郵箱:

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

【其他文章推薦】

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

工信部發佈第二批新能源車型目錄

2月29日,工信部發佈《新能源汽車推廣應用推薦車型目錄》(第2批),共有466款車型,進入此次目錄。

在純電動轎車\乘用車方面,比亞迪、東風、風神、啟辰、蓮花、邁迪、之諾、中華、吉利、知豆、康迪、騰勢、眾泰、江南、力帆、長安、奇瑞、凱翼、開瑞、江鈴、海馬、野馬、寶馬等21個品牌的車入選。

插電式混合動力轎車\乘用車方面,比亞迪、野馬、榮威三個品牌的車型入選。另外,傳祺GAC7100SHEVD5增程式混合動力轎車、比亞迪BYD7150WTHEV3和沃爾沃VCC7204C13PHEV混合動力轎車入選。

純電動客車方面,海格、東風、青年、福田、海格、黃海、金杯、申沃、暢達、亞星、安凱、宇通、比亞迪、野馬、金龍、金旅、中通、申龍、大馬、開沃、山西、黑龍江、象牌、常隆、陸地方舟、星凱龍、舒馳、江西、飛燕、揚子江、南車時代、廣通、蜀都、萬達等品牌的車型入選。插電式混合動力客車方面,亞星、安凱、晶馬、中通等品牌的車型入選。

混合動力客車方面,宇通、萬達、南車時代、中通、金旅、金龍、海格、比亞迪、福田等品牌的車型入選。

值得注意的是,純電動專用車都未進入第一批和第二批新能源汽車推廣應用推薦車型目錄中。

 

序号

企业名称

《目录》

序号

商标

产品型号

产品名称

1

东风汽车公司

3

东风牌

DFA7000L2ABEV

纯电动轿车

2

东风汽车公司

3

东风牌

DFA7000L2ABEV1

纯电动轿车

3

东风汽车公司

3

东风牌

DFA7000L2ABEV2

纯电动轿车

4

东风汽车公司

3

风神牌

DFM7000G1ABEV

纯电动轿车

5

东风汽车公司

3

风神牌

DFM7000H2ABEV1

纯电动轿车

6

东风汽车公司

3

风神牌

DFM7000H2DBEV1

纯电动轿车

7

东风汽车公司

3

东风牌

EQ6100CLBEV1

纯电动城市客车

8

东风汽车公司

3

东风牌

EQ6100CLCHEV

混合动力城市客车

9

东风汽车公司

3

东风牌

EQ6111CBEV

纯电动客车

10

东风汽车公司

3

东风牌

EQ6600CBEV

纯电动客车

11

东风汽车公司

3

东风牌

EQ6600CBEV1

纯电动客车

12

东风汽车公司

3

东风牌

EQ6600CBEV2

纯电动城市客车

13

东风汽车公司

3

东风牌

EQ6600CBEV3

纯电动客车

14

东风汽车公司

3

东风牌

EQ6600CBEV4

纯电动客车

15

东风汽车公司

3

东风牌

EQ6600CBEV5

纯电动城市客车

16

东风汽车公司

3

东风牌

EQ6620CLBEV2

纯电动城市客车

17

东风汽车公司

3

东风牌

EQ6640CLBEV1

纯电动客车

18

东风汽车有限公司

3

启辰牌

DFL7000B2BEV

纯电动轿车

19

东风特种汽车有限公司

3

东风牌

EQ6670CBEVT1

纯电动城市客车

20

金华青年汽车制造有限公司

7

青年牌

JNP6700BEV

纯电动城市客车

21

金华青年汽车制造有限公司

7

青年牌

JNP6700LBEV

纯电动客车

22

金华青年汽车制造有限公司

7

莲花牌

JNP7000BEV

纯电动轿车

23

金华青年汽车制造有限公司

7

迈迪牌

JNP7001BEV3

纯电动轿车

24

金华青年汽车制造有限公司

7

迈迪牌

JNP7001BEV4

纯电动轿车

25

北汽福田汽车股份有限公司

9

福田牌

BJ6105CHEVCG-1

混合动力城市客车

26

北汽福田汽车股份有限公司

9

福田牌

BJ6105EVCA-5

纯电动城市客车

27

北汽福田汽车股份有限公司

9

福田牌

BJ6105PHEVCA-10

混合动力城市客车

28

北汽福田汽车股份有限公司

9

福田牌

BJ6113PHEVUA

混合动力客车

29

北汽福田汽车股份有限公司

9

福田牌

BJ6116EVUA

纯电动客车

30

北汽福田汽车股份有限公司

9

福田牌

BJ6123CHEVCA-2

混合动力城市客车

31

北汽福田汽车股份有限公司

9

福田牌

BJ6123CHEVCG-1

混合动力城市客车

32

北汽福田汽车股份有限公司

9

福田牌

BJ6123EVCA-21

纯电动城市客车

33

北汽福田汽车股份有限公司

9

福田牌

BJ6123EVCA-22

纯电动城市客车

34

北汽福田汽车股份有限公司

9

福田牌

BJ6123PHEVCA-10

混合动力城市客车

35

北汽福田汽车股份有限公司

9

福田牌

BJ6127EVUA-2

纯电动客车

36

北汽福田汽车股份有限公司

9

福田牌

BJ6127PHEVCA-1

混合动力城市客车

37

北汽福田汽车股份有限公司

9

福田牌

BJ6127PHEVUA-1

混合动力客车

38

北汽福田汽车股份有限公司

9

福田牌

BJ6127PHEVUA-2

混合动力客车

39

北汽福田汽车股份有限公司

9

福田牌

BJ6180EVCA-1

纯电动城市客车

40

北汽福田汽车股份有限公司

9

福田牌

BJ6180SHEVCA

混合动力城市客车

41

北汽福田汽车股份有限公司

9

福田牌

BJ6731EVCA-1

纯电动城市客车

42

北汽福田汽车股份有限公司

9

福田牌

BJ6731EVUA-1

纯电动客车

43

北汽福田汽车股份有限公司

9

福田牌

BJ6905CHEVCA-1

混合动力城市客车

44

北汽福田汽车股份有限公司

9

福田牌

BJ6905CHEVCA-2

混合动力城市客车

45

一汽客车(大连)有限公司

28

解放牌

CA6103URHEV31

混合动力城市客车

46

丹东黄海汽车有限责任公司

29

黄海牌

DD6109CHEV4N

混合动力城市客车

47

丹东黄海汽车有限责任公司

29

黄海牌

DD6109EV11

纯电动城市客车

48

丹东黄海汽车有限责任公司

29

黄海牌

DD6109PHEV1N

混合动力城市客车

49

丹东黄海汽车有限责任公司

29

黄海牌

DD6129CHEV7N

混合动力城市客车

50

丹东黄海汽车有限责任公司

29

黄海牌

DD6129CHEV8N

混合动力城市客车

51

丹东黄海汽车有限责任公司

29

黄海牌

DD6129PHEV1N

混合动力城市客车

52

丹东黄海汽车有限责任公司

29

黄海牌

DD6600EV3

纯电动客车

53

华晨宝马汽车有限公司

33

之诺(ZINORO)牌

BBA7000EV(ZINORO1E)

纯电动轿车

54

华晨宝马汽车有限公司

33

宝马(BMW)牌

BMW7201AMHEV(BMW530Le)

插电式混合动力轿车

55

华晨汽车集团控股有限公司

33

中华牌

SY7000BEVDAE1

纯电动轿车

56

沈阳华晨金杯汽车有限公司

33

金杯牌

SY6548BEVD3HB

纯电动轻型客车

57

上海申沃客车有限公司

42

申沃牌

SWB6108EV47

纯电动城市客车

58

上海申沃客车有限公司

42

申沃牌

SWB6108EV52

纯电动城市客车

59

上海申沃客车有限公司

42

申沃牌

SWB6110EV65

纯电动客车

60

上海申沃客车有限公司

42

申沃牌

SWB6121EV60

纯电动城市客车

61

上海申沃客车有限公司

42

申沃牌

SWB6128EV52

纯电动城市客车

62

上海申沃客车有限公司

42

申沃牌

SWB6128EV56

纯电动城市客车

63

南京汽车集团有限公司

44

畅达牌

NJ6708BEV

纯电动客车

64

扬州亚星客车股份有限公司

49

亚星牌

JS6111SHEVC

插电式混合动力双层城市客车

65

扬州亚星客车股份有限公司

49

亚星牌

YBL6111HBEV

纯电动客车

66

扬州亚星客车股份有限公司

49

亚星牌

YBL6600BEV6

纯电动客车

67

扬州亚星客车股份有限公司

49

亚星牌

YBL6600BEV7

纯电动客车

68

浙江豪情汽车制造有限公司

52

吉利牌

JL7001BEV34

纯电动轿车

69

浙江豪情汽车制造有限公司

52

沃尔沃牌

VCC7204C13PHEV

混合动力轿车

70

浙江吉利汽车有限公司

52

吉利牌

SMA7000BEV06

纯电动轿车

71

浙江吉利汽车有限公司

52

吉利牌

SMA7001BEV05

纯电动轿车

72

浙江吉利汽车有限公司

52

知豆牌

SMA7001BEV18

纯电动轿车

73

浙江吉利汽车有限公司

52

知豆牌

SMA7001BEV19

纯电动轿车

74

浙江吉利汽车有限公司

52

知豆牌

SMA7001BEV22

纯电动轿车

75

浙江吉利汽车有限公司

52

知豆牌

SMA7001BEV23

纯电动轿车

76

浙江吉利汽车有限公司

52

知豆牌

SMA7001BEV60

纯电动轿车

77

浙江吉利汽车有限公司

52

知豆牌

SMA7001BEV61

纯电动轿车

78

浙江吉利汽车有限公司

52

康迪牌

SMA7002BEV05

纯电动轿车

79

安徽安凯汽车股份有限公司

55

安凯牌

HFF6100G03EV-2

纯电动城市客车

80

安徽安凯汽车股份有限公司

55

安凯牌

HFF6102G03CHEV-1

插电式混合动力城市客车

81

安徽安凯汽车股份有限公司

55

安凯牌

HFF6102G03EV-3

纯电动城市客车

82

安徽安凯汽车股份有限公司

55

安凯牌

HFF6109G03EV

纯电动城市客车

83

安徽安凯汽车股份有限公司

55

安凯牌

HFF6109K10EV

纯电动客车

84

安徽安凯汽车股份有限公司

55

安凯牌

HFF6110K10EV

纯电动客车

85

安徽安凯汽车股份有限公司

55

安凯牌

HFF6121G03CHEV-2

插电式混合动力城市客车

86

安徽安凯汽车股份有限公司

55

安凯牌

HFF6121K10EV

纯电动客车

87

安徽安凯汽车股份有限公司

55

安凯牌

HFF6122G03CHEV-2

插电式混合动力城市客车

88

安徽安凯汽车股份有限公司

55

安凯牌

HFF6123G03EV-2

纯电动城市客车

89

安徽安凯汽车股份有限公司

55

安凯牌

HFF6127K46EV-6

纯电动客车

90

安徽安凯汽车股份有限公司

55

安凯牌

HFF6660GEVB

纯电动城市客车

91

安徽安凯汽车股份有限公司

55

安凯牌

HFF6660GEVB1

纯电动城市客车

92

安徽安凯汽车股份有限公司

55

安凯牌

HFF6707BEV

纯电动客车

93

安徽安凯汽车股份有限公司

55

安凯牌

HFF6708BEV

纯电动客车

94

安徽安凯汽车股份有限公司

55

安凯牌

HFF6800GEVB

纯电动城市客车

95

安徽安凯汽车股份有限公司

55

安凯牌

HFF6800GEVB2

纯电动城市客车

96

安徽安凯汽车股份有限公司

55

安凯牌

HFF6800GEVB3

纯电动城市客车

97

安徽安凯汽车股份有限公司

55

安凯牌

HFF6851G03EV

纯电动城市客车

98

安徽江淮汽车股份有限公司

56

江淮牌

HFC6601EVH

纯电动客车

99

安徽江淮汽车股份有限公司

56

江淮牌

HFC6601EVH1

纯电动客车

100

江西江铃集团晶马汽车有限公司

62

晶马牌

JMV6105GRPHEV

插电式混合动力城市客车

101

江西江铃集团晶马汽车有限公司

62

晶马牌

JMV6115GRPHEV

插电式混合动力城市客车

102

江西江铃集团晶马汽车有限公司

62

晶马牌

JMV6115GRPHEVN

插电式混合动力城市客车

103

江西江铃集团晶马汽车有限公司

62

晶马牌

JMV6700BEV

纯电动客车

104

郑州宇通客车股份有限公司

71

宇通牌

ZK6105CHEVNPG11

混合动力城市客车

105

郑州宇通客车股份有限公司

71

宇通牌

ZK6105CHEVNPG52

混合动力城市客车

106

郑州宇通客车股份有限公司

71

宇通牌

ZK6105CHEVPG31

混合动力城市客车

107

郑州宇通客车股份有限公司

71

宇通牌

ZK6105PHEVNPG3

混合动力城市客车

108

郑州宇通客车股份有限公司

71

宇通牌

ZK6115PHEVPG1

混合动力城市客车

109

郑州宇通客车股份有限公司

71

宇通牌

ZK6115PHEVPT5

混合动力客车

110

郑州宇通客车股份有限公司

71

宇通牌

ZK6119BEVQ2

纯电动客车

111

郑州宇通客车股份有限公司

71

宇通牌

ZK6120CHEVNPG11

混合动力城市客车

112

郑州宇通客车股份有限公司

71

宇通牌

ZK6120CHEVPG31

混合动力城市客车

113

郑州宇通客车股份有限公司

71

宇通牌

ZK6120PHEVNPG3

混合动力城市客车

114

郑州宇通客车股份有限公司

71

宇通牌

ZK6125BEV1Y

纯电动客车

115

郑州宇通客车股份有限公司

71

宇通牌

ZK6125BEV1Z

纯电动客车

116

郑州宇通客车股份有限公司

71

宇通牌

ZK6125BEV2Y

纯电动客车

117

郑州宇通客车股份有限公司

71

宇通牌

ZK6125BEV4

纯电动客车

118

郑州宇通客车股份有限公司

71

宇通牌

ZK6125CHEVNPG11

混合动力城市客车

119

郑州宇通客车股份有限公司

71

宇通牌

ZK6125CHEVNPG52

混合动力城市客车

120

郑州宇通客车股份有限公司

71

宇通牌

ZK6125CHEVPG11

混合动力城市客车

121

郑州宇通客车股份有限公司

71

宇通牌

ZK6125CHEVPG31

混合动力城市客车

122

郑州宇通客车股份有限公司

71

宇通牌

ZK6125CHEVPG52

混合动力城市客车

123

郑州宇通客车股份有限公司

71

宇通牌

ZK6641BEVG10

纯电动城市客车

124

郑州宇通客车股份有限公司

71

宇通牌

ZK6641BEVG4

纯电动城市客车

125

郑州宇通客车股份有限公司

71

宇通牌

ZK6701BEVQ8

纯电动客车

126

郑州宇通客车股份有限公司

71

宇通牌

ZK6808BEVQ1

纯电动客车

127

郑州宇通客车股份有限公司

71

宇通牌

ZK6906BEVQ5

纯电动客车

128

比亚迪汽车工业有限公司

79

比亚迪牌

BYD6121LGEV

纯电动城市客车

129

比亚迪汽车工业有限公司

79

比亚迪牌

BYD6420SHEV

插电式混合动力多用途乘用车

130

比亚迪汽车工业有限公司

79

比亚迪牌

BYD6450VHEV5

插电式混合动力多用途乘用车

131

比亚迪汽车工业有限公司

79

比亚迪牌

BYD6650HZEV

纯电动城市客车

132

比亚迪汽车工业有限公司

79

比亚迪牌

BYD6710HLEV

纯电动客车

133

比亚迪汽车工业有限公司

79

比亚迪牌

BYD6710HZEV

纯电动城市客车

134

比亚迪汽车工业有限公司

79

比亚迪牌

CK6100LGEV

纯电动城市客车

135

比亚迪汽车工业有限公司

79

比亚迪牌

CK6120LGEV2

纯电动城市客车

136

比亚迪汽车工业有限公司

79

比亚迪牌

CK6121LGEV

纯电动城市客车

137

比亚迪汽车工业有限公司

79

比亚迪牌

CK6800LZEV

纯电动城市客车

138

比亚迪汽车工业有限公司

79

比亚迪牌

CK6800LZEV2

纯电动城市客车

139

比亚迪汽车工业有限公司

79

腾势牌

QCJ7007BEV

纯电动轿车

140

湖南江南汽车制造有限公司

84

众泰牌

JNJ6408EV1

纯电动多用途乘用车

141

湖南江南汽车制造有限公司

84

江南牌

JNJ7000EVA6

纯电动轿车

142

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVE3

纯电动轿车

143

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVE4

纯电动轿车

144

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVK

纯电动轿车

145

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVK1

纯电动轿车

146

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVS

纯电动轿车

147

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVS1

纯电动轿车

148

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVX7

纯电动轿车

149

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVX8

纯电动轿车

150

湖南江南汽车制造有限公司

84

众泰牌

JNJ7000EVX9

纯电动轿车

151

广州汽车集团乘用车有限公司

89

传祺(Trumpchi)牌

GAC7100SHEVD5

增程式混合动力轿车

152

重庆力帆乘用车有限公司

93

力帆牌

LF7002CEV260

纯电动轿车

153

重庆长安汽车股份有限公司

96

长安牌

SC7003AEV

纯电动轿车

154

四川野马汽车股份有限公司

101

野马牌

SQJ6111B3BEV

纯电动城市客车

155

四川野马汽车股份有限公司

101

野马牌

SQJ6420BEV

纯电动乘用车

156

四川野马汽车股份有限公司

101

野马牌

SQJ6420SHEV

插电式混合动力乘用车

157

四川野马汽车股份有限公司

101

野马牌

SQJ6460BEV

纯电动乘用车

158

四川野马汽车股份有限公司

101

野马牌

SQJ6610BEV

纯电动客车

159

四川野马汽车股份有限公司

101

野马牌

SQJ6900B3BEV

纯电动客车

160

比亚迪汽车有限公司

108

比亚迪牌

BYD6460STHEV1

插电式混合动力多用途乘用车

161

比亚迪汽车有限公司

108

比亚迪牌

BYD7005BEV

纯电动轿车

162

比亚迪汽车有限公司

108

比亚迪牌

BYD7150WT5HEV

插电式混合动力轿车

163

比亚迪汽车有限公司

108

比亚迪牌

BYD7150WTHEV3

混合动力轿车

164

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6109EV0H

纯电动客车

165

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6109EV0N

纯电动客车

166

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6109EV0N1

纯电动客车

167

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6109EV1N

纯电动客车

168

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6109GAHEVE5BZ

混合动力城市客车

169

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV0H

纯电动客车

170

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV0N

纯电动客车

171

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV0N1

纯电动客车

172

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV0X1

纯电动客车

173

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV1H

纯电动客车

174

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV1N

纯电动客车

175

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6115HZEV1X1

纯电动客车

176

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6125LZEV0X

纯电动客车

177

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6125LZEV1X

纯电动客车

178

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6125ZEV0H

纯电动客车

179

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6125ZEV0N

纯电动客车

180

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6125ZEV1H

纯电动客车

181

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6129GAEVN1

纯电动城市客车

182

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6129GAHEVE4B

混合动力城市客车

183

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6601BEV1N1

纯电动客车

184

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6601GBEVX2

纯电动城市客车

185

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6602GEVH

纯电动城市客车

186

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6606BEV0X2

纯电动客车

187

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6702EV0N

纯电动客车

188

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6702GEVN

纯电动城市客车

189

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6800GEVN2

纯电动城市客车

190

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6800GEVX

纯电动城市客车

191

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802EV0H

纯电动客车

192

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802EV0N

纯电动客车

193

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802GEVH

纯电动城市客车

194

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802GEVN

纯电动城市客车

195

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802GEVX

纯电动城市客车

196

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802KAEV0H1

纯电动客车

197

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802KAEV0H2

纯电动客车

198

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802KAEV0N

纯电动客车

199

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802KAEV0N1

纯电动客车

200

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6802KAEV1N1

纯电动客车

201

金龙联合汽车工业(苏州)有限公司

112

海格牌

KLQ6850GEVN

纯电动城市客车

202

奇瑞汽车股份有限公司

119

开瑞牌

SQR6440BEVK06

纯电动多用途乘用车

203

奇瑞汽车股份有限公司

119

开瑞牌

SQR6440BEVK08

纯电动多用途乘用车

204

奇瑞汽车股份有限公司

119

奇瑞牌

SQR7000BEVJ00

纯电动轿车

205

奇瑞汽车股份有限公司

119

奇瑞牌

SQR7000BEVJ001

纯电动轿车

206

奇瑞汽车股份有限公司

119

凯翼牌

SQR7000BEVJ51

纯电动轿车

207

奇瑞汽车股份有限公司

119

开瑞牌

SQR7000BEVK08

纯电动轿车

208

江铃控股有限公司

121

江铃牌

JX70010BEV

纯电动轿车

209

江铃控股有限公司

121

江铃牌

JX7005BEV

纯电动轿车

210

江铃控股有限公司

121

江铃牌

JX7006BEV

纯电动轿车

211

江铃控股有限公司

121

江铃牌

JX7007BEV

纯电动轿车

212

江铃控股有限公司

121

江铃牌

JX7008BEV

纯电动轿车

213

江铃控股有限公司

121

江铃牌

JX7009BEV

纯电动轿车

214

上海汽车集团股份有限公司

122

荣威牌

CSA7144CDPHEV

插电式混合动力轿车

215

上海汽车集团股份有限公司

122

荣威牌

CSA7155TDPHEV

插电混合动力轿车

216

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6106AGBEVL

纯电动城市客车

217

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6106AGHEV14

混合动力城市客车

218

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6110BCBEVL7

纯电动客车

219

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6113BYBEVL3

纯电动客车

220

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6113BYBEVL4

纯电动客车

221

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6113BYPHEVD4

混合动力客车

222

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6127AGPHEVN51

混合动力城市客车

223

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6129HYPHEVD4

混合动力客车

224

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6610CEBEVL2

纯电动客车

225

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6610CEBEVL3

纯电动客车

226

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6610CEBEVL4

纯电动客车

227

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6662AGBEVL

纯电动城市客车

228

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6662AGBEVL1

纯电动城市客车

229

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6706BYBEVL

纯电动客车

230

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6706BYBEVL1

纯电动客车

231

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6706BYBEVL2

纯电动客车

232

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6802AGBEVL

纯电动城市客车

233

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6850AGBEVL2

纯电动城市客车

234

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6850AGPHEVD51

混合动力城市客车

235

厦门金龙联合汽车工业有限公司

123

金龙牌

XMQ6850AGPHEVN51

混合动力城市客车

236

厦门金龙旅行车有限公司

124

金旅牌

XML6102JEV10

纯电动客车

237

厦门金龙旅行车有限公司

124

金旅牌

XML6102JEV10C

纯电动城市客车

238

厦门金龙旅行车有限公司

124

金旅牌

XML6102JEV30

纯电动客车

239

厦门金龙旅行车有限公司

124

金旅牌

XML6105JEV20C

纯电动城市客车

240

厦门金龙旅行车有限公司

124

金旅牌

XML6105JEV30C

纯电动城市客车

241

厦门金龙旅行车有限公司

124

金旅牌

XML6105JEV60C

纯电动城市客车

242

厦门金龙旅行车有限公司

124

金旅牌

XML6105JHEVA5C1

混合动力城市客车

243

厦门金龙旅行车有限公司

124

金旅牌

XML6105JHEVA5CN1

混合动力城市客车

244

厦门金龙旅行车有限公司

124

金旅牌

XML6112JEV10

纯电动客车

245

厦门金龙旅行车有限公司

124

金旅牌

XML6112JEV20

纯电动客车

246

厦门金龙旅行车有限公司

124

金旅牌

XML6112JEV30

纯电动客车

247

厦门金龙旅行车有限公司

124

金旅牌

XML6112JEV50

纯电动客车

248

厦门金龙旅行车有限公司

124

金旅牌

XML6112JEV60

纯电动客车

249

厦门金龙旅行车有限公司

124

金旅牌

XML6112JEV70

纯电动客车

250

厦门金龙旅行车有限公司

124

金旅牌

XML6112JHEVA8C

混合动力城市客车

251

厦门金龙旅行车有限公司

124

金旅牌

XML6115JEV20C

纯电动城市客车

252

厦门金龙旅行车有限公司

124

金旅牌

XML6115JEV30C

纯电动城市客车

253

厦门金龙旅行车有限公司

124

金旅牌

XML6115JEV50C

纯电动城市客车

254

厦门金龙旅行车有限公司

124

金旅牌

XML6115JEV60C

纯电动城市客车

255

厦门金龙旅行车有限公司

124

金旅牌

XML6122JEV10

纯电动客车

256

厦门金龙旅行车有限公司

124

金旅牌

XML6122JHEVA8C

混合动力城市客车

257

厦门金龙旅行车有限公司

124

金旅牌

XML6125JEV50C

纯电动城市客车

258

厦门金龙旅行车有限公司

124

金旅牌

XML6125JEV60C

纯电动城市客车

259

厦门金龙旅行车有限公司

124

金旅牌

XML6125JEVB0C

纯电动城市客车

260

厦门金龙旅行车有限公司

124

金旅牌

XML6125JEVC0C

纯电动城市客车

261

厦门金龙旅行车有限公司

124

金旅牌

XML6125JHEVA5C1

混合动力城市客车

262

厦门金龙旅行车有限公司

124

金旅牌

XML6532JEV70

纯电动轻型客车

263

厦门金龙旅行车有限公司

124

金旅牌

XML6532JEV80

纯电动轻型客车

264

厦门金龙旅行车有限公司

124

金旅牌

XML6532JEVA0

纯电动轻型客车

265

厦门金龙旅行车有限公司

124

金旅牌

XML6532JEVD0

纯电动轻型客车

266

厦门金龙旅行车有限公司

124

金旅牌

XML6532JEVF0

纯电动轻型客车

267

厦门金龙旅行车有限公司

124

金旅牌

XML6532JEVG0

纯电动轻型客车

268

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV10

纯电动客车

269

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV20

纯电动客车

270

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV30

纯电动客车

271

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV50

纯电动客车

272

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV60

纯电动客车

273

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV80

纯电动客车

274

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEV90

纯电动客车

275

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEVB0

纯电动客车

276

厦门金龙旅行车有限公司

124

金旅牌

XML6609JEVC0

纯电动客车

277

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV10C

纯电动城市客车

278

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV20

纯电动客车

279

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV30

纯电动客车

280

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV30C

纯电动城市客车

281

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV50C

纯电动城市客车

282

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV80

纯电动客车

283

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV80C

纯电动城市客车

284

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEV90

纯电动客车

285

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEVA0

纯电动客车

286

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEVA0C

纯电动城市客车

287

厦门金龙旅行车有限公司

124

金旅牌

XML6700JEVG0

纯电动客车

288

厦门金龙旅行车有限公司

124

金旅牌

XML6805JEV20C

纯电动城市客车

289

厦门金龙旅行车有限公司

124

金旅牌

XML6827JEV10

纯电动客车

290

厦门金龙旅行车有限公司

124

金旅牌

XML6827JEV20

纯电动客车

291

厦门金龙旅行车有限公司

124

金旅牌

XML6827JEV30

纯电动客车

292

厦门金龙旅行车有限公司

124

金旅牌

XML6827JHEV15C

混合动力城市客车

293

厦门金龙旅行车有限公司

124

金旅牌

XML6827JHEV18C

混合动力城市客车

294

厦门金龙旅行车有限公司

124

金旅牌

XML6907JEV10

纯电动客车

295

中通客车控股股份有限公司

125

中通牌

LCK6106PHEVC

插电式混合动力城市客车

296

中通客车控股股份有限公司

125

中通牌

LCK6107PHEVC

插电式混合动力城市客车

297

中通客车控股股份有限公司

125

中通牌

LCK6107PHEVNC

插电式混合动力城市客车

298

中通客车控股股份有限公司

125

中通牌

LCK6108EVG4

纯电动城市客车

299

中通客车控股股份有限公司

125

中通牌

LCK6108EVG5

纯电动城市客车

300

中通客车控股股份有限公司

125

中通牌

LCK6118EV

纯电动客车

301

中通客车控股股份有限公司

125

中通牌

LCK6122EVG

纯电动城市客车

302

中通客车控股股份有限公司

125

中通牌

LCK6127PHEVC

插电式混合动力城市客车

303

中通客车控股股份有限公司

125

中通牌

LCK6127PHEVNC

插电式混合动力城市客车

304

中通客车控股股份有限公司

125

中通牌

LCK6600BEV1

纯电动客车

305

中通客车控股股份有限公司

125

中通牌

LCK6609EV3

纯电动客车

306

中通客车控股股份有限公司

125

中通牌

LCK6609EV5

纯电动客车

307

中通客车控股股份有限公司

125

中通牌

LCK6663EVG

纯电动城市客车

308

中通客车控股股份有限公司

125

中通牌

LCK6808EV2

纯电动客车

309

中通客车控股股份有限公司

125

中通牌

LCK6809EVG11

纯电动城市客车

310

中通客车控股股份有限公司

125

中通牌

LCK6809EVG12

纯电动城市客车

311

中通客车控股股份有限公司

125

中通牌

LCK6820PHENV

混合动力城市客车

312

中通客车控股股份有限公司

125

中通牌

LCK6820PHEV

插电式混合动力客车

313

中通客车控股股份有限公司

125

中通牌

LCK6820PHEVG

混合动力城市客车

314

中通客车控股股份有限公司

125

中通牌

LCK6850PHEVNG

混合动力城市客车

315

海马轿车有限公司

128

海马牌

HMA7004S30BEV

纯电动轿车

316

海马轿车有限公司

128

海马牌

HMA7005S30BEV

纯电动轿车

317

上海申龙客车有限公司

129

申龙牌

SLK6663ULE0BEVS1

纯电动城市客车

318

江苏九龙汽车制造有限公司

141

大马牌

HKL6600BEV5

纯电动客车

319

江苏九龙汽车制造有限公司

141

大马牌

HKL6600BEV6

纯电动客车

320

江苏九龙汽车制造有限公司

141

大马牌

HKL6600BEVB1

纯电动客车

321

江苏九龙汽车制造有限公司

141

大马牌

HKL6601BEV

纯电动客车

322

南京金龙客车制造有限公司

142

开沃牌

NJL6100BEV1

纯电动城市客车

323

南京金龙客车制造有限公司

142

开沃牌

NJL6100BEV13

纯电动城市客车

324

南京金龙客车制造有限公司

142

开沃牌

NJL6100BEV2

纯电动城市客车

325

南京金龙客车制造有限公司

142

开沃牌

NJL6100BEV3

纯电动城市客车

326

南京金龙客车制造有限公司

142

开沃牌

NJL6100BEV5

纯电动城市客车

327

南京金龙客车制造有限公司

142

开沃牌

NJL6100BEV7

纯电动城市客车

328

南京金龙客车制造有限公司

142

开沃牌

NJL6107BEV

纯电动客车

329

南京金龙客车制造有限公司

142

开沃牌

NJL6107BEV1

纯电动客车

330

南京金龙客车制造有限公司

142

开沃牌

NJL6107BEV2

纯电动客车

331

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV10

纯电动客车

332

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV11

纯电动客车

333

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV12

纯电动客车

334

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV4

纯电动客车

335

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV7

纯电动客车

336

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV8

纯电动客车

337

南京金龙客车制造有限公司

142

开沃牌

NJL6117BEV9

纯电动客车

338

南京金龙客车制造有限公司

142

开沃牌

NJL6118BEV1

纯电动客车

339

南京金龙客车制造有限公司

142

开沃牌

NJL6118BEV4

纯电动客车

340

南京金龙客车制造有限公司

142

开沃牌

NJL6118BEV5

纯电动客车

341

南京金龙客车制造有限公司

142

开沃牌

NJL6118BEV7

纯电动客车

342

南京金龙客车制造有限公司

142

开沃牌

NJL6118BEV9

纯电动客车

343

南京金龙客车制造有限公司

142

开沃牌

NJL6120BEV

纯电动客车

344

南京金龙客车制造有限公司

142

开沃牌

NJL6129BEV12

纯电动城市客车

345

南京金龙客车制造有限公司

142

开沃牌

NJL6129BEV3

纯电动城市客车

346

南京金龙客车制造有限公司

142

开沃牌

NJL6129BEV5

纯电动城市客车

347

南京金龙客车制造有限公司

142

开沃牌

NJL6129BEV8

纯电动城市客车

348

南京金龙客车制造有限公司

142

开沃牌

NJL6129BEV9

纯电动城市客车

349

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV24

纯电动客车

350

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV25

纯电动客车

351

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV28

纯电动客车

352

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV30

纯电动客车

353

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV31

纯电动城市客车

354

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV32

纯电动客车

355

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV41

纯电动客车

356

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV45

纯电动客车

357

南京金龙客车制造有限公司

142

开沃牌

NJL6600BEV49

纯电动客车

358

南京金龙客车制造有限公司

142

开沃牌

NJL6601BEV5

纯电动客车

359

南京金龙客车制造有限公司

142

开沃牌

NJL6680BEV16

纯电动城市客车

360

南京金龙客车制造有限公司

142

开沃牌

NJL6680BEV20

纯电动城市客车

361

南京金龙客车制造有限公司

142

开沃牌

NJL6680BEV8

纯电动城市客车

362

南京金龙客车制造有限公司

142

开沃牌

NJL6706BEV8

纯电动客车

363

南京金龙客车制造有限公司

142

开沃牌

NJL6706BEV9

纯电动客车

364

南京金龙客车制造有限公司

142

开沃牌

NJL6820BEV

纯电动客车

365

南京金龙客车制造有限公司

142

开沃牌

NJL6820BEV1

纯电动客车

366

南京金龙客车制造有限公司

142

开沃牌

NJL6820BEV3

纯电动客车

367

南京金龙客车制造有限公司

142

开沃牌

NJL6820BEVG

纯电动城市客车

368

南京金龙客车制造有限公司

142

开沃牌

NJL6820BEVG1

纯电动城市客车

369

南京金龙客车制造有限公司

142

开沃牌

NJL6859BEV

纯电动城市客车

370

南京金龙客车制造有限公司

142

开沃牌

NJL6859BEV15

纯电动城市客车

371

南京金龙客车制造有限公司

142

开沃牌

NJL6859BEV18

纯电动城市客车

372

南京金龙客车制造有限公司

142

开沃牌

NJL6859BEV7

纯电动城市客车

373

南京金龙客车制造有限公司

142

开沃牌

NJL6859BEV8

纯电动城市客车

374

南京金龙客车制造有限公司

142

开沃牌

NJL6859BEV9

纯电动城市客车

375

山西皇城相府宇航汽车制造有限公司

(四)01

山西牌

SXK6601TBEV3

纯电动客车

376

山西皇城相府宇航汽车制造有限公司

(四)01

山西牌

SXK6800TBEV

纯电动客车

377

黑龙江龙华汽车有限公司

(八)16

黑龙江牌

HLJ6122PHEV

混合动力城市客车

378

黑龙江龙华汽车有限公司

(八)16

黑龙江牌

HLJ6681BEV

纯电动城市客车

379

上海万象汽车制造有限公司

(九)26

象牌

SXC6110CBEV

纯电动客车

380

上海万象汽车制造有限公司

(九)26

象牌

SXC6110CBEV1

纯电动客车

381

上海万象汽车制造有限公司

(九)26

象牌

SXC6110GBEV2

纯电动城市客车

382

上海万象汽车制造有限公司

(九)26

象牌

SXC6110GBEV3

纯电动城市客车

383

上海万象汽车制造有限公司

(九)26

象牌

SXC6120GBEV3

纯电动城市客车

384

上海万象汽车制造有限公司

(九)26

象牌

SXC6750GBEV1

纯电动城市客车

385

上海万象汽车制造有限公司

(九)26

象牌

SXC6940GBEV

纯电动城市客车

386

上海万象汽车制造有限公司

(九)26

象牌

SXC6940GBEV1

纯电动城市客车

387

江苏常隆客车有限公司

(十)17

常隆牌

YS6103GBEV

纯电动城市客车

388

江苏常隆客车有限公司

(十)17

常隆牌

YS6104GBEV

纯电动城市客车

389

江苏常隆客车有限公司

(十)17

常隆牌

YS6105BEV

纯电动客车

390

江苏常隆客车有限公司

(十)17

常隆牌

YS6107BEV

纯电动客车

391

江苏常隆客车有限公司

(十)17

常隆牌

YS6107GBEV

纯电动城市客车

392

江苏常隆客车有限公司

(十)17

常隆牌

YS6109GBEV

纯电动城市客车

393

江苏常隆客车有限公司

(十)17

常隆牌

YS6123GBEV

纯电动城市客车

394

江苏常隆客车有限公司

(十)17

常隆牌

YS6124GBEV

纯电动城市客车

395

江苏常隆客车有限公司

(十)17

常隆牌

YS6126BEV

纯电动客车

396

江苏常隆客车有限公司

(十)17

常隆牌

YS6126GBEV

纯电动城市客车

397

江苏常隆客车有限公司

(十)17

常隆牌

YS6127BEV

纯电动客车

398

江苏常隆客车有限公司

(十)17

常隆牌

YS6127GBEV

纯电动城市客车

399

江苏常隆客车有限公司

(十)17

常隆牌

YS6700BEV

纯电动客车

400

江苏常隆客车有限公司

(十)17

常隆牌

YS6757GBEV

纯电动城市客车

401

江苏常隆客车有限公司

(十)17

常隆牌

YS6830GBEV

纯电动城市客车

402

江苏常隆客车有限公司

(十)17

常隆牌

YS6832GBEV

纯电动城市客车

403

江苏常隆客车有限公司

(十)17

常隆牌

YS6834GBEV

纯电动城市客车

404

江苏常隆客车有限公司

(十)17

常隆牌

YS6836GBEV

纯电动城市客车

405

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6100GEVH3

纯电动城市客车

406

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6100GEVH5

纯电动城市客车

407

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6100GEVH7

纯电动城市客车

408

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6100GEVH8

纯电动城市客车

409

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6120GEVH0

纯电动城市客车

410

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6120GEVH2

纯电动城市客车

411

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6120GEVH3

纯电动城市客车

412

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6120GEVH4

纯电动城市客车

413

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6700XEVH12

纯电动客车

414

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6700XEVH7

纯电动客车

415

江苏陆地方舟新能源电动汽车有限公司

(十)28

陆地方舟牌

RQ6850GEVH1

纯电动城市客车

416

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6100KEV09

纯电动客车

417

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6120KEV07

纯电动客车

418

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6121GEV03

纯电动城市客车

419

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6600KEV05

纯电动客车

420

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6600KEV10

纯电动客车

421

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6601KEV05

纯电动客车

422

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6601KEV10

纯电动客车

423

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6604KEV10

纯电动客车

424

安徽星凯龙客车有限公司

(十二)18

星凯龙牌

HFX6701KEV08

纯电动客车

425

江西凯马百路佳客车有限公司

(十四)03

江西牌

JXK6121BEV

纯电动城市客车

426

烟台舒驰客车有限责任公司

(十五)18

舒驰牌

YTK6118EV2

纯电动客车

427

中国重汽集团济南豪沃客车有限公司

(十五)19

黄河牌

JK6106GBEV2

纯电动城市客车

428

中国重汽集团济南豪沃客车有限公司

(十五)19

黄河牌

JK6856GBEV

纯电动城市客车

429

中国重汽集团济南豪沃客车有限公司

(十五)19

黄河牌

JK6856GBEV2

纯电动城市客车

430

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6100EVL

纯电动旅游客车

431

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6120EVG1

纯电动城市客车

432

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6120EVG4

纯电动城市客车

433

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6120EVG5

纯电动城市客车

434

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6122EVG

纯电动城市客车

435

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6830EVG

纯电动城市客车

436

山东沂星电动汽车有限公司

(十五)25

飞燕牌

SDL6832EVG

纯电动城市客车

437

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6100BEVH

纯电动城市客车

438

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6101BEVH

纯电动城市客车

439

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6120BEVHM1

纯电动城市客车

440

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6120BEVHM2

纯电动城市客车

441

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6610BEVH

纯电动城市客车

442

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6611BEVQ

纯电动客车

443

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6612BEVZ

纯电动客车

444

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6650BEVH

纯电动城市客车

445

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6660BEVH

纯电动城市客车

446

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6702BEVH

纯电动客车

447

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6820BEVH

纯电动城市客车

448

东风扬子江汽车(武汉)有限责任公司

(十七)48

扬子江牌

WG6821BEVH

纯电动客车

449

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6106EHEV08

混合动力城市客车

450

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6106EHEV11

混合动力城市客车

451

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6106EHEVN06

混合动力城市客车

452

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6106HEV24

混合动力城市客车

453

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6129EHEV04

混合动力城市客车

454

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6129EHEV08

混合动力城市客车

455

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6600EV02

纯电动客车

456

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6820BEV01

纯电动城市客车

457

湖南南车时代电动汽车股份有限公司

(十八)23

南车时代牌

TEG6851BEV01

纯电动城市客车

458

珠海广通汽车有限公司

(十九)28

广通牌

GTQ6105BEVB1

纯电动城市客车

459

珠海广通汽车有限公司

(十九)28

广通牌

GTQ6701BEV1

纯电动旅游客车

460

成都客车股份有限公司

(二十二)10

蜀都牌

CDK6113CEDHEV

混合动力城市客车

461

成都客车股份有限公司

(二十二)10

蜀都牌

CDK6125CBEV1

纯电动城市客车

462

成都客车股份有限公司

(二十二)10

蜀都牌

CDK6604BEV

纯电动客车

463

奇瑞万达贵州客车股份有限公司

(二十三)06

万达牌

WD6105EHEV

混合动力城市客车

464

奇瑞万达贵州客车股份有限公司

(二十三)06

万达牌

WD6115EHEV

混合动力城市客车

465

奇瑞万达贵州客车股份有限公司

(二十三)06

万达牌

WD6125EHEV

混合动力城市客车

466

奇瑞万达贵州客车股份有限公司

(二十三)06

万达牌

WD6602BEV

纯电动客车

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

【其他文章推薦】

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

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

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

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務