NewLife.Net——構建可靠的網絡服務


網絡程序應該注冊成為系統服務,以保證其自啟動以及穩定可靠運行!

這一場,講講怎么建立一個生產級別的網絡服務。

老規矩,先上源碼:https://github.com/NewLifeX/NewLife.Net

系統服務功能,由網絡庫的兄弟框架,X組件的Agent來支撐,以前也叫XAgent,網上搜索 NewLife XAgent 可以找到不少文章。

XAgent在X組件里面很年輕,才10年,設計於2008年,上海陸家嘴。

〇、最終效果 

先來看看最終效果,大家也可以telnet net.newlifex.com 1234 來看效果

左邊窗口就是這次要講的網絡服務程序,工作在調試模式。

右邊窗口是上一次的EchoTest客戶端,連接左邊網絡服務。

一、建立控制台項目

建立一個控制台項目,通過nuget引用NewLife.Core

新建一個服務類 MyService,繼承自泛型基類 AgentServiceBase<MyService>

Program.Main里面增加一行引導程序:

class Program
{
    static void Main(String[] args)
    {
        // 引導進入我的服務控制類
        MyService.ServiceMain();
    }
}

 下面就開始慢慢完善我們的服務類MyService

public MyService()
{
    ServiceName = "EchoAgent";
    DisplayName = "回聲服務";
    Description = "這是NewLife.Net的一個回聲服務示例!";

    // 准備兩個工作線程,分別負責輸出日志和向客戶端發送時間
    ThreadCount = 2;
    Intervals = new[] { 1, 5 };
}

指定一些基本參數,看效果圖可以猜到用途

服務名、顯示名、描述,就這么多!

 

ThreadCount = 2指定兩個工作線程,Intervals指定它們的輪詢周期分別是1秒和5秒

 

系統服務的標准動作就是啟動和停止

MyNetServer _Server;
/// <summary>開始服務</summary>
/// <param name="reason"></param>
protected override void StartWork(String reason)
{
    // 實例化服務端,指定端口,同時在Tcp/Udp/IPv4/IPv6上監聽
    var svr = new MyNetServer
    {
        Port = 1234,
        Log = XTrace.Log
    };
    svr.Start();

    _Server = svr;

    base.StartWork(reason);
}

/// <summary>停止服務</summary>
/// <param name="reason"></param>
protected override void StopWork(String reason)
{
    _Server.TryDispose();
    _Server = null;

    base.StopWork(reason);
}

我們重載啟動函數,初始化網絡服務,並重啟停止函數來銷毀網絡服務。

這里的MyNetServer從上一個例程拷貝過來。

網絡服務做一個成員資源,避免被GC回收。

 

XAgent默認帶來多線程任務調度,其核心是 Work(Int32 index)

/// <summary>調度器讓每個任務線程定時執行Work,index標識任務</summary>
/// <param name="index"></param>
/// <returns></returns>
public override Boolean Work(Int32 index)
{
    switch (index)
    {
        case 0: ShowStat(_Server); break;
        case 1: SendTime(_Server); break;
    }
    return false;
}

private String _last;
/// <summary>顯示服務端狀態</summary>
/// <param name="ns"></param>
private void ShowStat(NetServer ns)
{
    var msg = ns.GetStat();
    if (msg == _last) return;

    _last = msg;

    WriteLog(msg);
}

/// <summary>向所有客戶端發送時間</summary>
/// <param name="ns"></param>
private void SendTime(NetServer ns)
{
    var str = DateTime.Now.ToFullString() + Environment.NewLine;
    var buf = str.GetBytes();
    ns.SendAllAsync(buf);
}

XAgent內部設計有一個任務調度器,它會實際創建2個線程(ThreadCount指定),每個線程定時執行Work(Int32 index)函數,index參數用於標識哪一個任務線程。

我們這只需要一個很簡單的switch,0號線程負責輸出服務端狀態,每秒一次,1號線程負責給連接到服務端的所有會話發送服務器當前時間。

 

多說幾句XAgent:

1,任務線程具有較高線程優先級,比一般線程有更多機會得到CPU時間

2,調度器有個最高優先級的管理線程,負責監管所有任務線程,如果任務線程崩潰或者超時,它會干掉並新建

3,管理線程還負責監控線程數、句柄數、內存占用等

 

二、開發調試

 既然是控制台項目,先跑起來看看:

紅色字體顯示重要信息,黃色字體顯示菜單,常用功能是235。

我們選擇5,循環調試,其實就是在控制台里面模擬服務工作流程,讓網絡服務跑起來。

底下日志可以看到,它監聽了4個套接字。

 

2是安裝服務,也就是把當前應用安裝成為Windows服務,這里特別注意,一般需要管理員權限,才能安裝成功,除非關閉系統UAC。

3是啟動服務,只有在安裝了服務之后,才能看到。

 

所以,XAgent程序,既是開發調試控制台程序,也是安裝卸載、啟動停止服務的操作台,更是Windows服務程序本身!

細心的同學可以發現,安裝好的Windows服務實質上就是 EchoAgent.exe -s,帶有-s參數。

 

三、安裝服務

 最后,我們把它安裝到一台公網服務器上,tcp://net.newlifex.com:1234,telnet上去看看效果

從日志文件可以看到,它的應用類型 ApplicationType 是 Service,也就是Windows Service。

下面的日志,在A0線程(也就是0號任務線程)輸出服務端狀態。

在線1/1,當前在線/最大在線

發送 2/20/0,共發送2次,最大速度每秒20字節,當前速度每秒0字節

 

既然有A0線程,同樣也會有A1,還會有An(ThreadCount>n),可用於區分不同任務線程輸出的日志。

 

至此,我們的Windows網絡服務程序開發完成,並安裝到公網服務器上,持續對外提供Echo服務!


免責聲明!

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



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