NewLife.Net——構(gòu)建可靠的網(wǎng)絡(luò)服務(wù)
網(wǎng)絡(luò)程序應(yīng)該注冊(cè)成為系統(tǒng)服務(wù),以保證其自啟動(dòng)以及穩(wěn)定可靠運(yùn)行!
這一場(chǎng),講講怎么建立一個(gè)生產(chǎn)級(jí)別的網(wǎng)絡(luò)服務(wù)。
老規(guī)矩,先上源碼:https://github.com/NewLifeX/NewLife.Net
系統(tǒng)服務(wù)功能,由網(wǎng)絡(luò)庫(kù)的兄弟框架,X組件的Agent來(lái)支撐,以前也叫XAgent,網(wǎng)上搜索 NewLife XAgent 可以找到不少文章。
XAgent在X組件里面很年輕,才10年,設(shè)計(jì)于2008年,上海陸家嘴。
〇、最終效果
先來(lái)看看最終效果,大家也可以telnet net.newlifex.com 1234 來(lái)看效果

左邊窗口就是這次要講的網(wǎng)絡(luò)服務(wù)程序,工作在調(diào)試模式。
右邊窗口是上一次的EchoTest客戶端,連接左邊網(wǎng)絡(luò)服務(wù)。
一、建立控制臺(tái)項(xiàng)目
建立一個(gè)控制臺(tái)項(xiàng)目,通過(guò)nuget引用NewLife.Core
新建一個(gè)服務(wù)類 MyService,繼承自泛型基類 AgentServiceBase<MyService>
Program.Main里面增加一行引導(dǎo)程序:
class Program { static void Main(String[] args) { // 引導(dǎo)進(jìn)入我的服務(wù)控制類 MyService.ServiceMain(); } }
下面就開(kāi)始慢慢完善我們的服務(wù)類MyService
public MyService() { ServiceName = "EchoAgent"; DisplayName = "回聲服務(wù)"; Description = "這是NewLife.Net的一個(gè)回聲服務(wù)示例!"; // 準(zhǔn)備兩個(gè)工作線程,分別負(fù)責(zé)輸出日志和向客戶端發(fā)送時(shí)間 ThreadCount = 2; Intervals = new[] { 1, 5 }; }
指定一些基本參數(shù),看效果圖可以猜到用途

服務(wù)名、顯示名、描述,就這么多!
ThreadCount = 2指定兩個(gè)工作線程,Intervals指定它們的輪詢周期分別是1秒和5秒
系統(tǒng)服務(wù)的標(biāo)準(zhǔn)動(dòng)作就是啟動(dòng)和停止
MyNetServer _Server; /// <summary>開(kāi)始服務(wù)</summary> /// <param name="reason"></param> protected override void StartWork(String reason) { // 實(shí)例化服務(wù)端,指定端口,同時(shí)在Tcp/Udp/IPv4/IPv6上監(jiān)聽(tīng) var svr = new MyNetServer { Port = 1234, Log = XTrace.Log }; svr.Start(); _Server = svr; base.StartWork(reason); } /// <summary>停止服務(wù)</summary> /// <param name="reason"></param> protected override void StopWork(String reason) { _Server.TryDispose(); _Server = null; base.StopWork(reason); }
我們重載啟動(dòng)函數(shù),初始化網(wǎng)絡(luò)服務(wù),并重啟停止函數(shù)來(lái)銷毀網(wǎng)絡(luò)服務(wù)。
這里的MyNetServer從上一個(gè)例程拷貝過(guò)來(lái)。
網(wǎng)絡(luò)服務(wù)做一個(gè)成員資源,避免被GC回收。
XAgent默認(rèn)帶來(lái)多線程任務(wù)調(diào)度,其核心是 Work(Int32 index)
/// <summary>調(diào)度器讓每個(gè)任務(wù)線程定時(shí)執(zhí)行Work,index標(biāo)識(shí)任務(wù)</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>顯示服務(wù)端狀態(tài)</summary> /// <param name="ns"></param> private void ShowStat(NetServer ns) { var msg = ns.GetStat(); if (msg == _last) return; _last = msg; WriteLog(msg); } /// <summary>向所有客戶端發(fā)送時(shí)間</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內(nèi)部設(shè)計(jì)有一個(gè)任務(wù)調(diào)度器,它會(huì)實(shí)際創(chuàng)建2個(gè)線程(ThreadCount指定),每個(gè)線程定時(shí)執(zhí)行Work(Int32 index)函數(shù),index參數(shù)用于標(biāo)識(shí)哪一個(gè)任務(wù)線程。
我們這只需要一個(gè)很簡(jiǎn)單的switch,0號(hào)線程負(fù)責(zé)輸出服務(wù)端狀態(tài),每秒一次,1號(hào)線程負(fù)責(zé)給連接到服務(wù)端的所有會(huì)話發(fā)送服務(wù)器當(dāng)前時(shí)間。
多說(shuō)幾句XAgent:
1,任務(wù)線程具有較高線程優(yōu)先級(jí),比一般線程有更多機(jī)會(huì)得到CPU時(shí)間
2,調(diào)度器有個(gè)最高優(yōu)先級(jí)的管理線程,負(fù)責(zé)監(jiān)管所有任務(wù)線程,如果任務(wù)線程崩潰或者超時(shí),它會(huì)干掉并新建
3,管理線程還負(fù)責(zé)監(jiān)控線程數(shù)、句柄數(shù)、內(nèi)存占用等
二、開(kāi)發(fā)調(diào)試
既然是控制臺(tái)項(xiàng)目,先跑起來(lái)看看:

紅色字體顯示重要信息,黃色字體顯示菜單,常用功能是235。
我們選擇5,循環(huán)調(diào)試,其實(shí)就是在控制臺(tái)里面模擬服務(wù)工作流程,讓網(wǎng)絡(luò)服務(wù)跑起來(lái)。
底下日志可以看到,它監(jiān)聽(tīng)了4個(gè)套接字。
2是安裝服務(wù),也就是把當(dāng)前應(yīng)用安裝成為Windows服務(wù),這里特別注意,一般需要管理員權(quán)限,才能安裝成功,除非關(guān)閉系統(tǒng)UAC。
3是啟動(dòng)服務(wù),只有在安裝了服務(wù)之后,才能看到。
所以,XAgent程序,既是開(kāi)發(fā)調(diào)試控制臺(tái)程序,也是安裝卸載、啟動(dòng)停止服務(wù)的操作臺(tái),更是Windows服務(wù)程序本身!
細(xì)心的同學(xué)可以發(fā)現(xiàn),安裝好的Windows服務(wù)實(shí)質(zhì)上就是 EchoAgent.exe -s,帶有-s參數(shù)。
三、安裝服務(wù)
最后,我們把它安裝到一臺(tái)公網(wǎng)服務(wù)器上,tcp://net.newlifex.com:1234,telnet上去看看效果


從日志文件可以看到,它的應(yīng)用類型 ApplicationType 是 Service,也就是Windows Service。
下面的日志,在A0線程(也就是0號(hào)任務(wù)線程)輸出服務(wù)端狀態(tài)。
在線1/1,當(dāng)前在線/最大在線
發(fā)送 2/20/0,共發(fā)送2次,最大速度每秒20字節(jié),當(dāng)前速度每秒0字節(jié)
既然有A0線程,同樣也會(huì)有A1,還會(huì)有An(ThreadCount>n),可用于區(qū)分不同任務(wù)線程輸出的日志。
至此,我們的Windows網(wǎng)絡(luò)服務(wù)程序開(kāi)發(fā)完成,并安裝到公網(wǎng)服務(wù)器上,持續(xù)對(duì)外提供Echo服務(wù)!

浙公網(wǎng)安備 33010602011771號(hào)