天天看點

ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus

ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus

本文承接我的上一篇博文: ASP.NET 5 Linux部署,那篇文章主要是針對最新的ASP.NET 5的,但在随後的研究中,我對這種娛樂型的部署依然不是非常滿意,當然其主要原因是因為ASP.NET 5 依然處于RC版本,并不十分成熟. 但可以預見到的是,就算本月ASP.NET 5 RTM版本如期推出,其在Linux上面的開發和部署前景依然不是非常明朗: 特别令人困惑的是,MS在Linux上至今僅僅推出了幾個以開發為目的的簡單伺服器實作,難以在其計劃中尋覓到類似IIS的完整部署環境,那麼所謂的ASP.NET 5的跨平台開發是否隻能停留在實驗室水準? 目前乃至今後很長一段時間内(直到ASP.NET 5完全在Linux上站穩腳跟),我們有沒有更好的選擇?下面我将給出我自己的想法.

這裡首先聲明一點,ASP.NET Linux部署系列僅針對Linux部署環境,不涉及Windows部署環境.下面還是先給出一些概念以便于大家更好的了解後續的内容.

ASP.NET ASP.NET是.NET Framework的一部分,是一項微軟公司的技術,是一種使嵌入網頁中的腳本可由網際網路伺服器執行的伺服器端腳本技術, 本月即将釋出的最新版本是版本5,又成為vNext.
Linux Linux是一套免費使用和自由傳播的類Unix作業系統,是一個基于POSIX和UNIX的多使用者、多任務、支援多線程和多CPU的作業系統. 本文中的Linux主要以Ubuntu作為樣例.
Mono mono是指由Novell公司(由Xamarin發起,并由Miguel de lcaza上司的,一個緻力于開創.NET在Linux上使用的開源工程. 就目前而言,在Linux上的.NET應用還必須基于Mono來運作.
Jexus Jexus 即 Jexus Web Server,簡稱JWS,是Linux平台上的一款ASP.NET WEB伺服器,是目前唯一能夠支援企業級ASP.NET Linux部署的一種方案(其他的伺服器方案無類似定位).
OWIN OWIN在.NET Web Servers與Web Application之間定義了一套标準接口,OWIN的目标是用于解耦Web Server和Web Application。基于此标準,鼓勵開發者開發簡單、靈活的子產品,進而推進.NET Web Development開源生态系統的發展。
MS Owin 微軟開發的基于OWIN規範的底層實作,最新版本是3.0.1,其主項目名稱為Kanata
ASP.NET WebApi ASP.NET MVC 4 包含了 ASP.NET Web API, 這是一個建立可以連接配接包括浏覽器、移動裝置等多種用戶端的 Http 服務的新架構, ASP.NET Web API 也是建構 RESTful 服務的理想平台
RESTful 一種軟體架構風格,設計風格而不是标準,隻是提供了一組設計原則和限制條件。它主要用于用戶端和伺服器互動類的軟體。基于這個風格設計的軟體可以更簡潔,更有層次,更易于實作緩存等機制。
NancyFx Nancy 是一個基于 .NET 和 Mono 平台用于建構輕量級基于 HTTP 的 Web 服務。基于 .NET 和 Mono 平台,架構的目标是保持盡可能多的方式,并提供一個super-duper-happy-path所有互動。官方網站 http://nancyfx.org/

三種選擇

就.NET路線的Web開發來看,不管何種方式,未來必然是基于OWIN開發的事實已經不可動搖了; 在這個基礎上, 我認為目前在Linux上開發并部署.NET Web應用程式有3個路線可以選擇:

  1. 底層Owin路線: 選擇MS的底層OWIN實作,配合其他基于OWIN的獨立元件,形成以底層OWIN為核心的自行搭配的輕型構架,這個方案目前已經可以完美部署到Jexus.
  2. 三方構架路線: 選擇同樣基于OWIN标準的,非MS的三方構架實作, 目前最有潛力,名氣最大的是NancyFx, Nancy架構目前也同樣能較好的部署到Jexus上去.
  3. 正統vNext路線: 選擇MS正統的下一代ASP.NET 5 (vNext),該版本的底層基于OWIN實作(注意任何老的ASP.NET版本都不是基于OWIN的), 可謂是親兒子; 但目前還沒有釋出正式版本,其未來不可預期, 最關鍵的一點是,在Linux上,包括Jexus在内,目前依然沒有完美的基于商業環境的部署伺服器環境支援.

就這3個方案而言,我覺得各有利弊: 底層方案需要更多的自行選擇群組裝,但是與任何基于Owin的元件搭配自如; 三方方案面臨生态環境的問題,由于大部分高端的元件都來自MS,能否真正無縫連接配接需要考驗,自身的生存能力也是問題; 正統方案内容完整,支援強大, 與MS各項技術融合度高,但卻面臨成熟周期問題(時不我待),另外我最不爽的一點是,vNext又一次搞成了鐵索連環船, 連WebApi都和MVC融合了,又給人一種整套推銷的感覺, 有違當初Owin體系的初衷;而最根本的問題是,目前還沒有任何方案給vNext提供一個Linux上的IIS級伺服器,沒有好的載體,僅僅是把vNext的Linux部署定義為娛樂這個顯然看不出太大的誠意.

綜上,我目前還是傾向于使用底層Owin方案,目前商業化開發路線是: 基于MS Owin實作,根據需要加入各種MS穩定元件,比如Web API 2.2 OWIN 5.2.3, Identity Owin 2.2.1, SignalR OWIN 1.2.2, OAuth 3.0.1,和其他所有的通用型元件,如EF, Logging, IoC等等; 最終通過Mono和 Jexus架設到Linux環境.

下面我建一步示範如何組裝MS Owin和Web API 2.2, 并把它們部署到Jexus上去.

開發環境VS 2013, Window 7或 8; 部署環境Ubuntu 15.

第一步: 建立項目

首先,在VS 2103中建立一個Class Library項目,注意隻要Library項目,這裡可以選擇Framework 4.5.2或者4.5.1. 這個項目假設命名為OwinExample.

ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus

然後,我們加入這個項目必須的元件,根據上面的描述,我們需要2個元件: MS Owin的核心實作Microsoft Owin和ASP.NET WebApi 2.2 Owin

我們先加入Microsoft Owin

ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus

然後加入ASP.NET WebApi 2.2 Owin

ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus

第二步: 建立Owin入口代碼

首先,Owin的傳統入口類登場:  Startup.cs

using Owin;
using System.Web.Http;
   public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            #region WebApi
            var httpConfig = new HttpConfiguration();
            httpConfig.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{action}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
            //強制設定目前的WebApi傳回格式為json
            httpConfig.Formatters.Remove(httpConfig.Formatters.XmlFormatter);
            //加載WebApi中間件
            app.UseWebApi(httpConfig);
            #endregion
        }
     }      

