前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NewLife.Net——构建可靠的网络服务

NewLife.Net——构建可靠的网络服务

作者头像
大石头
发布2018-07-31 14:25:10
4640
发布2018-07-31 14:25:10
举报
文章被收录于专栏:智能大石头

网络程序应该注册成为系统服务,以保证其自启动以及稳定可靠运行!

这一场,讲讲怎么建立一个生产级别的网络服务。

老规矩,先上源码:https://github.com/nnhy/NewLife.Net.Tests

系统服务功能,由网络库的兄弟框架,X组件的Agent来支撑,以前也叫XAgent,网上搜索 NewLife XAgent 可以找到不少文章。

XAgent在X组件里面很年轻,才10年,设计于2008年,上海陆家嘴。

〇、最终效果 

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

左边窗口就是这次要讲的网络服务程序,工作在调试模式。

右边窗口是上一次的EchoTest客户端,连接左边网络服务。

一、建立控制台项目

建立一个控制台项目,通过nuget引用NewLife.Core

新建一个服务类 MyService,继承自泛型基类 AgentServiceBase<MyService>

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

代码语言:javascript
复制
class Program
{
    static void Main(String[] args)
    {
        // 引导进入我的服务控制类
        MyService.ServiceMain();
    }
}

 下面就开始慢慢完善我们的服务类MyService

代码语言:javascript
复制
public MyService()
{
    ServiceName = "EchoAgent";
    DisplayName = "回声服务";
    Description = "这是NewLife.Net的一个回声服务示例!";

    // 准备两个工作线程,分别负责输出日志和向客户端发送时间
    ThreadCount = 2;
    Intervals = new[] { 1, 5 };
}

指定一些基本参数,看效果图可以猜到用途

服务名、显示名、描述,就这么多!

ThreadCount = 2指定两个工作线程,Intervals指定它们的轮询周期分别是1秒和5秒

系统服务的标准动作就是启动和停止

代码语言:javascript
复制
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)

代码语言:javascript
复制
/// <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服务!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-05-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 〇、最终效果 
  • 一、建立控制台项目
  • 二、开发调试
  • 三、安装服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档