多进程VS多线程
在之前的文章中,已经提到了目前服务器的主流框架是多进程或者多线程的架构(游戏服务器的中心节点)。
多进程服务器可以分布式部署,总体会更加灵活。此外,多进程的情况下,我们可以更加肆无忌惮的使用静态数据;但多线程情况下,静态数据访问要么加锁,要么就只能尽量避免。另外,多进程如果发生异常崩溃等突发情况,不至于整个服务器组玉石俱焚。所以,一般我还是推荐使用多进程的架构。
但是多进程服务器架构,在win下有一些坑点
- 日志会分别打印到不同的控制台和文件中(多个进程写一个文件更慢更坑),查日志需要对比着进行,并不直观。
- 会在任务栏启动多个进程,看了比较心烦,当然可以选择隐藏起来,但同时就没法通过控制台实时看到日志了。
于是,我们想到是不是可以写一个shell进程,隐藏服务器进程ui(任务管理器中仍然可见)的情况下,收集所有日志,达到实时监控的目的。
核心的问题
隐藏界面的方式启动进程,并重定向该进程的标准输出。
通过C#的Process类,加上适当的配置,我们就可以启动一个“看不见”的进程了。接着,调用我们自己实现LogTextManager,并异步读取来自于被启动进程的日志。
public static void StartProcess(string pname, LogShowDevice dev, string parm = "")
{
Process process = new Process();
process.StartInfo.FileName = pname;
if (!string.IsNullOrEmpty(parm))
{
process.StartInfo.Arguments = parm;
}
process.StartInfo.UseShellExecute = false; // 是否使用外壳程序
process.StartInfo.CreateNoWindow = true; //是否在新窗口中启动该进程的值
process.StartInfo.RedirectStandardOutput = true; // 重定向输入流
process.OutputDataReceived += (s, _e) => LogTextManager.AddLog(_e.Data);
process.Start();
process.BeginOutputReadLine();
processList.Add(new ProcessInfoData { Process = process, ProcessId = process.Id, Dev = dev});
}
最后,LogTextManager再根据情况回显数据,我们就可以完成一个简单的进程启动器+日志显示器的功能了
其他必须功能
严重级别删选和进程删选
这很容易想到,我们现在只能看到所有进程日志的合集。但如果调试时,我们可能只想看某个服务器的log,又或者某种严重级别的log。所以,我们需要实现设定功能,可以对这两个条件进行删选。
复制日志内容
这也是Console程序的一个槽点。用过的同学都知道,win窗口程序复制,需要点击左上角->属性->选中,然后选则文本后右键,充满了浓浓的DOS风情。
在我们的shell程序中,我们就可以在选中日志行,右键显示具体文本了。在这里,我们的做法是调用notepad显示选中的多行信息,非常方便。
定制日志颜色
这个定制功能可能不是必须的,但也可以为这个shell的实用性大大增色。此外,通过C#组件PropertyView实现这个功能,该功能的实现也是非常容易的。
高级功能支持
服务器组控制
基本的控制功能,包括启动或者关闭服务器组,并且可以检测服务器运行中,就无法再次开启等等。有点类似于守护进程,甚至当某个进程挂了时,也可以扮演raise up的角色,重启进程,保证服务器组可用。
读取/修改服务器参数
有时,我们会遇到这样的情况,调试期间我们希望可以在运行时修改服务器的一些参数,比如逻辑时间,经验倍率,掉落倍率(重启服务器比较耗时)。通过这个shell程序来做这样的工作就会非常合适。通信的方法一般是socket等,这里就不用详细列举了。
运行状态的可视化
这也是控制台shell化带来的红利,我们可以把各个进程性能的数据(cpu,内存,网络消耗)等等,立即可视化绘制图表。如果需要做性能测试,应该会非常有用。