問題和需求
從2004年上線,ZLDNN.COM執行已經超過16年了,一直使用DotNetNuke平臺(現在叫DNN Platform),從最初的DotNetNuke 2.1到現在使用的7.4。先是在亦莊的獨立伺服器託管,後來遷到美國的PowerDNN的雲伺服器ECS,再後來遷移到阿里雲的ECS,採用Windows 2008系統,執行幾年以後,C盤已經滿了,可又沒有辦法清理,網站速度越來越慢,乾脆長痛不如短痛,徹底更新一下。
DotNetNuke嚴重依賴Web Form技術,其開發團隊到現在也沒有找到從.Net Framework遷移到.Net Core以及最新的.Net 5或.Net 6的合適技術路線,導致其只能在Windows下執行。另外一個問題是DotNetNuke只能使用SqlServer資料庫,無法使用更便宜更靈活的資料庫。網站的遷移實際上是在滿足現有基本功能的前提下,採用新的技術重新開發。在選擇新的技術之前,首先需要梳理一下網站的功能,確定哪些需要保留,哪些可以通過其它方式替代,哪些可以暫時不實現。網站需要保留的部分包括:
- 資料:包括使用者資料、訂單資料、技術支援資料等。
- 網站頁面的Url: 大部分Url已經是SEO友好,但有些頁面仍然採用web form模式,比如GetLicense.aspx,這部分Url也需要保留。
- 關鍵功能:諸如訂單接收、產品啟用等。
其它的需求還有,希望網站可以執行在維護成本比較低的輕量級應用伺服器中,可以採用MySql等開源資料庫,視覺效果上儘量與原有系統相同等等。還要留有使用者管理已經使用者註冊的介面。
在大的技術路線上,仍然採用.Net體系,研究了幾種技術,包括Qutane、Orchard等,最後決定採用Abp vNext進行開發。
開發
將開發中遇到的具體問題和最終的解決方案總結一下。
外觀
採用ABP自帶的Theme,根據現有網站的風格進行修改,保持風格大體一致。修改的辦法是從Abp原始碼中複製Theme相關檔案到自定義專案對應的目錄中,直接修改就可以了。需要修改的檔案如下圖:
網站的顏色等需要修改檔案global-styles.css:
首頁
DotNetNuke完全採用動態頁面,原來的首頁採用的是HTML模組加上DNNArticle的子模組,考慮到首頁的更新頻率不高,這次採用靜態頁面。
維護頁面
這部分主要是產品、版本、訂單等等的維護,屬於標準的CRUD介面。這部分採用ABP的標準化設計,首先設計各個實體,然後使用AbpHelper.Gui和AbpHelper.CLI生成相關程式碼和介面。所生成的介面基本可以使用,需要改造的地方是增加查詢功能和調整許可權。這裡簡單介紹一下如何增加查詢功能。
ABP MVC/Razor Page 模板生成的基於DataTables.Net的頁面支援分頁和排序,但預設情況下不支援查詢,需要根據實際情況自行新增。我們可以利用DataTables.Net自帶的查詢功能實現查詢。
首先修改Application專案,增加帶有查詢的Application服務。先在PagedAndSortedResultRequestDto基礎上定義帶有關鍵字的Dto:
public class OrderNotificationSearchDto: PagedAndSortedResultRequestDto
{
public string Key { get; set; }
}
然後在Application 服務中增加查詢服務:
public async Task<PagedResultDto<OrderNotificationDto>> GetSearchListAsync(OrderNotificationSearchDto input)
{
var query = await CreateFilteredQueryAsync(input);
if (!string.IsNullOrEmpty(input.Key))
{
query = query.Where(o => o.InvoiceID.Contains(input.Key)
|| o.OptionName.Contains(input.Key)
|| o.PackageName.Contains(input.Key)
|| o.BillToEmail.Contains(input.Key));
}
var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input);
query = ApplyPaging(query, input);
var entities = await AsyncExecuter.ToListAsync(query);
var entityDtos = await MapToGetListOutputDtosAsync(entities);
return new PagedResultDto<OrderNotificationDto>(
totalCount,
entityDtos
);
}
然後需要改造客戶端,首先將index.js中datatables的設定searching改為true:
var dataTable = $('#OrderNotificationTable').DataTable(abp.libs.datatables.normalizeConfiguration({
processing: true,
serverSide: true,
paging: true,
searching: true,
接下來修改ajax的定義:
//ajax: abp.libs.datatables.createAjax(service.getList),
ajax: abp.libs.datatables.createAjax(service.getSearchList, inputAction, responseCallback),
將getList修改為新的getSearchList,增加新的傳入引數和Callback。這兩個函式定義如下:
var inputAction = function (requestData, dataTableSettings) {
var ctl = $("#OrderNotificationTable_filter input").val();
return {
key: ctl,
};
};
var responseCallback = function (result) {
// your custom code.
return {
recordsTotal: result.totalCount,
recordsFiltered: result.totalCount,
data: result.items
};
};
網站資料的匯入
這部分主要包括產品資料和與啟用相關的資料,採用自己寫的一個面向.Net Core的ADO庫,將原有的資料匯出到Xml中,在新的應用中從Xml中讀取資料進行初始化。
產品內容頁
產品的內容原來保持在資料庫中,現在改為在檔案中儲存,載入產品頁時,從檔案讀出展示。
外部資料交換
主要包括接收從DNNStore發來的資料和產品啟用兩部分。採用Application Service實現,通過Apb框架的動態Web Api可以訪問。
Url重定位
包括與外界交換資料的Url和為了保證SEO一致的介面Url。採用.Net Core的ReWrite中介軟體實現,感覺這部分真的很好用。程式碼如下:
var options = new RewriteOptions()
.AddRewrite(@"^GetLicense.aspx", "Products/Services/ManualActivate",true)
.AddRewrite(@"^Products/currentpage/(\d+)", "Products?currentpage=$1", true)
.AddRewrite(@"^ProductDetail/(.+)", "Products/ViewDetail?name=$1", true)
.AddRewrite(@"^LicenseCode.aspx", "api/app/activate/req-license-code", true)
.AddRewrite(@"^desktopmodules/OrderNotification/OrderNotify.aspx", "api/app/activate/save-order", true)
app.UseRewriter(options);
還有其它一些細節包括關閉多租戶、關閉使用者註冊、國際化修改等等。
從十一前開始,斷斷續續開發了兩到三週的時間。
部署和執行
以前一直在Windows生態中,部署應用似乎不是大問題,只有在IIS上建立網站或者應用就可以了。現在希望將ZLDNN.COM遷移到阿里雲的輕量級伺服器,在Linux系統下部署,還是遇到一些挑戰。
首先解決.Net Core應用在Linux上執行的問題。由於在生產環境中只執行一個.Net Core應用,所以在生成部署檔案時採用獨立執行模式,這樣就不需要在生產環境中安裝.Net框架。這一步沒有遇到大問題,測試應用能夠執行。
然後是ABP應用在生產環境上執行,這裡遇到一個問題,Couldn’t find a valid ICU package installed on the system.這個問題在本地測試沒有遇到,查了一下是沒有安裝ICU庫,安裝完成後問題解決了。
資料庫的配置沒有遇到太大麻煩,但在後期執行時出現了MySql異常退出的問題,發現是記憶體問題,建立記憶體交換檔案後解決了。
Apache伺服器配置花了一些時間,因為兩個域名駐留在同一個伺服器上,需要將Apache伺服器配置為反向代理伺服器,由於對Apache伺服器不熟悉,折騰了一些時間,不過最後也成功了。
到現在新網站執行了兩個多月,基本沒有遇到太大的問題。效果還是不錯的,速度提升很多。