Quellcode durchsuchen

增加进程管理App: Watcher,
Watcher是一个守护进程,一台物理机只有一个,可以用来管理该物理机上的进程
目前实现了一键启动该物理机所有进程的功能,使用方式如下:
dotnet Server.dll --AppType=Watcher --Console=1
Watcher会把StartProcessConfig中,配置在该物理机上的进程启动起来,并且创建进程上的Scenes
关闭Watcher会把Watcher启动的进程全部关闭

tanghai vor 4 Jahren
Ursprung
Commit
d3d44a56aa

+ 1 - 1
Config/StartMachineConfigCategory.bytes

@@ -1,2 +1,2 @@
 
-	127.0.0.1	127.0.0.1
+	127.0.0.1	127.0.0.1"10000

+ 2 - 3
Config/StartProcessConfigCategory.bytes

@@ -1,4 +1,3 @@
 
-¡œ"
-Server.App
-¢œ"	Robot.App
+¡œ"Server
+¢œ"Robot

BIN
Excel/StartMachineConfig.xlsx


BIN
Excel/StartProcessConfig.xlsx


+ 4 - 0
Robot/App/Program.cs

@@ -11,6 +11,10 @@ namespace ET
     {
         private static void Main(string[] args)
         {
+            AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
+            {
+                Log.Error(e.ExceptionObject.ToString());
+            };
             // 异步方法全部会回掉到主线程
             SynchronizationContext.SetSynchronizationContext(ThreadSynchronizationContext.Instance);
 			

+ 1 - 0
Robot/App/Robot.App.csproj

@@ -4,6 +4,7 @@
         <OutputType>Exe</OutputType>
         <TargetFramework>net5.0</TargetFramework>
         <RootNamespace>ET</RootNamespace>
+        <AssemblyName>Robot</AssemblyName>
     </PropertyGroup>
 
     <PropertyGroup>

+ 0 - 6
Robot/Model/Robot.Model.csproj

@@ -94,11 +94,5 @@
       <ProjectReference Include="..\..\ThirdParty\ShareLib\ShareLib.csproj" />
       <ProjectReference Include="..\..\ThirdParty\UnityEngine\UnityEngine.csproj" />
     </ItemGroup>
-    <ItemGroup>
-      <PackageReference Include="CommandLineParser" Version="2.8.0" />
-      <PackageReference Include="mongocsharpdriver" Version="2.13.0" />
-      <PackageReference Include="NLog" Version="4.7.10" />
-      <PackageReference Include="SharpZipLib" Version="1.3.2" />
-    </ItemGroup>
 
 </Project>

+ 10 - 0
Server/App/NLog.config

@@ -113,6 +113,15 @@
 				layout="${longdate} ${message}" />
 	</targets>
 
+	<targets async="true">
+		<target name="Watcher" xsi:type="File"
+				openFileCacheTimeout="10"
+				keepFileOpen="true"
+				fileName="${basedir}/../Logs/${logger}.${var:appIdFormat}.Debug.log"
+				deleteOldFileOnStartup="false"
+				layout="${longdate} ${callsite:className=false:methodName=false:fileName=true:includeSourcePath=false:skipFrames=2} ${message}" />
+	</targets>
+
 	<targets async="true">
 		<target name="RobotConsole" xsi:type="Console" layout="${message}" />
 	</targets>
@@ -128,5 +137,6 @@
 		<logger ruleName="RobotWarn" name="Robot" minlevel="Warn" maxlevel="Warn" writeTo="RobotWarn" />
 		<logger ruleName="RobotError" name="Robot" minlevel="Error" maxlevel="Error" writeTo="RobotError" />
 		<logger ruleName="RobotConsole" name="Robot" minlevel="Warn" maxlevel="Error" writeTo="RobotConsole" />
+		<logger ruleName="Watcher" name="Watcher" minlevel="Trace" maxlevel="Error" writeTo="Watcher" />
 	</rules>
 </nlog>

+ 5 - 0
Server/App/Program.cs

@@ -11,6 +11,11 @@ namespace ET
 	{
 		private static void Main(string[] args)
 		{
+			AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
+			{
+				Log.Error(e.ExceptionObject.ToString());
+			};
+
 			// 异步方法全部会回掉到主线程
 			SynchronizationContext.SetSynchronizationContext(ThreadSynchronizationContext.Instance);
 			

+ 1 - 4
Server/App/Server.App.csproj

@@ -5,6 +5,7 @@
     <TargetFramework>net5.0</TargetFramework>
     <RootNamespace>ET</RootNamespace>
     <LangVersion>8</LangVersion>
+    <AssemblyName>Server</AssemblyName>
   </PropertyGroup>
 
   <PropertyGroup>
@@ -24,10 +25,6 @@
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
 
-  <ItemGroup>
-    <PackageReference Include="NLog" Version="4.7.10" />
-  </ItemGroup>
-
   <ItemGroup>
     <ProjectReference Include="..\Model\Server.Model.csproj" />
   </ItemGroup>

+ 20 - 8
Server/Hotfix/AppStart_Init.cs

@@ -26,21 +26,33 @@ namespace ET
             Game.Scene.AddComponent<ActorMessageDispatcherComponent>();
             // 数值订阅组件
             Game.Scene.AddComponent<NumericWatcherComponent>();
-
-            Game.Scene.AddComponent<NetThreadComponent>();
-            Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(processConfig.InnerIPPort);
             
-            var processScenes = StartSceneConfigCategory.Instance.GetByProcess(Game.Options.Process);
-            foreach (StartSceneConfig startConfig in processScenes)
-            {
-                await SceneFactory.Create(Game.Scene, startConfig.Id, startConfig.InstanceId, startConfig.Zone, startConfig.Name, startConfig.Type, startConfig);
-            }
+            Game.Scene.AddComponent<NetThreadComponent>();
 
             switch (Game.Options.AppType)
             {
                 case AppType.Server:
+                {
+                    Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(processConfig.InnerIPPort);
+
+                    var processScenes = StartSceneConfigCategory.Instance.GetByProcess(Game.Options.Process);
+                    foreach (StartSceneConfig startConfig in processScenes)
+                    {
+                        await SceneFactory.Create(Game.Scene, startConfig.Id, startConfig.InstanceId, startConfig.Zone, startConfig.Name,
+                            startConfig.Type, startConfig);
+                    }
+
                     break;
+                }
                 case AppType.Watcher:
+                {
+                    StartMachineConfig startMachineConfig = WatcherHelper.GetThisMachineConfig();
+                    WatcherComponent watcherComponent = Game.Scene.AddComponent<WatcherComponent>();
+                    watcherComponent.Start(Game.Options.CreateScenes);
+                    Game.Scene.AddComponent<NetInnerComponent, IPEndPoint>(NetworkHelper.ToIPEndPoint($"{startMachineConfig.InnerIP}:{startMachineConfig.WatcherPort}"));
+                    break;
+                }
+                case AppType.GameTool:
                     break;
             }
 

+ 39 - 0
Server/Hotfix/Watcher/WatcherComponentSystem.cs

@@ -0,0 +1,39 @@
+using System.Collections;
+using System.Diagnostics;
+
+namespace ET
+{
+    public class WatcherComponentAwakeSystem: AwakeSystem<WatcherComponent>
+    {
+        public override void Awake(WatcherComponent self)
+        {
+            WatcherComponent.Instance = self;
+        }
+    }
+    
+    public class WatcherComponentDestroySystem: DestroySystem<WatcherComponent>
+    {
+        public override void Destroy(WatcherComponent self)
+        {
+            WatcherComponent.Instance = null;
+        }
+    }
+    
+    public static class WatcherComponentSystem
+    {
+        public static void Start(this WatcherComponent self, int createScenes = 0)
+        {
+            string[] localIP = NetworkHelper.GetAddressIPs();
+            var processConfigs = StartProcessConfigCategory.Instance.GetAll();
+            foreach (StartProcessConfig startProcessConfig in processConfigs.Values)
+            {
+                if (!WatcherHelper.IsThisMachine(startProcessConfig.InnerIP, localIP))
+                {
+                    continue;
+                }
+                Process process = WatcherHelper.StartProcess(startProcessConfig.Id, createScenes);
+                self.Processes.Add(startProcessConfig.Id, process);
+            }
+        }
+    }
+}

+ 55 - 0
Server/Hotfix/Watcher/WatcherHelper.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace ET
+{
+    public static class WatcherHelper
+    {
+        public static StartMachineConfig GetThisMachineConfig()
+        {
+            string[] localIP = NetworkHelper.GetAddressIPs();
+            StartMachineConfig startMachineConfig = null;
+            foreach (StartMachineConfig config in StartMachineConfigCategory.Instance.GetAll().Values)
+            {
+                if (!WatcherHelper.IsThisMachine(config.InnerIP, localIP))
+                {
+                    continue;
+                }
+                startMachineConfig = config;
+                break;
+            }
+
+            if (startMachineConfig == null)
+            {
+                throw new Exception("not found this machine ip config!");
+            }
+
+            return startMachineConfig;
+        }
+        
+        public static bool IsThisMachine(string ip, string[] localIPs)
+        {
+            if (ip != "127.0.0.1" && ip != "0.0.0.0" && !((IList) localIPs).Contains(ip))
+            {
+                return false;
+            }
+            return true;
+        }
+        
+        public static Process StartProcess(int processId, int createScenes = 0)
+        {
+            StartProcessConfig startProcessConfig = StartProcessConfigCategory.Instance.Get(processId);
+            const string exe = "dotnet";
+            string arguments = $"{startProcessConfig.AppName}.dll" + 
+                    $" --Process={startProcessConfig.Id}" +
+                    $" --AppType={startProcessConfig.AppName}" +  
+                    $" --Develop={Game.Options.Develop}" +
+                    $" --CreateScenes={createScenes}" +
+                    $" --LogLevel={Game.Options.LogLevel}";
+            Log.Debug($"{exe} {arguments}");
+            Process process = ProcessHelper.Run(exe, arguments);
+            return process;
+        }
+    }
+}

+ 2 - 0
Server/Model/Generate/Config/StartMachineConfig.cs

@@ -76,6 +76,8 @@ namespace ET
 		public string InnerIP { get; set; }
 		[ProtoMember(3, IsRequired  = true)]
 		public string OuterIP { get; set; }
+		[ProtoMember(4, IsRequired  = true)]
+		public string WatcherPort { get; set; }
 
 
 		[ProtoAfterDeserialization]

+ 0 - 5
Server/Model/Server.Model.csproj

@@ -131,13 +131,8 @@
   </ItemGroup>
   
   <ItemGroup>
-    <PackageReference Include="CommandLineParser" Version="2.2.1" />
     <PackageReference Include="Microsoft.CodeAnalysis.Scripting" Version="2.9.0" />
-    <PackageReference Include="mongocsharpdriver" Version="2.13.0" />
-    <PackageReference Include="MongoDB.Bson" Version="2.13.0" />
     <PackageReference Include="MongoDB.Driver" Version="2.13.0" />
-    <PackageReference Include="NLog" Version="4.5.4" />
-    <PackageReference Include="SharpZipLib" Version="1.0.0-alpha2" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\ThirdParty\protobuf-net\protobuf-net.csproj" />

+ 12 - 0
Server/Model/Watcher/WatcherComponent.cs

@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace ET
+{
+    public class WatcherComponent: Entity
+    {
+        public static WatcherComponent Instance { get; set; }
+
+        public readonly Dictionary<int, Process> Processes = new Dictionary<int, Process>();
+    }
+}

+ 8 - 0
ThirdParty/ShareLib/ShareLib.csproj

@@ -45,4 +45,12 @@
       </Compile>
     </ItemGroup>
 
+    <ItemGroup>
+      <PackageReference Include="CommandLineParser" Version="2.8.0" />
+      <PackageReference Include="mongocsharpdriver" Version="2.13.0" />
+      <PackageReference Include="MongoDB.Bson" Version="2.13.0" />
+      <PackageReference Include="NLog" Version="4.7.10" />
+      <PackageReference Include="SharpZipLib" Version="1.3.2" />
+    </ItemGroup>
+
 </Project>

+ 1 - 1
Unity/Assets/Bundles/Config/StartMachineConfigCategory.bytes

@@ -1,2 +1,2 @@
 
-	127.0.0.1	127.0.0.1
+	127.0.0.1	127.0.0.1"10000

+ 2 - 3
Unity/Assets/Bundles/Config/StartProcessConfigCategory.bytes

@@ -1,4 +1,3 @@
 
-¡œ"
-Server.App
-¢œ"	Robot.App
+¡œ"Server
+¢œ"Robot

+ 1 - 1
Unity/Assets/Editor/RsyncEditor/RsyncEditor.cs

@@ -82,7 +82,7 @@ namespace ET
 			{
 				string arguments =
 						$"-vzrtopg --password-file=./Tools/cwRsync/Config/rsync.secrets --exclude-from=./Tools/cwRsync/Config/exclude.txt --delete ./ {this.rsyncConfig.Account}@{this.rsyncConfig.Host}::Upload/{this.rsyncConfig.RelativePath} --chmod=ugo=rwX";
-				ProcessHelper.Run(@"./Tools/cwRsync/rsync.exe", arguments, @"..\", waitExit: true);
+				ProcessHelper.Run(@"./Tools/cwRsync/rsync.exe", arguments, @"..\");
 				Log.Info("同步完成!");
 			}
 		}

+ 6 - 1
Unity/Assets/Model/Core/Options.cs

@@ -8,7 +8,8 @@ namespace ET
     {
         Server,
         Robot,
-        Watcher,
+        Watcher, // 每台物理机一个守护进程,用来启动该物理机上的所有进程
+        GameTool,
     }
     
     public class Options
@@ -27,5 +28,9 @@ namespace ET
         
         [Option("Console", Required = false, Default = 0)]
         public int Console { get; set; } = 0;
+        
+        // 进程启动是否创建该进程的scenes
+        [Option("CreateScenes", Required = false, Default = 1)]
+        public int CreateScenes { get; set; } = 1;
     }
 }

+ 56 - 19
Unity/Assets/Model/Core/ProcessHelper.cs

@@ -1,14 +1,16 @@
 using System;
 using System.Diagnostics;
 using System.Runtime.InteropServices;
+using System.Threading.Tasks;
 using Path = System.IO.Path;
 
 namespace ET
 {
     public static class ProcessHelper
     {
-        public static Process Run(string exe, string arguments, string workingDirectory = ".", bool waitExit = false)
+        public static Process Run(string exe, string arguments, string workingDirectory = ".")
         {
+            //Log.Debug($"Process Run exe:{exe} ,arguments:{arguments} ,workingDirectory:{workingDirectory}");
             try
             {
                 bool redirectStandardOutput = true;
@@ -20,14 +22,6 @@ namespace ET
                     redirectStandardError = false;
                     useShellExecute = true;
                 }
-
-                if (waitExit)
-                {
-                    redirectStandardOutput = true;
-                    redirectStandardError = true;
-                    useShellExecute = false;
-                }
-                
                 ProcessStartInfo info = new ProcessStartInfo
                 {
                     FileName = exe,
@@ -38,17 +32,10 @@ namespace ET
                     RedirectStandardOutput = redirectStandardOutput,
                     RedirectStandardError = redirectStandardError,
                 };
-                
-                Process process = Process.Start(info);
 
-                if (waitExit)
-                {
-                    process.WaitForExit();
-                    if (process.ExitCode != 0)
-                    {
-                        throw new Exception($"{process.StandardOutput.ReadToEnd()} {process.StandardError.ReadToEnd()}");
-                    }
-                }
+                Process process = Process.Start(info);
+                
+                WaitExitAsync(process);
 
                 return process;
             }
@@ -57,5 +44,55 @@ namespace ET
                 throw new Exception($"dir: {Path.GetFullPath(workingDirectory)}, command: {exe} {arguments}", e);
             }
         }
+        
+        private static async void WaitExitAsync(Process process)
+        {
+            await process.WaitForExitAsync();
+#if NOT_UNITY
+            Log.Info($"process exit, exitcode: {process.ExitCode} {process.StandardOutput.ReadToEnd()} {process.StandardError.ReadToEnd()}");
+#endif
+        }
+        
+#if !NOT_UNITY
+        private static async Task WaitForExitAsync(this Process self)
+        {
+            if (!self.HasExited)
+            {
+                return;
+            }
+
+            try
+            {
+                self.EnableRaisingEvents = true;
+            }
+            catch (InvalidOperationException)
+            {
+                if (self.HasExited)
+                {
+                    return;
+                }
+                throw;
+            }
+
+            var tcs = new TaskCompletionSource<bool>();
+
+            void Handler(object s, EventArgs e) => tcs.TrySetResult(true);
+            
+            self.Exited += Handler;
+
+            try
+            {
+                if (self.HasExited)
+                {
+                    return;
+                }
+                await tcs.Task;
+            }
+            finally
+            {
+                self.Exited -= Handler;
+            }
+        }
+#endif
     }
 }

+ 2 - 0
Unity/Assets/Model/Generate/Config/StartMachineConfig.cs

@@ -76,6 +76,8 @@ namespace ET
 		public string InnerIP { get; set; }
 		[ProtoMember(3, IsRequired  = true)]
 		public string OuterIP { get; set; }
+		[ProtoMember(4, IsRequired  = true)]
+		public string WatcherPort { get; set; }
 
 
 		[ProtoAfterDeserialization]