從一個簡單的ASP.NET 5站點開啟.NET跨平台之旅


.NET跨平台之旅

在經歷了阿里雲上“黑色1秒”的空歡喜之后,我們“被迫”考慮實現.NET的跨平台,將Web服務器由Windows換成Linux。而這種“被迫”在一個存在已久的願望下,變得水到渠成。這個願望就是 —— “Mac上寫.NET程序,Linux上跑.NET程序”。

既然水也到了,渠也成了,那我們還等什么,動身起程吧。

今天我們以我們邁出的第一步——一個部署在Linux上基於dnx/corefx/coreclr的非常簡單的ASP.NET 5/MVC 6站點——宣布“.NET跨平台之旅”開啟了!

這個基於跨平台.NET的站點已經上線,訪問網址:http://about.cnblogs.com/

該站點部署在CentOS服務器上(部署步驟),服務器上只安裝了dnx,沒有安裝mono,所以是完全基於.NET Core運行。后端Web服務器用的是Kestrel,也是目前跨平台.NET在非Windows平台上唯一能用的Web服務器。

CentOS服務器上運行情況如下:

[root@about-server AboutUs]# dnx . kestrel
Started

前端Web服務器用的是阿里雲SLB(負載均衡),如果不用SLB,可以直接在CentOS上用nginx做反向代理。為什么要用前端Web服務器?因為Kestrel Web服務器實在太簡陋了,連keep-alive與http compression的功能都沒有。

該站點的ASP.NET 5程序是在Ubuntu服務器上用vim進行開發的。

項目文件結構如下:

.
├── Controllers
│   ├── AboutController.cs
│   └── HomeController.cs
├── Extensions
│   └── HtmlHelperExtensions.cs
├── project.json
├── project.lock.json
├── Startup.cs
├── Views
│   ├── About
│   │   ├── Ad.cshtml
│   │   ├── Contact.cshtml
│   │   ├── Intro.cshtml
│   │   └── Job.cshtml
│   ├── Shared
│   │   └── _Layout.cshtml
│   └── _ViewStart.cshtml
└── wwwroot
    ├── images
    │   ├── about_cnbogs.gif
    │   ├── icon_arrow.gif
    │   └── icon_triangle.gif
    └── styles
        └── about.css

project.json文件中的配置:

{
    "webroot": "wwwroot",
    "exclude": ["wwwroot"],
    "commands":{
        "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --server.urls http://localhost:8001"
    },
    "dependencies":{
        "Kestrel": "1.0.0-*",
        "Microsoft.AspNet.Mvc": "6.0.0-*",
        "Microsoft.AspNet.StaticFiles": "1.0.0-*",
        "Microsoft.AspNet.Diagnostics": "1.0.0-*"
    },
    "frameworks":{
        "dnxcore50": {}
    }
}

frameworks中只有dnxcore50,說明程序是完全基於.NET Core的。但由於基於coreclr的dnu restore功能目前無法使用,所以在開發環境中不得不安裝mono,用基於mono的dnu retore安裝nuget包包。

Startup.cs中的代碼如下:

using Microsoft.AspNet.Builder;
using Microsoft.Framework.DependencyInjection;

namespace CNBlogs.AbouUs.Web
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.UseErrorPage();

            app.UseMvcWithDefaultRoute();

            app.UseStaticFiles();
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
        }
    }
}

(注:project.json與Startup.cs中都沒有多余的配置與代碼)

程序非常簡單,沒有數據庫操作,主要就是顯示文字內容。稍微復雜些的就是一個HtmlHelpder擴展方法(代碼是從現有項目中移植過來的),根據訪問的URL自動高亮左側的導航標簽,代碼如下:

using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;

namespace Microsoft.AspNet.Mvc.Rendering
{
    public static class HtmlHelperExtensions
    {
        public static HtmlString TabLink(this IHtmlHelper htmlHelper, string linkText, string linkUrl, string viewName)
        {
            var view = htmlHelper.ViewContext.View as RazorView;
            if (view != null && view.Path.IndexOf("/" + viewName + ".", System.StringComparison.OrdinalIgnoreCase) > -1)
            {
                return htmlHelper.Raw(string.Format("<a href=\"{0}\" class=\"current\">{1}</a>", linkUrl, linkText));
            }
            else
            {
                return htmlHelper.Raw(string.Format("<a href=\"{0}\">{1}</a>", linkUrl, linkText));
            }
        }
    }
}

這個ASP.NET 5程序的代碼是一步一步從無到有用vim手寫出來的(除了視圖與HtmlHelperExtensions), 從中更深刻地了解了ASP.NET 5的一些工作原理,從而也得到了一個運行這個簡單的ASP.NET 5程序所需的最小配置。

在開發過程中最痛苦的是修改代碼后ASP.NET 5不會自動重新編譯,需要重新用dnx運行程序;而且Kestrel目前有bug,無法退出,即使關閉ssh窗口,也照樣運行,必須用非常規手段強制結束進程(ps all; kill -9 [PID])。但Kestrel的這個bug卻帶來一個讓人驚喜的副作用,正因為它一啟動就一直運行,怎么也不會退出,相當於以一種后台服務的方式運行,一下子解決了部署時如何后台運行ASP.NET 5站點的問題。

雖然只是一個非常簡單的ASP.NET 5程序,雖然只是.NET跨平台之旅非常非常小的一步,但它卻是重要的一步,因為它讓我們實實在在地感受到了——.NET跨平台,路在腳下。

【更新】

6月29日15:35左右,出現異常造成kestrel退出,重新運行dnx之后恢復正常。異常信息如下:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.AspNet.Server.Kestrel.Networking.UvShutdownReq.UvShutdownCb(IntPtr ptr, Int32 status)

6月30日凌晨3:18左右,kestrel掛掉1次。

6月30日18:19左右,因為dnx內存泄漏而掛掉(懷疑是kestrel引起的內存泄漏)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM