using System;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using NewLife;
using NewLife.Agent;
using NewLife.Log;
using NewLife.Reflection;
using NewLife.Remoting;
using NewLife.Serialization;
using NewLife.Threading;
using Stardust;
using Upgrade = Stardust.Web.Upgrade;
namespace StarAgent
{
internal class Program
{
private static void Main(String[] args)
{
if ("-upgrade".EqualIgnoreCase(args)) Thread.Sleep(5_000);
var set = StarSetting.Current;
if (set.IsNew)
{
#if DEBUG
set.Server = "http://localhost:6600";
#endif
set.Save();
}
// 处理 -server 参数,建议在-start启动时添加
if (args != null && args.Length > 0)
{
for (var i = 0; i < args.Length; i++)
{
if (args[i].EqualIgnoreCase("-server") && i + 1 < args.Length)
{
var addr = args[i + 1];
set.Server = addr;
set.Save();
XTrace.WriteLine("服务端修改为:{0}", addr);
}
}
}
new MyService
{
StarSetting = set,
AgentSetting = Setting.Current
}.Main(args);
}
}
/// <summary>服务类。名字可以自定义</summary>
internal class MyService : ServiceBase
{
public StarSetting StarSetting { get; set; }
public StarAgent.Setting AgentSetting { get; set; }
public MyService()
{
ServiceName = "StarAgent";
// 注册菜单,在控制台菜单中按 t 可以执行Test函数,主要用于临时处理数据
AddMenu('s', "使用星尘", UseStarServer);
AddMenu('t', "服务器信息", ShowMachineInfo);
AddMenu('w', "测试微服务", UseMicroService);
MachineInfo.RegisterAsync();
//// 定时重启
//var set2 = NewLife.Agent.Setting.Current;
//if (set2.AutoRestart == 0)
//{
// set2.AutoRestart = 24 * 60;
// set2.Save();
//}
}
private ApiServer _server;
private TimerX _timer;
private StarClient _Client;
private StarFactory _factory;
private ServiceManager _Manager;
private String _lastVersion;
public void StartClient()
{
var server = StarSetting.Server;
if (server.IsNullOrEmpty()) return;
WriteLog("初始化服务端地址:{0}", server);
var set = AgentSetting;
var client = new StarClient(server)
{
Code = set.Code,
Secret = set.Secret,
ProductCode = "StarAgent",
Log = XTrace.Log,
Manager = _Manager,
};
// 登录后保存证书
client.OnLogined += (s, e) =>
{
var inf = client.Info;
if (inf != null && !inf.Code.IsNullOrEmpty())
{
set.Code = inf.Code;
set.Secret = inf.Secret;
set.Save();
}
};
// APM埋点。独立应用名
client.Tracer = _factory.Tracer;
_Manager.Attach(client.CommandQueue);
// 使用跟踪
client.UseTrace();
_Client = client;
// 可能需要多次尝试
_timer = new TimerX(TryConnectServer, client, 0, 5_000) { Async = true };
}
public void StartFactory()
{
if (_factory == null)
{
var server = StarSetting.Server;
if (!server.IsNullOrEmpty()) _factory = new StarFactory(server, "StarAgent", null);
}
}
private async Task TryConnectServer(Object state)
{
var client = state as StarClient;
await client.Login();
await CheckUpgrade(client);
_timer.TryDispose();
_timer = new TimerX(CheckUpgrade, null, 600_000, 600_000) { Async = true };
}
/// <summary>服务启动</summary>
/// <remarks>
/// 安装Windows服务后,服务启动会执行一次该方法。
/// 控制台菜单按5进入循环调试也会执行该方法。
/// </remarks>
protected override void StartWork(String reason)
{
var set = AgentSetting;
// 应用服务管理
_Manager = new ServiceManager
{
Services = set.Services,
Log = XTrace.Log,
};
// 监听端口,用于本地通信
if (set.LocalPort > 0)
{
//var uri = new NetUri(set.LocalServer);
try
{
var svr = new ApiServer(set.LocalPort)
{
Log = XTrace.Log
};
svr.Register(new StarService
{
Service = this,
Host = Host,
Manager = _Manager,
Setting = StarSetting,
Log = XTrace.Log
}, null);
_server = svr;
svr.Start();
}
catch (Exception ex)
{
XTrace.WriteException(ex);
}
}
StartFactory();
// 启动星尘客户端,连接服务端
StartClient();
_Manager.Start();
base.StartWork(reason);
}
/// <summary>服务管理线程</summary>
/// <param name="data"></param>
protected override void DoCheck(Object data)
{
// 支持动态更新
_Manager.Services = AgentSetting.Services;
base.DoCheck(data);
}
/// <summary>服务停止</summary>
/// <remarks>
/// 安装Windows服务后,服务停止会执行该方法。
/// 控制台菜单按5进入循环调试,任意键结束时也会执行该方法。
/// </remarks>
protected override void StopWork(String reason)
{
base.StopWork(reason);
_timer.TryDispose();
_timer = null;
_Manager.Stop(reason);
//_Manager.TryDispose();
_Client?.Logout(reason);
//_Client.TryDispose();
_Client = null;
_factory = null;
_server.TryDispose();
_server = null;
}
private async Task CheckUpgrade(Object data)
{
var client = _Client;
// 运行过程中可能改变配置文件的通道
var channel = AgentSetting.Channel;
var ug = new Upgrade { Log = XTrace.Log };
// 去除多余入口文件
ug.Trim("StarAgent");
// 检查更新
var ur = await client.Upgrade(channel);
if (ur != null && ur.Version != _lastVersion)
{
ug.Url = ur.Source;
await ug.Download();
// 检查文件完整性
if (ur.FileHash.IsNullOrEmpty() || ug.CheckFileHash(ur.FileHash))
{
// 执行更新,解压缩覆盖文件
var rs = ug.Update();
if (rs && !ur.Executor.IsNullOrEmpty()) ug.Run(ur.Executor);
_lastVersion = ur.Version;
// 去除多余入口文件
ug.Trim("StarAgent");
// 强制更新时,马上重启
if (rs && ur.Force)
{
// 以服务方式运行时,重启服务,否则采取拉起进程的方式
if (Host is Host host && host.InService)
{
rs = Host.Restart("StarAgent");
}
else
{
// 重新拉起进程
rs = ug.Run("StarAgent", "-run -upgrade");
if (rs) StopWork("Upgrade");
}
if (rs) ug.KillSelf();
}
}
}
}
protected override void ShowMenu()
{
base.ShowMenu();
var set = StarSetting;
if (!set.Server.IsNullOrEmpty()) Console.WriteLine("服务端:{0}", set.Server);
Console.WriteLine();
}
public void UseStarServer()
{
var set = StarSetting;
if (!set.Server.IsNullOrEmpty()) Console.WriteLine("服务端:{0}", set.Server);
Console.WriteLine("请输入新的服务端:");
var addr = Console.ReadLine();
if (addr.IsNullOrEmpty()) addr = "http://star.newlifex.com:6600";
set.Server = addr;
set.Save();
WriteLog("服务端修改为:{0}", addr);
}
public void ShowMachineInfo()
{
XTrace.WriteLine("FullPath:{0}", ".".GetFullPath());
XTrace.WriteLine("BasePath:{0}", ".".GetBasePath());
XTrace.WriteLine("TempPath:{0}", Path.GetTempPath());
var mi = MachineInfo.Current ?? MachineInfo.RegisterAsync().Result;
mi.Refresh();
foreach (var pi in mi.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var val = mi.GetValue(pi);
if (pi.Name.EndsWithIgnoreCase("Memory"))
val = val.ToLong().ToGMK();
else if (pi.Name.EndsWithIgnoreCase("Rate", "Battery"))
val = val.ToDouble().ToString("p2");
XTrace.WriteLine("{0}:\t{1}", pi.Name, val);
}
// 网络信息
XTrace.WriteLine("NetworkAvailable:{0}", NetworkInterface.GetIsNetworkAvailable());
foreach (var item in NetworkInterface.GetAllNetworkInterfaces())
{
//if (item.OperationalStatus != OperationalStatus.Up) continue;
if (item.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
XTrace.WriteLine("{0} {1} {2}", item.NetworkInterfaceType, item.OperationalStatus, item.Name);
XTrace.WriteLine("\tDescription:\t{0}", item.Description);
XTrace.WriteLine("\tMac:\t{0}", item.GetPhysicalAddress().GetAddressBytes().ToHex("-"));
var ipp = item.GetIPProperties();
if (ipp != null && ipp.UnicastAddresses.Any(e => e.Address.IsIPv4()))
{
XTrace.WriteLine("\tIP:\t{0}", ipp.UnicastAddresses.Where(e => e.Address.IsIPv4()).Join(",", e => e.Address));
if (ipp.GatewayAddresses.Any(e => e.Address.IsIPv4()))
XTrace.WriteLine("\tGateway:{0}", ipp.GatewayAddresses.Where(e => e.Address.IsIPv4()).Join(",", e => e.Address));
if (ipp.DnsAddresses.Any(e => e.IsIPv4()))
XTrace.WriteLine("\tDns:\t{0}", ipp.DnsAddresses.Where(e => e.IsIPv4()).Join());
}
}
}
private String _lastService;
public void UseMicroService()
{
if (_lastService.IsNullOrEmpty())
Console.WriteLine("请输入要测试的微服务名称:");
else
Console.WriteLine("请输入要测试的微服务名称({0}):", _lastService);
var serviceName = Console.ReadLine();
if (serviceName.IsNullOrEmpty()) serviceName = _lastService;
if (serviceName.IsNullOrEmpty()) return;
_lastService = serviceName;
StartFactory();
var models = _factory.Service.ResolveAsync(serviceName).Result;
//if (models == null) models = _factory.Dust.ResolveAsync(new ConsumeServiceInfo { ServiceName = serviceName }).Result;
Console.WriteLine(models.ToJson(true));
}
}
}
|