diff --git a/Stardust.Data/Entity/应用在线.Biz.cs b/Stardust.Data/Entity/应用在线.Biz.cs index 33e435aa..4411c987 100644 --- a/Stardust.Data/Entity/应用在线.Biz.cs +++ b/Stardust.Data/Entity/应用在线.Biz.cs @@ -138,18 +138,6 @@ namespace Stardust.Data return Find(_.Session == session); } - - /// 根据应用、实例查找 - /// 应用 - /// 实例 - /// 实体对象 - public static AppOnline FindByAppIDAndInstance(Int32 appid, String instance) - { - // 实体缓存 - if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.AppID == appid && e.Instance == instance); - - return Find(_.AppID == appid & _.Instance == instance); - } #endregion #region 高级查询 diff --git a/Stardust.Data/Entity/应用在线.cs b/Stardust.Data/Entity/应用在线.cs index 8606b793..879ad046 100644 --- a/Stardust.Data/Entity/应用在线.cs +++ b/Stardust.Data/Entity/应用在线.cs @@ -12,7 +12,8 @@ namespace Stardust.Data [DataObject] [Description("应用在线。一个应用有多个部署,每个在线会话对应一个服务地址")] [BindIndex("IU_AppOnline_Session", true, "Session")] - [BindIndex("IU_AppOnline_AppID_Instance", true, "AppID,Instance")] + [BindIndex("IX_AppOnline_Client", false, "Client")] + [BindIndex("IX_AppOnline_AppID", false, "AppID")] [BindTable("AppOnline", Description = "应用在线。一个应用有多个部署,每个在线会话对应一个服务地址", ConnName = "Registry", DbType = DatabaseType.None)] public partial class AppOnline : IAppOnline { @@ -33,22 +34,54 @@ namespace Stardust.Data [BindColumn("AppID", "应用", "")] public Int32 AppID { get { return _AppID; } set { if (OnPropertyChanging(__.AppID, value)) { _AppID = value; OnPropertyChanged(__.AppID); } } } - private String _Instance; - /// 实例。IP@进程 - [DisplayName("实例")] - [Description("实例。IP@进程")] - [DataObjectField(false, false, true, 50)] - [BindColumn("Instance", "实例。IP@进程", "")] - public String Instance { get { return _Instance; } set { if (OnPropertyChanging(__.Instance, value)) { _Instance = value; OnPropertyChanged(__.Instance); } } } - private String _Session; - /// 会话。tcp://ip:port - [DisplayName("会话")] - [Description("会话。tcp://ip:port")] + /// 实例。IP加端口 + [DisplayName("实例")] + [Description("实例。IP加端口")] [DataObjectField(false, false, true, 50)] - [BindColumn("Session", "会话。tcp://ip:port", "")] + [BindColumn("Session", "实例。IP加端口", "")] public String Session { get { return _Session; } set { if (OnPropertyChanging(__.Session, value)) { _Session = value; OnPropertyChanged(__.Session); } } } + private String _Client; + /// 客户端。IP加进程 + [DisplayName("客户端")] + [Description("客户端。IP加进程")] + [DataObjectField(false, false, true, 50)] + [BindColumn("Client", "客户端。IP加进程", "")] + public String Client { get { return _Client; } set { if (OnPropertyChanging(__.Client, value)) { _Client = value; OnPropertyChanged(__.Client); } } } + + private String _Name; + /// 名称。机器名称 + [DisplayName("名称")] + [Description("名称。机器名称")] + [DataObjectField(false, false, true, 50)] + [BindColumn("Name", "名称。机器名称", "", Master = true)] + public String Name { get { return _Name; } set { if (OnPropertyChanging(__.Name, value)) { _Name = value; OnPropertyChanged(__.Name); } } } + + private String _Version; + /// 版本。客户端 + [DisplayName("版本")] + [Description("版本。客户端")] + [DataObjectField(false, false, true, 50)] + [BindColumn("Version", "版本。客户端", "")] + public String Version { get { return _Version; } set { if (OnPropertyChanging(__.Version, value)) { _Version = value; OnPropertyChanged(__.Version); } } } + + private DateTime _Compile; + /// 编译时间。客户端 + [DisplayName("编译时间")] + [Description("编译时间。客户端")] + [DataObjectField(false, false, true, 0)] + [BindColumn("Compile", "编译时间。客户端", "")] + public DateTime Compile { get { return _Compile; } set { if (OnPropertyChanging(__.Compile, value)) { _Compile = value; OnPropertyChanged(__.Compile); } } } + + private String _Server; + /// 服务端。客户端登录到哪个服务端,IP加端口 + [DisplayName("服务端")] + [Description("服务端。客户端登录到哪个服务端,IP加端口")] + [DataObjectField(false, false, true, 50)] + [BindColumn("Server", "服务端。客户端登录到哪个服务端,IP加端口", "")] + public String Server { get { return _Server; } set { if (OnPropertyChanging(__.Server, value)) { _Server = value; OnPropertyChanged(__.Server); } } } + private String _Address; /// 服务地址。tcp://ip:port [DisplayName("服务地址")] @@ -57,14 +90,6 @@ namespace Stardust.Data [BindColumn("Address", "服务地址。tcp://ip:port", "")] public String Address { get { return _Address; } set { if (OnPropertyChanging(__.Address, value)) { _Address = value; OnPropertyChanged(__.Address); } } } - private String _Version; - /// 版本 - [DisplayName("版本")] - [Description("版本")] - [DataObjectField(false, false, true, 50)] - [BindColumn("Version", "版本", "")] - public String Version { get { return _Version; } set { if (OnPropertyChanging(__.Version, value)) { _Version = value; OnPropertyChanged(__.Version); } } } - private Int32 _Services; /// 服务数。该应用提供的服务数 [DisplayName("服务数")] @@ -126,10 +151,13 @@ namespace Stardust.Data { case __.ID : return _ID; case __.AppID : return _AppID; - case __.Instance : return _Instance; case __.Session : return _Session; - case __.Address : return _Address; + case __.Client : return _Client; + case __.Name : return _Name; case __.Version : return _Version; + case __.Compile : return _Compile; + case __.Server : return _Server; + case __.Address : return _Address; case __.Services : return _Services; case __.Actions : return _Actions; case __.Clients : return _Clients; @@ -145,10 +173,13 @@ namespace Stardust.Data { case __.ID : _ID = Convert.ToInt32(value); break; case __.AppID : _AppID = Convert.ToInt32(value); break; - case __.Instance : _Instance = Convert.ToString(value); break; case __.Session : _Session = Convert.ToString(value); break; - case __.Address : _Address = Convert.ToString(value); break; + case __.Client : _Client = Convert.ToString(value); break; + case __.Name : _Name = Convert.ToString(value); break; case __.Version : _Version = Convert.ToString(value); break; + case __.Compile : _Compile = Convert.ToDateTime(value); break; + case __.Server : _Server = Convert.ToString(value); break; + case __.Address : _Address = Convert.ToString(value); break; case __.Services : _Services = Convert.ToInt32(value); break; case __.Actions : _Actions = Convert.ToString(value); break; case __.Clients : _Clients = Convert.ToInt32(value); break; @@ -171,18 +202,27 @@ namespace Stardust.Data /// 应用 public static readonly Field AppID = FindByName(__.AppID); - /// 实例。IP@进程 - public static readonly Field Instance = FindByName(__.Instance); - - /// 会话。tcp://ip:port + /// 实例。IP加端口 public static readonly Field Session = FindByName(__.Session); + /// 客户端。IP加进程 + public static readonly Field Client = FindByName(__.Client); + + /// 名称。机器名称 + public static readonly Field Name = FindByName(__.Name); + + /// 版本。客户端 + public static readonly Field Version = FindByName(__.Version); + + /// 编译时间。客户端 + public static readonly Field Compile = FindByName(__.Compile); + + /// 服务端。客户端登录到哪个服务端,IP加端口 + public static readonly Field Server = FindByName(__.Server); + /// 服务地址。tcp://ip:port public static readonly Field Address = FindByName(__.Address); - /// 版本 - public static readonly Field Version = FindByName(__.Version); - /// 服务数。该应用提供的服务数 public static readonly Field Services = FindByName(__.Services); @@ -213,18 +253,27 @@ namespace Stardust.Data /// 应用 public const String AppID = "AppID"; - /// 实例。IP@进程 - public const String Instance = "Instance"; - - /// 会话。tcp://ip:port + /// 实例。IP加端口 public const String Session = "Session"; + /// 客户端。IP加进程 + public const String Client = "Client"; + + /// 名称。机器名称 + public const String Name = "Name"; + + /// 版本。客户端 + public const String Version = "Version"; + + /// 编译时间。客户端 + public const String Compile = "Compile"; + + /// 服务端。客户端登录到哪个服务端,IP加端口 + public const String Server = "Server"; + /// 服务地址。tcp://ip:port public const String Address = "Address"; - /// 版本 - public const String Version = "Version"; - /// 服务数。该应用提供的服务数 public const String Services = "Services"; @@ -256,18 +305,27 @@ namespace Stardust.Data /// 应用 Int32 AppID { get; set; } - /// 实例。IP@进程 - String Instance { get; set; } - - /// 会话。tcp://ip:port + /// 实例。IP加端口 String Session { get; set; } + /// 客户端。IP加进程 + String Client { get; set; } + + /// 名称。机器名称 + String Name { get; set; } + + /// 版本。客户端 + String Version { get; set; } + + /// 编译时间。客户端 + DateTime Compile { get; set; } + + /// 服务端。客户端登录到哪个服务端,IP加端口 + String Server { get; set; } + /// 服务地址。tcp://ip:port String Address { get; set; } - /// 版本 - String Version { get; set; } - /// 服务数。该应用提供的服务数 Int32 Services { get; set; } diff --git a/Stardust.Data/Entity/应用系统.cs b/Stardust.Data/Entity/应用系统.cs index 28a31f9a..4e1fc12c 100644 --- a/Stardust.Data/Entity/应用系统.cs +++ b/Stardust.Data/Entity/应用系统.cs @@ -48,6 +48,22 @@ namespace Stardust.Data [BindColumn("Secret", "密钥", "")] public String Secret { get { return _Secret; } set { if (OnPropertyChanging(__.Secret, value)) { _Secret = value; OnPropertyChanged(__.Secret); } } } + private String _Version; + /// 版本 + [DisplayName("版本")] + [Description("版本")] + [DataObjectField(false, false, true, 50)] + [BindColumn("Version", "版本", "")] + public String Version { get { return _Version; } set { if (OnPropertyChanging(__.Version, value)) { _Version = value; OnPropertyChanged(__.Version); } } } + + private DateTime _Compile; + /// 编译时间 + [DisplayName("编译时间")] + [Description("编译时间")] + [DataObjectField(false, false, true, 0)] + [BindColumn("Compile", "编译时间", "")] + public DateTime Compile { get { return _Compile; } set { if (OnPropertyChanging(__.Compile, value)) { _Compile = value; OnPropertyChanged(__.Compile); } } } + private Boolean _Enable; /// 启用 [DisplayName("启用")] @@ -175,6 +191,8 @@ namespace Stardust.Data case __.Name : return _Name; case __.DisplayName : return _DisplayName; case __.Secret : return _Secret; + case __.Version : return _Version; + case __.Compile : return _Compile; case __.Enable : return _Enable; case __.Services : return _Services; case __.Actions : return _Actions; @@ -200,6 +218,8 @@ namespace Stardust.Data case __.Name : _Name = Convert.ToString(value); break; case __.DisplayName : _DisplayName = Convert.ToString(value); break; case __.Secret : _Secret = Convert.ToString(value); break; + case __.Version : _Version = Convert.ToString(value); break; + case __.Compile : _Compile = Convert.ToDateTime(value); break; case __.Enable : _Enable = Convert.ToBoolean(value); break; case __.Services : _Services = Convert.ToInt32(value); break; case __.Actions : _Actions = Convert.ToInt32(value); break; @@ -236,6 +256,12 @@ namespace Stardust.Data /// 密钥 public static readonly Field Secret = FindByName(__.Secret); + /// 版本 + public static readonly Field Version = FindByName(__.Version); + + /// 编译时间 + public static readonly Field Compile = FindByName(__.Compile); + /// 启用 public static readonly Field Enable = FindByName(__.Enable); @@ -296,6 +322,12 @@ namespace Stardust.Data /// 密钥 public const String Secret = "Secret"; + /// 版本 + public const String Version = "Version"; + + /// 编译时间 + public const String Compile = "Compile"; + /// 启用 public const String Enable = "Enable"; @@ -357,6 +389,12 @@ namespace Stardust.Data /// 密钥 String Secret { get; set; } + /// 版本 + String Version { get; set; } + + /// 编译时间 + DateTime Compile { get; set; } + /// 启用 Boolean Enable { get; set; } diff --git a/Stardust.Data/Model.xml b/Stardust.Data/Model.xml index 540f4aea..4d8283e5 100644 --- a/Stardust.Data/Model.xml +++ b/Stardust.Data/Model.xml @@ -6,6 +6,8 @@ + + @@ -91,10 +93,13 @@ - - + + + + + + - @@ -104,7 +109,8 @@ - + + diff --git a/Stardust.Data/Stardust.Data.csproj b/Stardust.Data/Stardust.Data.csproj index 14d001b5..3db31b2e 100644 --- a/Stardust.Data/Stardust.Data.csproj +++ b/Stardust.Data/Stardust.Data.csproj @@ -1,7 +1,14 @@ - + netstandard2.0 + 星尘数据 + 星尘,轻量级服务框架。远程方法调用,服务自动注册和发现,负载均衡,动态伸缩,故障转移,性能监控。 + 版权所有(C) 新生命开发团队 2019 + 新生命开发团队 + 1.0.2019.0101 + 1.0.* + false diff --git a/Stardust.Web/Stardust.Web.csproj b/Stardust.Web/Stardust.Web.csproj index 75a75db6..cb1297db 100644 --- a/Stardust.Web/Stardust.Web.csproj +++ b/Stardust.Web/Stardust.Web.csproj @@ -1,7 +1,14 @@ - + netcoreapp2.1 + 星尘管理平台 + 星尘,轻量级服务框架。远程方法调用,服务自动注册和发现,负载均衡,动态伸缩,故障转移,性能监控。 + 版权所有(C) 新生命开发团队 2019 + 新生命开发团队 + 1.0.2019.0101 + 1.0.* + false diff --git a/Stardust/Program.cs b/Stardust/Program.cs index ecfdb110..1a5d2923 100644 --- a/Stardust/Program.cs +++ b/Stardust/Program.cs @@ -1,12 +1,114 @@ using System; +using System.Net; +using NewLife; +using NewLife.Agent; +using NewLife.Log; +using NewLife.Net; +using NewLife.Remoting; +using NewLife.Threading; +using Stardust.Data; namespace Stardust { class Program { - static void Main(string[] args) + static void Main(String[] args) => new MyService().Main(); + } + + /// 服务类。名字可以自定义 + class MyService : AgentServiceBase + { + /// 是否使用线程池调度。false表示禁用线程池,改用Agent线程 + public Boolean Pooling { get; set; } = true; + + public MyService() + { + ServiceName = "Stardust"; + + ThreadPoolX.QueueUserWorkItem(() => + { + var n = App.Meta.Count; + AppStat.Meta.Session.Dal.Db.ShowSQL = false; + + var set2 = XCode.Setting.Current; + if (set2.IsNew) + { + set2.Debug = true; + set2.ShowSQL = false; + set2.TraceSQLTime = 3000; + set2.SQLiteDbPath = @"..\Data"; + + set2.Save(); + } + }); + + // 注册菜单,在控制台菜单中按 t 可以执行Test函数,主要用于临时处理数据 + AddMenu('t', "数据测试", Test); + } + + ApiServer _Server; + private void Init() + { + var sc = _Server; + if (sc == null) + { + var set = Setting.Current; + + sc = new ApiServer(set.Port) + { + Log = XTrace.Log + }; + if (Setting.Current.Debug) + { + var ns = sc.EnsureCreate() as NetServer; + ns.Log = XTrace.Log; +#if DEBUG + ns.LogSend = true; + ns.LogReceive = true; + sc.EncoderLog = XTrace.Log; +#endif + } + + // 注册服务 + sc.Register(); + + StarService.Log = XTrace.Log; + StarService.Local = new IPEndPoint(NetHelper.MyIP(), set.Port); + + sc.Start(); + + _Server = sc; + } + } + + /// 服务启动 + /// + /// 安装Windows服务后,服务启动会执行一次该方法。 + /// 控制台菜单按5进入循环调试也会执行该方法。 + /// + protected override void StartWork(String reason) + { + Init(); + + base.StartWork(reason); + } + + /// 服务停止 + /// + /// 安装Windows服务后,服务停止会执行该方法。 + /// 控制台菜单按5进入循环调试,任意键结束时也会执行该方法。 + /// + protected override void StopWork(String reason) + { + base.StopWork(reason); + + _Server.TryDispose(); + _Server = null; + } + + /// 数据测试,菜单t + public void Test() { - Console.WriteLine("Hello World!"); } } -} +} \ No newline at end of file diff --git a/Stardust/Setting.cs b/Stardust/Setting.cs new file mode 100644 index 00000000..bcfbd938 --- /dev/null +++ b/Stardust/Setting.cs @@ -0,0 +1,28 @@ +using System; +using System.ComponentModel; +using NewLife.Xml; + +namespace Stardust +{ + /// 配置 + [XmlConfigFile("Config/Stardust.config", 15000)] + public class Setting : XmlConfig + { + #region 属性 + /// 调试开关。默认true + [Description("调试开关。默认true")] + public Boolean Debug { get; set; } = true; + + /// 服务端口。默认6666 + [Description("服务端口。默认6666")] + public Int32 Port { get; set; } = 6666; + #endregion + + #region 构造 + /// 实例化 + public Setting() + { + } + #endregion + } +} diff --git a/Stardust/StarClient.cs b/Stardust/StarClient.cs new file mode 100644 index 00000000..e22f73f1 --- /dev/null +++ b/Stardust/StarClient.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using NewLife.Log; +using NewLife.Net; +using NewLife.Reflection; +using NewLife.Remoting; +using NewLife.Serialization; + +namespace Stardust +{ + public class StarClient : ApiClient + { + #region 属性 + /// 用户名 + public String UserName { get; set; } + + /// 密码 + public String Password { get; set; } + + /// 是否已登录 + public Boolean Logined { get; set; } + + /// 最后一次登录成功后的消息 + public IDictionary Info { get; private set; } + #endregion + + #region 方法 + /// 实例化 + public StarClient() + { +#if DEBUG + Log = XTrace.Log; + EncoderLog = XTrace.Log; +#endif + } + + /// 实例化 + /// + public StarClient(String uri) + { + if (!uri.IsNullOrEmpty()) + { + var u = new Uri(uri); + + Servers = new[] { "{2}://{0}:{1}".F(u.Host, u.Port, u.Scheme) }; + + var us = u.UserInfo.Split(":"); + if (us.Length > 0) UserName = us[0]; + if (us.Length > 1) Password = us[1]; + } + } + #endregion + + #region 登录 + /// 连接后自动登录 + /// 客户端 + /// 强制登录 + protected override async Task OnLoginAsync(ISocketClient client, Boolean force) + { + if (Logined && !force) return null; + + var asmx = AssemblyX.Entry; + + var arg = new + { + user = UserName, + pass = Password.MD5(), + machine = Environment.MachineName, + processid = Process.GetCurrentProcess().Id, + version = asmx?.Version, + compile = asmx?.Compile, + }; + + var rs = await base.InvokeWithClientAsync(client, "Login", arg); + if (Setting.Current.Debug) XTrace.WriteLine("登录{0}成功!{1}", client, rs.ToJson()); + + Logined = true; + + return Info = rs as IDictionary; + } + #endregion + + #region 核心方法 + public async Task Report(String[] services) + { + return await InvokeAsync(nameof(Report), services); + } + #endregion + + #region 辅助 +#if DEBUG + /// 创建 + /// + /// + protected override ISocketClient OnCreate(String svr) + { + var client = base.OnCreate(svr); + if (client != null) client.Log = Log; + + return client; + } +#endif + #endregion + } +} \ No newline at end of file diff --git a/Stardust/StarService.cs b/Stardust/StarService.cs new file mode 100644 index 00000000..a6c0fc0b --- /dev/null +++ b/Stardust/StarService.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using NewLife.Log; +using NewLife.Net; +using NewLife.Remoting; +using Stardust.Data; + +namespace Stardust +{ + [Api(null)] + public class StarService : IApi, IActionFilter + { + #region 属性 + /// 本地节点 + public static EndPoint Local { get; set; } + #endregion + + #region 登录 + public IApiSession Session { get; set; } + + /// + /// 传入应用名和密钥登陆, + /// 返回应用名和应用显示名 + /// + /// 应用名 + /// + /// + [Api(nameof(Login))] + public Object Login(String user, String pass) + { + if (user.IsNullOrEmpty()) throw new ArgumentNullException(nameof(user)); + if (pass.IsNullOrEmpty()) throw new ArgumentNullException(nameof(pass)); + + var ns = Session as INetSession; + var ip = ns.Remote.Host; + var ps = ControllerContext.Current.Parameters; + + WriteLog("[{0}]从[{1}]登录", user, ns.Remote); + + // 找应用 + var app = App.FindByName(user); + if (app == null || app.Secret.IsNullOrEmpty()) + { + if (app == null) app = new App(); + + if (app.ID == 0) + { + app.Name = user; + //app.Secret = pass; + app.CreateIP = ip; + app.CreateTime = DateTime.Now; + app.Enable = true; + } + + var name = ps["name"] + ""; + if (!name.IsNullOrEmpty()) app.DisplayName = name; + + app.UpdateIP = ip; + app.UpdateTime = DateTime.Now; + + app.Save(); + } + + if (!app.Enable) throw new Exception("已禁用!"); + + // 核对密码 + if (!app.Secret.IsNullOrEmpty()) + { + var pass2 = app.Secret.MD5(); + if (pass != pass2) throw new Exception("密码错误!"); + } + + // 应用上线 + CreateOnline(app, ns, ps); + + app.LastIP = ip; + app.LastLogin = DateTime.Now; + app.Save(); + + // 记录当前用户 + Session["App"] = app; + + return new + { + app.Name, + app.DisplayName, + }; + } + + void IActionFilter.OnActionExecuting(ControllerContext filterContext) + { + var act = filterContext.ActionName; + if (act == nameof(Login)) return; + + if (Session["App"] is App app) + { + var online = GetOnline(app, Session as INetSession); + online.UpdateTime = DateTime.Now; + online.SaveAsync(); + } + else + { + var ns = Session as INetSession; + throw new ApiException(401, "{0}未登录!不能执行{1}".F(ns.Remote, act)); + } + } + + void IActionFilter.OnActionExecuted(ControllerContext filterContext) + { + var ex = filterContext.Exception; + if (ex != null && !filterContext.ExceptionHandled) + { + // 显示错误 + if (ex is ApiException) + XTrace.Log.Error(ex.Message); + else + XTrace.WriteException(ex); + } + } + #endregion + + #region 业务 + /// 报告服务列表 + /// + /// + [Api(nameof(Report))] + public Boolean Report(String[] services) + { + return false; + } + #endregion + + #region 在线状态 + AppOnline CreateOnline(IApp app, INetSession ns, IDictionary ps) + { + var ip = ns.Remote.Host; + + var machine = ps["machine"] + ""; + var pid = ps["processid"].ToInt(); + var ver = ps["version"] + ""; + var compile = ps["compile"].ToDateTime(); + + var online = GetOnline(app, ns); + + // 客户端特性 + online.Client = $"{(ip.IsNullOrEmpty() ? machine : ip)}@{pid}"; + online.Name = machine; + online.Version = ver; + online.Compile = compile; + + // 服务器特性 + pid = Process.GetCurrentProcess().Id; + online.Server = Local + "@" + pid; + online.Save(); + + // 真正的用户 + Session["AppOnline"] = online; + + // 下线 + ns.OnDisposed += (s, e) => online.Delete(); + + // 版本和编译时间 + if (app.Version.IsNullOrEmpty() || app.Version.CompareTo(ver) < 0) app.Version = ver; + if (app.Compile.Year < 2000 || app.Compile < compile) app.Compile = compile; + + return online; + } + + AppOnline GetOnline(IApp app, INetSession ns) + { + if (Session["AppOnline"] is AppOnline online) return online; + + var ip = ns.Remote.Host; + var ins = ns.Remote.EndPoint + ""; + online = AppOnline.FindBySession(ins) ?? new AppOnline { CreateIP = ip }; + online.AppID = app.ID; + online.Session = ins; + + return online; + } + #endregion + + #region 日志 + /// 日志 + public static ILog Log { get; set; } + + /// 写日志 + /// + /// + public static void WriteLog(String format, params Object[] args) => Log?.Info(format, args); + #endregion + } +} \ No newline at end of file diff --git a/Stardust/Stardust.csproj b/Stardust/Stardust.csproj index ccb1d22b..d8fe16ee 100644 --- a/Stardust/Stardust.csproj +++ b/Stardust/Stardust.csproj @@ -1,10 +1,22 @@ - + Exe netcoreapp2.1 + 星尘 + 星尘,轻量级服务框架。远程方法调用,服务自动注册和发现,负载均衡,动态伸缩,故障转移,性能监控。 + 版权所有(C) 新生命开发团队 2019 + 新生命开发团队 + 1.0.2019.0101 + 1.0.* + false + ..\Bin + + + + diff --git a/Test/Program.cs b/Test/Program.cs new file mode 100644 index 00000000..9db49358 --- /dev/null +++ b/Test/Program.cs @@ -0,0 +1,12 @@ +using System; + +namespace Test +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/Test/Test.csproj b/Test/Test.csproj new file mode 100644 index 00000000..3b17bfdc --- /dev/null +++ b/Test/Test.csproj @@ -0,0 +1,10 @@ + + + + Exe + netcoreapp2.1 + 1.0.* + false + + + diff --git a/星尘.sln b/星尘.sln index d770f406..8129f67f 100644 --- a/星尘.sln +++ b/星尘.sln @@ -16,6 +16,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Stardust.Data", "Stardust.D EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stardust.WebFx", "Stardust.WebFx\Stardust.WebFx.csproj", "{A9E0597C-E818-4B33-8AC3-BE134D68B78E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{3B87711E-FF90-470B-A429-CFDF3B9B1F5F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -38,6 +40,10 @@ Global {A9E0597C-E818-4B33-8AC3-BE134D68B78E}.Debug|Any CPU.Build.0 = Debug|Any CPU {A9E0597C-E818-4B33-8AC3-BE134D68B78E}.Release|Any CPU.ActiveCfg = Release|Any CPU {A9E0597C-E818-4B33-8AC3-BE134D68B78E}.Release|Any CPU.Build.0 = Release|Any CPU + {3B87711E-FF90-470B-A429-CFDF3B9B1F5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B87711E-FF90-470B-A429-CFDF3B9B1F5F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B87711E-FF90-470B-A429-CFDF3B9B1F5F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B87711E-FF90-470B-A429-CFDF3B9B1F5F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE