判断目标端口是否已使用,作为是否探测星尘代理的依据,加速应用启动。通过进程名判断是否存在,可能会误判,因为获取其它dotnet进程命令行需要管理员权限

This commit is contained in:
大石头 2023-06-10 11:58:09 +08:00
parent 79e401e7c5
commit 9830338c27
6 changed files with 189 additions and 220 deletions

View File

@ -1,27 +1,50 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Diagnostics;
using NewLife.Log;
using NewLife.Serialization;
using Stardust.Models;
using Xunit;
namespace ClientTest
{
public class AppInfoTests
{
[Fact]
public void Test()
{
//var p = Process.GetCurrentProcess();
namespace ClientTest;
foreach (var item in Process.GetProcesses())
{
//Console.WriteLine(item);
var pi = new AppInfo(item);
if (pi.ProcessorTime > 0) XTrace.WriteLine(pi.ToJson());
}
public class AppInfoTests
{
[Fact]
public void Test()
{
foreach (var p in Process.GetProcesses())
{
//Console.WriteLine(p);
var pi = new AppInfo(p);
if (pi.ProcessorTime > 0) XTrace.WriteLine(pi.ToJson());
}
}
[Fact]
public void GetProcessName()
{
var p = Process.GetCurrentProcess();
var name = AppInfo.GetProcessName(p);
Assert.Equal("testhost", name);
}
//[Fact]
//public void GetStarAgentName()
//{
// var flag = false;
// foreach (var p in Process.GetProcesses())
// {
// if (p.ProcessName == "dotnet")
// {
// var name = AppInfo.GetProcessName(p);
// if (name == "StarAgent")
// {
// flag = true;
// break;
// }
// }
// }
// Assert.True(flag);
//}
}

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using NewLife;
using NewLife.Configuration;
using NewLife.Http;
@ -16,106 +12,105 @@ using Stardust.Monitors;
using Stardust.Registry;
using Xunit;
namespace ClientTest
namespace ClientTest;
public class StarFactoryTests
{
public class StarFactoryTests
[Fact]
public void Normal()
{
[Fact]
public void Normal()
{
var set = StarSetting.Current;
var secret = Rand.NextString(8, true);
set.Secret = secret;
var set = StarSetting.Current;
var secret = Rand.NextString(8, true);
set.Secret = secret;
using var star = new StarFactory(null, "StarWeb", null);
using var star = new StarFactory(null, "StarWeb", null);
Assert.NotNull(star.Local);
Assert.Equal("http://star.newlifex.com:6600", star.Server);
Assert.Equal("StarWeb", star.AppId);
Assert.Equal(secret, star.Secret);
Assert.NotNull(star.Local);
Assert.Equal("http://127.0.0.1:6600", star.Server);
Assert.Equal("StarWeb", star.AppId);
Assert.Equal(secret, star.Secret);
var inf = star.Local.Info;
Assert.NotNull(inf);
var inf = star.Local.Info;
Assert.NotNull(inf);
var tracer = star.Tracer as StarTracer;
Assert.NotNull(tracer);
Assert.NotEmpty(tracer.ClientId);
var tracer = star.Tracer as StarTracer;
Assert.NotNull(tracer);
Assert.NotEmpty(tracer.ClientId);
var config = star.Config as HttpConfigProvider;
Assert.NotNull(config);
Assert.Equal("NewLife开发团队", config["Title"]);
var config = star.Config as HttpConfigProvider;
Assert.NotNull(config);
Assert.Equal("NewLife开发团队", config["Title"]);
var dust = star.Service as AppClient;
Assert.NotNull(dust);
var dust = star.Service as AppClient;
Assert.NotNull(dust);
var filter = star.GetValue("_tokenFilter") as TokenHttpFilter;
Assert.NotNull(filter);
Assert.Equal(star.AppId, filter.UserName);
Assert.Equal(star.Secret, filter.Password);
Assert.Equal(filter, (tracer.Client as ApiHttpClient).Filter);
Assert.Equal(filter, (config.Client as ApiHttpClient).Filter);
Assert.Equal(filter, (dust as ApiHttpClient).Filter);
}
var filter = star.GetValue("_tokenFilter") as TokenHttpFilter;
Assert.NotNull(filter);
Assert.Equal(star.AppId, filter.UserName);
Assert.Equal(star.Secret, filter.Password);
Assert.Equal(filter, (tracer.Client as ApiHttpClient).Filter);
Assert.Equal(filter, (config.Client as ApiHttpClient).Filter);
Assert.Equal(filter, (dust as ApiHttpClient).Filter);
}
[Fact]
public async void CreateForService()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", "xxx");
await star.Service.RegisterAsync("testService", "http://localhost:1234", "tA,tagB,ttC");
[Fact]
public async void CreateForService()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", "xxx");
await star.Service.RegisterAsync("testService", "http://localhost:1234", "tA,tagB,ttC");
var client = star.CreateForService("testService", "tagB") as ApiHttpClient;
Assert.NotNull(client);
Assert.True(client.RoundRobin);
Assert.Equal("http://localhost:1234/", client.Services.Join(",", e => e.Address));
}
var client = star.CreateForService("testService", "tagB") as ApiHttpClient;
Assert.NotNull(client);
Assert.True(client.RoundRobin);
Assert.Equal("http://localhost:1234/", client.Services.Join(",", e => e.Address));
}
[Fact]
public async void CreateForService2()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", "xxx");
[Fact]
public async void CreateForService2()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", "xxx");
var client = star.CreateForService("StarWeb", "tagB") as ApiHttpClient;
Assert.NotNull(client);
Assert.True(client.RoundRobin);
Assert.Equal(0, client.Services.Count);
var client = star.CreateForService("StarWeb", "tagB") as ApiHttpClient;
Assert.NotNull(client);
Assert.True(client.RoundRobin);
Assert.Equal(0, client.Services.Count);
var client2 = star.CreateForService("StarWeb", "Development") as ApiHttpClient;
Assert.NotNull(client2);
Assert.True(client2.RoundRobin);
Assert.Equal("https://localhost:5001/,http://localhost:5000/", client2.Services.Join(",", e => e.Address));
}
var client2 = star.CreateForService("StarWeb", "Development") as ApiHttpClient;
Assert.NotNull(client2);
Assert.True(client2.RoundRobin);
Assert.Equal("https://localhost:5001/,http://localhost:5000/", client2.Services.Join(",", e => e.Address));
}
[Fact]
public void IocTest()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", null);
[Fact]
public void IocTest()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", null);
var provider = ObjectContainer.Provider;
var provider = ObjectContainer.Provider;
var factory = provider.GetRequiredService<StarFactory>();
Assert.NotNull(factory);
Assert.Equal(star, factory);
var factory = provider.GetRequiredService<StarFactory>();
Assert.NotNull(factory);
Assert.Equal(star, factory);
var tracer = provider.GetRequiredService<ITracer>();
Assert.NotNull(tracer);
Assert.Equal(star.Tracer, tracer);
var tracer = provider.GetRequiredService<ITracer>();
Assert.NotNull(tracer);
Assert.Equal(star.Tracer, tracer);
var config = provider.GetRequiredService<IConfigProvider>();
Assert.NotNull(config);
Assert.Equal(star.Config, config);
var config = provider.GetRequiredService<IConfigProvider>();
Assert.NotNull(config);
Assert.Equal(star.Config, config);
var service = provider.GetRequiredService<IRegistry>();
Assert.NotNull(service);
Assert.Equal(star.Service, service);
}
var service = provider.GetRequiredService<IRegistry>();
Assert.NotNull(service);
Assert.Equal(star.Service, service);
}
[Fact]
public async void SendNodeCommand()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", "xxx");
[Fact]
public async void SendNodeCommand()
{
using var star = new StarFactory("http://127.0.0.1:6600", "test", "xxx");
var rs = await star.SendNodeCommand("7F0F011A", "hello", "stone", 33);
Assert.True(rs > 0);
}
var rs = await star.SendNodeCommand("7F0F011A", "hello", "stone", 33);
Assert.True(rs > 0);
}
}