幾個要點:

l  Startup中的Configuration寫成類成員方式,而不是靜态方式,是為了和Jexus擴充卡配合,其實差異不大.

l  WebApi的配置寫法和MVC基本類似.

l  Startup和Configuration的命名并不是固定的,隻是預定俗成而已.

第三步: 建立WebApi代碼

建立DefaultController.cs 為一個預設的WebApi,裡面包含一個最簡單的Hello函數.

using System.Web.Http;
    [AllowAnonymous]
    public class DefaultController : ApiController
    {
        [HttpGet]
        public string Hello()
        {
            return "Hello Owin!";
        }
    }      

自此,簡單的MS Owin + WebApi程式架設完畢. 在Owin體系下,我們發現一切都變得非常簡單和清晰.

第四步: 建立Jexus擴充卡代碼

為了把項目部署到Jexus上去,我們還需要一個非常簡單的擴充卡類,在項目中加入這個類以後,就能無縫部署到Jexus伺服器上去了, 我們把這個代碼命名為Adapter.cs:

/**************************************************************************************
 * 加載Microsoft.Owin.dll 進行owin編譯的擴充卡(插件)示例
 * ==================================================================================
 * 目的:
 *   示範如何将自己的處理方法(中間件)加入到 Microsoft.Owin.dll的處理環節中
 * 
 * 使用方法:
 * 将編譯得到的dll連同Owin.dll、Microsoft.Owin.dll等檔案一并放置到網站的bin檔案夾中
 *************************************************************************************/

#region <USINGs>

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Owin.Builder;

#endregion

namespace OwinExample
{
    public class Adapter
    {
        static Func<IDictionary<string, object>, Task> _owinApp;

        /// <summary>
        /// 預設構造函數
        /// </summary>
        public Adapter()
        {
            //建立預設的AppBuilder
            var builder = new AppBuilder();
            
            //建立使用者定義的 Startup類
            //這個類中必須有“Configuration”方法
            var startup = new Startup();

            //調用Configuration方法,把自己的處理函數注冊到處理流程中
            startup.Configuration(builder);

            //生成OWIN“入口”函數
            _owinApp = builder.Build();
        }

