從功能上來說,請參考 預告篇,因自知當時預告篇沒有任何含金量,所以並沒有主動推送到首頁,而是私下的給一些人發的。 從個人角度上來說,我希望.net的環境會越來越好,就我自己的成長曲線是從mxdn開始自學、cxdn嘗試解答問題、博客園讀別人博客再到自己寫博客、最後到工作中經常使用到的stackxxxx ...
做這個開源項目的意義是什麼?(口水自問自答,不喜可略過) |
從功能上來說,請參考 預告篇,因自知當時預告篇沒有任何含金量,所以並沒有主動推送到首頁,而是私下的給一些人發的。
從個人角度上來說,我希望.net的環境會越來越好,就我自己的成長曲線是從mxdn開始自學、cxdn嘗試解答問題、博客園讀別人博客再到自己寫博客、最後到工作中經常使用到的stackxxxxflow、gxxgle。這其中我當然是走了很多彎路,踩過無數的坑,也埋了無數的坑。現在自己有了一點小小的能力,想盡自己所能,通過一個項目整理出來給大家參考、學習的同時也能給自己一些意見。對新人來說也算是一種回饋,對老人來說也算是互相切磋互相提升。
什麼是分散式部署解決方案? |
部署也有很多人叫發佈。那正常的流程是什麼樣的呢?
相信這張圖大家都不會太陌生。一般少數幾台伺服器的時候直接這樣發佈是最省時省力的。
但是,如果有一天,你的伺服器變成幾十臺,然後又面臨著經常發佈的情況該怎麼辦呢?
@echo off echo Start to Publish ApplicationName All Site set local="C:\inetpub\ApplicationName" Set RemotePath=C$\inetpub\ApplicationName For %%I in (192.168.0.2 192.168.0.3 ... 192.168.0.n) do ( echo "Publish ApplicationName %%I" net use \\%%I\ipc$ Password /User:UserName For %%P in (default) do ( echo "Publish \\%%I\%RemotePath%\"dd xcopy /e /y %local% "\\%%I\%RemotePath%\" ) net use \\%%I\ipc$ /del ) :End pause;
上面這段代碼,相信也有一部分人用過吧。使用流程也比較簡單,先用vs發佈到本地,然後再使用批處理文件,通過發佈命令來進行多台網站的部署。
突然有一天,你是上司跟你說,你的這段批處理有很多問題,比如不利於維護、沒有部署記錄、發佈後首次訪問很慢、沒有版本管理、部署過程一旦發生異常也沒有容錯機制等等。
是的,這些問題都還是基礎的。如果你的伺服器數量達到一定級別以後,你的部署會變得異常艱難。某台伺服器上部署了多少個服務、某幾台伺服器是一組,這些會讓你抓狂,甚至想說髒話,就如同下圖。
由於後面還會有一系列文章要出,此處就不再過多的解釋,當你看到完整的項目之後,相信你會對它有一個新的認識。
第一個正式版包含哪些功能? |
請允許我偷個懶,從預告篇把尚不成熟的功能列表copy一份過來:
1 基礎的許可權控制(可能只支持一個角色,甚至是寫死)
2 部署項目管理(以Jenkins為例,做自動化構建方案)
3 部署伺服器管理(以Aliyun伺服器為例)
4 部署組管理(包括部署組、部署組項)
5 創建部署任務(包括觸發自動化構建、部署文件關聯等)
6 部署伺服器常駐服務(以Windows Service的形式駐留,主要完成中控的指令協助部署)
7 一鍵部署(支持單台或部署組)
7.1 支持手動綁定歷史部署文件版本(理論上支持所有的,如Jenkins這種構建方案還會涉及到保存構建副本數量和天數等,另本功能只支持單台部署,部署組的修改版本通過創建部署任務時統一指定)
7.2 自動檢測部署文件包狀態(以Jenkins為例,會自動等待構建完畢,並會自行檢測構建狀態判斷是否繼續向下執行)
7.3 下載部署文件包並解壓
7.4 控制負載均衡降權
7.5 部署(包括等待伺服器正在執行的請求完成的檢測)
7.6 觸發緩存(也可以理解為觸發首次訪問,提升用戶體驗)
7.7 控制負載均衡升權
PS:其中為了支持單台伺服器部署,所以一些擴展性功能會採用插件(暫定)的形式允許自行實現,同時也會包含一套以阿裡雲、jenkisn為基礎的示例實現。
後續也會考慮把一些功能提取出來做成API,允許把功能嵌入到自己的系統里去。當然,這個要看有多少人需要了。
核心技術與開發工具 |
後端:.net 4.6.1,EF6,mvc5(不上.net core的原因是1.1.0目前並不穩定,還是有不少bug,我真的親身踩到了,實在是不想無限踩過去,請原諒我沒有勇於踩坑的心,確確實實是精力有限)
前端:AdminLTE 2 支持PC、Mobile雙端
資料庫:SQL Server LocalDB
IDE:Visual Studio 2017 RC
源碼托管:oschina git
現在做到哪一步了? |
先上一張解決方案資源管理器的截圖,簡單的看下項目結構。
可以看到,目前只有一個項目,而且比較亂,Business、Data、Models 各種亂入。
這麼低級的一個項目怎麼好意思開源的?
是的,沒錯,目前項目狀態就是這樣。
因為我要做的不是發佈出來一個成品,寫個介紹就完了。
我會從0代碼開始在git上保留整個過程。且根據進度不定期更新博文來講解編碼過程中的各種問題以及解決思路。
而下一篇的名字我也已經想好了。
【G】開源的分散式部署解決方案(二) - 好項目是從爛項目基礎上重構出來的
在我的這個開源系列博客中,你可以看到一個開源項目的完整成長歷程。我不知道這個項目會走多遠,但我堅信這個項目一定會幫到一部分人,這就足夠了。
下麵放幾張截圖,也是下一篇內容的主角。
(簡單的登錄頁)
(後臺UI的基礎框架)
(已完成的一個功能,部署伺服器管理)
(支持手機端的table)
登錄的實現 |
為了避免太水的嫌疑,上一點點乾貨。
新建項目時,點擊Change Authentication會看到4個選項。至於如何選擇我就不多說了,我先說說我選了 Identity(Individual User Accounts)踩過的坑。
因為我之前主要是做架構方向的,可以理解為這些都是所謂的“小弟”在做的功能,而我一個不小心就掉進了陷阱里去。說是陷阱吧,其實主要是因為自己不熟悉,畢竟mvc還是比較龐大的,即便你順著它的思路去做,也未必能做得對。
預設情況下生成好的項目是已經使用推薦的EF6實現了整個登錄流程。而我又希望自己可以掌控關鍵的驗證邏輯,所以一路摸下去把 ApplicationUser、AppplicationUserManager、UserManager、UserStore都看了一遍,經過各種嘗試,發現驗證邏輯封裝在Microsoft.AspNet.Identity.EntityFramework(這個是盲打的,已經回不去了,如果錯了歡迎指正)。
找到了目標當然第一想法是功課他,隨著不斷的踩坑發現工作量異常的大,遂放棄。想從另外一個角度入手,因為UserManager才是核心,那我順著這條線是否可以把他已經實現的EF那套開給剔除掉。
於是就有了下麵的代碼:
首先要改造Model,於是自己把 ApplicationUser、IdentityUser、UserStore都重寫了。前面兩個比較簡單,重點是UserStore,要實現IUserStore<TUser>這個介面,這裡是自行編寫驗證邏輯的轉折點。
其次,Controller也進行的小改造,去掉了SignInManager等,只保留了UserManager,同時Startup.Auth裡面的DbContext也換成了自己的。
最後把Name也一同存入了Cookie,方便layout裡面要顯示用戶名。
核心代碼如下:
1.IdentityUser 其實這個類可以跟 ApplicationUser合併的,我也是跟官方生成項目時的寫法保留下來的。可能故意分開在ApplicationUser裡面寫的是邏輯,而IdentityUser是對屬性的定義,這樣會顯得更清晰一點吧,雖然我也會這麼做,也很熱衷於這麼做,但區別是我不會讓ApplicationUser繼承IdentityUser,而是寫一個Business來實現方法做一個徹底的拆分。
public class IdentityUser : IUser<string> { public string Id { get; set; } public string Name { get; set; } public string Password { get; set; } public string Role { get; set; } public string UserName { get; set; } }
2.UserStore其實並沒有多少借鑒的意義,因為這是很小學生的寫法了,主要是為了突出UserStore的重要性。
public class UserStore : IUserStore<ApplicationUser> { public async Task CreateAsync(ApplicationUser user) { using (var dbContext = GDbContext.Create()) { dbContext.User.Add(new User() { UserName = user.UserName, Password = user.Password, Name = user.Name, Role = user.Role, }); await dbContext.SaveChangesAsync(); } } public Task DeleteAsync(ApplicationUser user) { throw new NotImplementedException(); } public void Dispose() { //nothing to do } public Task<ApplicationUser> FindByIdAsync(string userId) { int id = 0; if (!Int32.TryParse(userId, out id)) { throw new ArgumentException(nameof(userId)); } using (var dbContext = GDbContext.Create()) { var user = dbContext.User.SingleOrDefault(u => u.ID == id && !u.IsDelete); return Task.FromResult(new ApplicationUser() { Id = user.ID.ToString(), Name = user.Name, Password = user.Password, Role = user.Role, UserName = user.UserName }); } } public Task<ApplicationUser> FindByNameAsync(string userName) { using (var dbContext = GDbContext.Create()) { var user = dbContext.User.SingleOrDefault(u => u.UserName == userName && !u.IsDelete); return Task.FromResult(new ApplicationUser() { Id = user.ID.ToString(), Name = user.Name, Password = user.Password, Role = user.Role, UserName = user.UserName }); } } public Task UpdateAsync(ApplicationUser user) { throw new NotImplementedException(); } }
3.Startup.Auth ConfigureAuth方法進行瞭如下的改動,主要是修改 DbContext 的獲取,以及SecurityStampValidator.OnvalidateIdentity這個方法的參數調整。
// 配置資料庫上下文、用戶管理器和登錄管理器,以便為每個請求使用單個實例 app.CreatePerOwinContext(GDbContext.Create); app.CreatePerOwinContext(() => new UserManager<ApplicationUser>(new UserStore())); // 使應用程式可以使用 Cookie 來存儲已登錄用戶的信息 // 並使用 Cookie 來臨時存儲有關使用第三方登錄提供程式登錄的用戶的信息 // 配置登錄 Cookie app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { // 當用戶登錄時使應用程式可以驗證安全戳。 // 這是一項安全功能,當你更改密碼或者向帳戶添加外部登錄名時,將使用此功能。 OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<UserManager<ApplicationUser>, ApplicationUser>( validateInterval: TimeSpan.FromMinutes(30), regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) } });
說起來簡單,但真的做起來還是踩過了大大小小的坑,即便是你覺得很不起眼的一個功能,都有可能折騰的你要死要活。
我會告訴你我新建項目、刪除項目、再新建、再刪除,這個過程已經重覆好多遍了嗎?
當你看到一段好的代碼在你面前時,又有幾個人能體會寫的人死了多少腦細胞?
我不會拒絕伸手黨,但我希望伸手的同時能再點個贊,你的支持是無數同行堅持在這條路上的動力。
聲明 |
1.在出第一個正式版之前不會使用任何開源協議
2.永遠免費,不會出什麼專業版、旗艦版之類的進行收費
3.第一個版本完結時間目前還不知道,我這個人懶散慣了,但我會儘量多抽出一些時間儘快寫出來。
最後,本項目暫定名為 G,唯一群號:7424099
Git地址:http://git.oschina.net/doddgu/G (希望大家可以順手點個star,如果有喜歡的朋友捐贈下就更好了,感謝各位的支持)