View File

@ -1,11 +1,13 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using NewLife;
using NewLife.Http;
using NewLife.Log;
using NewLife.Messaging;
using NewLife.Net;
using NewLife.Remoting;
using Stardust.Models;
#if NET45_OR_GREATER || NETCOREAPP || NETSTANDARD
@ -24,6 +26,9 @@ public class LocalStarClient
/// <summary>本地服务端地址</summary>
public String Server { get; set; }
/// <summary>本地星尘代理服务地址</summary>
public static Int32 Port { get; set; } = 5500;
private AgentInfo _local;
private ApiClient _client;
#endregion
@ -42,7 +47,7 @@ public class LocalStarClient
{
if (_client != null) return;
_client = new ApiClient("udp://127.0.0.1:5500")
_client = new ApiClient($"udp://127.0.0.1:{Port}")
{
Timeout = 3_000,
Log = Log,
@ -59,14 +64,28 @@ public class LocalStarClient
/// <returns></returns>
public AgentInfo GetInfo()
{
// 检测进程是否存在,如果进程都不存在,没必要获取信息
if (!Process.GetProcessesByName("StarAgent").Any())
{
var pis = Process.GetProcessesByName("dotnet");
if (pis.Length == 0) return null;
//!!! 通过进程名判断是否存在可能会误判因为获取其它dotnet进程命令行需要管理员权限
//// 检测进程是否存在,如果进程都不存在,没必要获取信息
//if (!Process.GetProcessesByName("StarAgent").Any())
//{
// var pis = Process.GetProcessesByName("dotnet");
// if (pis.Length == 0) return null;
if (!pis.Any(p => AppInfo.GetProcessName(p).EqualIgnoreCase("StarAgent"))) return null;
// if (!pis.Any(p => AppInfo.GetProcessName(p).EqualIgnoreCase("StarAgent"))) return null;
//}
// 判断目标端口是否已使用,作为是否探测星尘代理的依据,加速应用启动
//if (!IPAddress.Any.CheckPort(NetType.Udp, 5500) &&
// !IPAddress.Loopback.CheckPort(NetType.Udp, 5500) &&
// !IPAddress.IPv6Loopback.CheckPort(NetType.Udp, 5500)) return null;
try
{
// 某些情况下检查端口占用会抛出异常,原因未知
var gp = IPGlobalProperties.GetIPGlobalProperties();
var eps = gp.GetActiveUdpListeners();
if (!eps.Any(ep => ep.Port == Port)) return null;
}
catch { }
var task = TaskEx.Run(GetInfoAsync);
return task.Wait(500) ? task.Result : null;
@ -418,9 +437,9 @@ public class LocalStarClient
var buf = encoder.CreateRequest("Info", null).ToPacket().ToArray();
// 广播消息
// 在局域网中广播消息
var udp = new UdpClient();
udp.Send(buf, buf.Length, new IPEndPoint(IPAddress.Broadcast, 5500));
udp.Send(buf, buf.Length, new IPEndPoint(IPAddress.Broadcast, Port));
var end = DateTime.Now.AddSeconds(timeout);
while (DateTime.Now < end)

View File

@ -214,17 +214,12 @@ public class AppInfo
{
try
{
var dic = ReadWmic("process", "processId=" + process.Id, "commandline");
if (dic.TryGetValue("commandline", out var str))
var dic = MachineInfo.ReadWmic("process where processId=" + process.Id, "commandline");
if (dic.TryGetValue("commandline", out var str) && !str.IsNullOrEmpty())
{
var p = str.IndexOf('\"');
if (p >= 0)
{
var p2 = str.IndexOf('\"', p + 1);
if (p2 > 0) str = str.Substring(p2 + 1);
}
var ss = str.Split(' ');
if (ss.Length >= 2) name = Path.GetFileNameWithoutExtension(ss[1]);
var ss = str.Split(' ').Select(e => e.Trim('\"')).ToArray();
str = ss.FirstOrDefault(e => e.EndsWithIgnoreCase(".dll"));
if (!str.IsNullOrEmpty()) name = Path.GetFileNameWithoutExtension(str);
}
}
catch { }
@ -234,67 +229,5 @@ public class AppInfo
return name;
}
/// <summary>通过WMIC命令读取信息</summary>
/// <param name="type"></param>
/// <param name="where"></param>
/// <param name="keys"></param>
/// <returns></returns>
public static IDictionary<String, String> ReadWmic(String type, String where, params String[] keys)
{
var dic = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
var args = $"{type} where {where} get {keys.Join(",")} /format:list";
var str = Execute("wmic", args)?.Trim();
if (str.IsNullOrEmpty()) return dic;
var ss = str.Split(Environment.NewLine);
foreach (var item in ss)
{
var ks = item.Split("=");
if (ks != null && ks.Length >= 2)
{
var k = ks[0].Trim();
var v = ks[1].Trim();
if (dic.TryGetValue(k, out var val))
dic[k] = val + "," + v;
else
dic[k] = v;
}
}
// 排序,避免多个磁盘序列号时,顺序变动
foreach (var item in dic)
{
if (item.Value.Contains(','))
dic[item.Key] = item.Value.Split(',').OrderBy(e => e).Join();
}
return dic;
}
private static String Execute(String cmd, String arguments = null)
{
try
{
var psi = new ProcessStartInfo(cmd, arguments)
{
// UseShellExecute 必须 false以便于后续重定向输出流
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
RedirectStandardOutput = true,
};
var process = Process.Start(psi);
if (!process.WaitForExit(3_000))
{
process.Kill();
return null;
}
return process.StandardOutput.ReadToEnd();
}
catch { return null; }
}
#endregion
}

View File

@ -165,6 +165,7 @@ public class StarFactory : DisposeBase
if (AppId != "StarAgent")
{
// 借助本地StarAgent获取服务器地址
var sw = Stopwatch.StartNew();
try
{
//XTrace.WriteLine("正在探测本机星尘代理……");
@ -173,7 +174,7 @@ public class StarFactory : DisposeBase
if (!server.IsNullOrEmpty())
{
if (Server.IsNullOrEmpty()) Server = server;
XTrace.WriteLine("星尘探测:{0}", server);
XTrace.WriteLine("星尘探测:{0} Cost={1}ms", server, sw.ElapsedMilliseconds);
if (set.Server.IsNullOrEmpty())
{
@ -182,11 +183,11 @@ public class StarFactory : DisposeBase
}
}
else
XTrace.WriteLine("星尘探测StarAgent Not Found");
XTrace.WriteLine("星尘探测StarAgent Not Found, Cost={0}ms", sw.ElapsedMilliseconds);
}
catch (Exception ex)
{
XTrace.Log.Error("星尘探测失败!{0}", ex.Message);
XTrace.Log.Error("星尘探测失败!{0} Cost={1}ms", ex.Message, sw.ElapsedMilliseconds);
}
}

View File

@ -1,45 +1,43 @@
using System;
using System.ComponentModel;
using System.ComponentModel;
using NewLife.Configuration;
namespace Stardust
namespace Stardust;
/// <summary>星尘客户端配置</summary>
[Config("Star")]
public class StarSetting : Config<StarSetting>
{
/// <summary>星尘客户端配置</summary>
[Config("Star")]
public class StarSetting : Config<StarSetting>
{
#region
/// <summary>调试开关。默认false</summary>
[Description("调试开关。默认false")]
public Boolean Debug { get; set; }
#region
/// <summary>调试开关。默认false</summary>
[Description("调试开关。默认false")]
public Boolean Debug { get; set; }
/// <summary>服务端地址。如http://star.newlifex.com:6600默认为空</summary>
[Description("服务端地址。如http://star.newlifex.com:6600默认为空")]
public String Server { get; set; } = "";
/// <summary>服务端地址。如http://star.newlifex.com:6600默认为空</summary>
[Description("服务端地址。如http://star.newlifex.com:6600默认为空")]
public String Server { get; set; } = "";
/// <summary>应用标识</summary>
[Description("应用标识")]
public String AppKey { get; set; }
/// <summary>应用标识</summary>
[Description("应用标识")]
public String AppKey { get; set; }
/// <summary>应用密钥</summary>
[Description("应用密钥")]
public String Secret { get; set; }
/// <summary>应用密钥</summary>
[Description("应用密钥")]
public String Secret { get; set; }
/// <summary>服务地址。人工设定,用于提交注册中心,默认为空,自动识别外部访问地址</summary>
[Description("服务地址。人工设定,用于提交注册中心,默认为空,自动识别外部访问地址")]
public String ServiceAddress { get; set; }
/// <summary>服务地址。人工设定,用于提交注册中心,默认为空,自动识别外部访问地址</summary>
[Description("服务地址。人工设定,用于提交注册中心,默认为空,自动识别外部访问地址")]
public String ServiceAddress { get; set; }
/// <summary>跟踪采样周期。默认60s</summary>
[Description("跟踪采样周期。默认60s")]
public Int32 TracerPeriod { get; set; } = 60;
/// <summary>跟踪采样周期。默认60s</summary>
[Description("跟踪采样周期。默认60s")]
public Int32 TracerPeriod { get; set; } = 60;
/// <summary>最大正常采样数。采样周期内最多只记录指定数量的正常事件用于绘制依赖关系默认1</summary>
[Description("最大正常采样数。采样周期内最多只记录指定数量的正常事件用于绘制依赖关系默认1")]
public Int32 MaxSamples { get; set; } = 1;
/// <summary>最大正常采样数。采样周期内最多只记录指定数量的正常事件用于绘制依赖关系默认1</summary>
[Description("最大正常采样数。采样周期内最多只记录指定数量的正常事件用于绘制依赖关系默认1")]
public Int32 MaxSamples { get; set; } = 1;
/// <summary>最大异常采样数。采样周期内最多只记录指定数量的异常事件默认10</summary>
[Description("最大异常采样数。采样周期内最多只记录指定数量的异常事件默认10")]
public Int32 MaxErrors { get; set; } = 10;
#endregion
}
/// <summary>最大异常采样数。采样周期内最多只记录指定数量的异常事件默认10</summary>
[Description("最大异常采样数。采样周期内最多只记录指定数量的异常事件默认10")]
public Int32 MaxErrors { get; set; } = 10;
#endregion
}