        /// <summary>
        /// *** JWS所需要的關鍵函數 ***
        /// <para>每個請求到來,JWS都把請求打包成字典,通過這個函數交給使用者</para>
        /// </summary>
        /// <param name="env">新請求的環境字典,具體内容參見OWIN标準</param>
        /// <returns>傳回一個正在運作或已經完成的任務</returns>
        public Task OwinMain(IDictionary<string, object> env)
        {
            if (_owinApp == null) return null;

            // 将請求交給Microsoft.Owin對這個請求進行處理
            //(你的處理方法已經在本類的構造函數中加入到它的處理序列中了)
            return _owinApp(env);
        }
    }
}      

這裡再次感謝Jexus作者宇内流雲提供的代碼, 出于對原作者的敬意這個代碼除了命名空間以外我一個字母也沒有改,其實也不需要改. 其實大家可以看的出來,這麼變态的注釋應該不是我故意去寫的.

自此我們的基于MS Owin和WebApi的迷你版應用開發完成,改為Release模式編譯,我們可以得到如下圖所示的一系列DLL:

ASP.NET Linux部署(2) - MS Owin + WebApi + Mono + Jexus

就這些DLL就能形成一個WebApi應用嗎?事實就是如此,而且這個應用能很好的部署到Linux環境上去.

第五步: 安裝Jexus環境

這裡先聲明下,基于個人的能力所限,隻能先給出Ubuntu最新版本的一個部署方案,使用其他版本Linux的兄弟隻能麻煩你們自尋門路了.

首先,我們再Ubuntu上面安裝Mono最新版本. 可以參考下面超鍊文章的指引:

http://www.linuxdot.net/bbsfile-3090

然後我們安裝Jexus最新版本. (同樣請參考下面的超鍊)

http://www.linuxdot.net/bbsfile-3500

第六步: 部署到Jexus

部署Jexus網站的正常指導資訊,大家可以移步這裡:

http://www.linuxdot.net/bbsfile-3084

 下面說下我們的特殊部署步驟 (具體Linux指令我就不列舉了):

  1. 建立網站目錄 /var/www/owinexample, 然後在這個目錄下再建立一個bin目錄.
  2. 通過各種方式把上面自己開發産生的dll拷貝網站目錄的bin目錄下.
  3. 建立Jexus網站的配置檔案,假設我們命名為 owinexample

其重要内容應該包括以下設定:

# For owinexample

 port=88

root=/ /var/www/owinexample

hosts=*    # or  your.com,*.your.com

OwinMain=OwinExample.dll,OwinExample.Adapter

特别強調的是OwinMain這個必需配置,并且需要對應正确的DLL檔案名和Apdater類. 根據前面的描述,我們可以知道我們應用的配置應該是OwinExample.dll, OwinExample.Adapter.

另外, Web.Config檔案和其他任何檔案在這種構架裡面不是必須的.

  1. 重新開機 Jexus 服務
  2. 打開你的浏覽器,輸入 http://linuxserverip:88/api/default/hello 就可以看到結果.

注意linuxserverip為部署伺服器的IP, 88為我們再Jexus配置中設定的端口, api/default/hello對應我們WebApi的路徑映射,Controller類名和方法名.

結束語

最後還是說下我們這種模式的優勢,劣勢和意義:

優勢: 基于Owin底層,簡單明了穩定,可以融合任何基于Owin的相關技術,擴充性強,可以和Mono, Jexus完美結合,性能最高.

劣勢: 相當于自行組建構架,搭建工作量大, 由于目前沒有獨立的MVC元件,在MVC開發方面缺乏支援(Nancy的一部分MVC構架比如Razor引擎可以獨立移入,但這個方案有待驗證).

這個方案的最終意義在于,結合目前.NET和Linux方向上最具備穩定性和代表性的MONO, MS Owin和 Jexus, 在ASP.NET vNext最終能完美部署到Linux之前,這是最接近于商業生産環境的方案之一.

 最後拖一句,這個方案的開發環境可以考慮用TinyFox或者MS Owin Self Host來做宿主. 都可以無縫連接配接,代碼不需要修改.

軟體開發,項目管理,開發管理,團隊管理.

CMMI,PMP

繼續閱讀