csharp/agebullhu/MicroZero/src/Core/ZeroNetCore/Application/ZeroApplication.cs

ZeroApplication.cs
using System;
using System.Net;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Agebull.Common.Ioc;
using Agebull.Common.Logging;
using Agebull.Common.Rpc;
using Agebull.ZeroNet.PubSub;
using Agebull.ZeroNet.ZeroApi;
using Gboxt.Common.DataModel;
using ZeroMQ;

namespace Agebull.ZeroNet.Core
{
    /// 
    ///     站点应用
    /// 
    public partial clast ZeroApplication
    {
        #region Console

        /// 
        ///     命令行方式管理
        /// 
        public static void CommandConsole()
        {
            while (true)
            {
                var cmd = Console.ReadLine();
                if (String.IsNullOrWhiteSpace(cmd))
                    continue;
                switch (cmd.Trim().ToLower())
                {
                    case "quit":
                    case "exit":
                        Shutdown();
                        return;
                    case "start":
                        Start();
                        continue;
                }

                var words = cmd.Split(' ', '\t', '\r', '\n');
                if (words.Length == 0)
                {
                    Console.WriteLine("请输入正确命令");
                    continue;
                }

                var result = SystemManager.Instance.CallCommand(words);
                if (result.InteractiveSuccess)
                    ZeroTrace.SystemLog("Console", result.TryGetValue(ZeroFrameType.Status, out var value)
                        ? value
                        : result.State.Text());
                else
                    ZeroTrace.WriteError("Console", result.TryGetValue(ZeroFrameType.Status, out var value)
                        ? value
                        : result.State.Text());
            }
        }

        #endregion


        #region State

        /// 
        ///     ZeroCenter是否正在运行
        /// 
        public static bool ZerCenterIsRun => ZerCenterStatus == ZeroCenterState.Run;

        /// 
        ///     服务器状态
        /// 
        public static ZeroCenterState ZerCenterStatus { get; internal set; }

        /// 
        ///     运行状态(本地与服务器均正常)
        /// 
        public static bool CanDo =>
            (ApplicationState == StationState.BeginRun || ApplicationState == StationState.Run) &&
            ZerCenterStatus == ZeroCenterState.Run;

        /// 
        ///     运行状态(本地未关闭)
        /// 
        public static bool IsAlive => ApplicationState < StationState.Destroy;

        /// 
        ///     已关闭
        /// 
        public static bool IsDisposed => ApplicationState == StationState.Disposed;

        /// 
        ///     已关闭
        /// 
        public static bool IsClosed => ApplicationState >= StationState.Closed;

        /// 
        ///     是否正在运行
        /// 
        public static bool InRun => ApplicationState == StationState.Run;

        /// 
        ///     运行状态
        /// 
        internal static int _appState;

        /// 
        ///     状态
        /// 
        public static int ApplicationState
        {
            get => _appState;
            internal set => Interlocked.Exchange(ref _appState, value);
        }

        #endregion


        #region Flow

        #region Option

        /// 
        ///     配置校验,作为第一步
        /// 
        public static void CheckOption()
        {
            ZeroTrace.SystemLog("Weconme ZeroNet");
            ZContext.Initialize();
            ZeroTrace.Initialize();
            var testContext = IocHelper.Create();
            if (testContext == null)
                IocHelper.AddScoped();
            CheckConfig();
            InitializeDependency();
        }


        /// 
        ///     设置LogRecorder的依赖属性(内部使用)
        /// 
        private static void InitializeDependency()
        {
            GlobalContext.ServiceRealName = Config.RealName;
            GlobalContext.ServiceKey = Config.ServiceKey;
            GlobalContext.ServiceName = Config.ServiceName;
            LogRecorder.GetMachineNameFunc = () => Config.ServiceName;
            LogRecorder.GetUserNameFunc = () => GlobalContext.CurrentNoLazy?.User?.Account ?? "*";
            LogRecorder.GetRequestIdFunc = () => GlobalContext.CurrentNoLazy?.Request?.RequestId ?? RandomOperate.Generate(10);
            IocHelper.AddSingleton();
            AddInImporter.Importe();
            AddInImporter.Instance.Initialize();
            LogRecorder.Initialize();
        }

        private static string GetHostIps()
        {
            var ips = new StringBuilder();
            var first = true;
            foreach (var address in Dns.GetHostAddresses(Dns.GetHostName()))
            {
                if (address.IsIPv4MappedToIPv6 || address.IsIPv6LinkLocal || address.IsIPv6Multicast ||
                    address.IsIPv6SiteLocal || address.IsIPv6Teredo)
                    continue;
                var ip = address.ToString();
                if (ip == "127.0.0.1" || ip == "127.0.1.1" || ip == "::1" || ip == "-1")
                    continue;
                if (first)
                    first = false;
                else
                    ips.Append(" , ");
                ips.Append(ip);
            }

            return ips.ToString();
        }

        /// 
        ///     发现
        /// 
        public static void Discove(astembly astembly, string stationName = null)
        {
            var discover = new ZeroDiscover
            {
                StationName = stationName ?? Config.StationName,
                astembly = astembly
            };
            ZeroTrace.SystemLog("Discove", discover.astembly.FullName);
            discover.FindApies();
            discover.FindZeroObjects();
        }

        #endregion

        #region Initialize

        /// 
        ///     初始化
        /// 
        public static void Initialize()
        {
            RegistZeroObject(ZeroConnectionPool.CreatePool());
            AddInImporter.Instance.AutoRegist();
            ApplicationState = StationState.Initialized;
            OnZeroInitialize();
            SystemManager.Instance = SystemManager.CreateInstance();
            IocHelper.Update();
        }

        #endregion

        #region Run

        /// 
        ///     启动
        /// 
        private static void Start()
        {
            using (OnceScope.CreateScope(Config))
            {
                ApplicationState = StationState.Start;
                Task.Factory.StartNew(SystemMonitor.Monitor);
                JoinCenter();
            }
            SystemMonitor.WaitMe();
        }

        /// 
        ///     运行
        /// 
        public static void Run()
        {
            Start();
        }

        /// 
        ///     执行并等待
        /// 
        public static void RunAwaite()
        {
            Console.CancelKeyPress += OnCancelKeyPress;
            Console.WriteLine("Zeronet application start...");
            Start();
            Task.Factory.StartNew(WaitTask).Wait();
        }

        /// 
        ///     应用程序等待结果的信号量对象
        /// 
        private static readonly SemapreplacedSlim WaitToken = new SemapreplacedSlim(0, 1);

        /// 
        ///     执行直到连接成功
        /// 
        private static void WaitTask()
        {
            Console.WriteLine("Zeronet application runing. Press Ctrl+C to shutdown.");
            WaitToken.Wait();
        }

        /// 
        ///     进入系统侦听
        /// 
        internal static bool JoinCenter()
        {
            ZeroTrace.SystemLog($"try connect zero center ({Config.ZeroManageAddress})...");
            if (!SystemManager.Instance.PingCenter())
            {
                ApplicationState = StationState.Failed;
                ZerCenterStatus = ZeroCenterState.Failed;
                ZeroTrace.WriteError("JoinCenter", "zero center can`t connection.");
                return false;
            }

            ZerCenterStatus = ZeroCenterState.Run;
            ApplicationState = StationState.BeginRun;
            if (!SystemManager.Instance.HeartJoin())
            {
                ApplicationState = StationState.Failed;
                ZerCenterStatus = ZeroCenterState.Failed;
                ZeroTrace.WriteError("JoinCenter", "zero center can`t join.");
                return false;
            }

            if (!SystemManager.Instance.LoadAllConfig())
            {
                ApplicationState = StationState.Failed;
                ZerCenterStatus = ZeroCenterState.Failed;
                return false;
            }
            ZeroTrace.SystemLog("be connected successfully,start local stations.");
            OnZeroStart();
            SystemManager.Instance.UploadDocameent();
            return true;
        }

        #endregion

        #region Destroy

        /// 
        ///     关闭
        /// 
        public static void Shutdown()
        {
            ZeroTrace.SystemLog("Begin shutdown...");
            switch (ApplicationState)
            {
                case StationState.Destroy:
                    return;
                case StationState.BeginRun:
                case StationState.Run:
                    OnZeroEnd();
                    break;
                case StationState.Failed:
                    SystemManager.Instance.HeartLeft();
                    break;
            }
            ApplicationState = StationState.Destroy;
            if (GlobalObjects.Count > 0)
                GlobalSemapreplaced.Wait();
            OnZeroDestory();
            SystemManager.Instance.Destroy();
            LogRecorder.Shutdown();
            SystemMonitor.WaitMe();
            GC.Collect();
            ZContext.Destroy();
            ZeroTrace.SystemLog("Application shutdown ,see you late.");
            ApplicationState = StationState.Disposed;
            WaitToken.Release();
        }

        private static void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            Shutdown();
        }

        #endregion

        #endregion

        #region Event

        /// 
        /// 站点事件发生
        /// 
        public static event EventHandler ZeroNetEvent;

        /// 
        /// 发出事件
        /// 
        public static void InvokeEvent(ZeroNetEventType centerEvent, string context, StationConfig config)
        {
            try
            {
                ZeroNetEvent?.Invoke(Config, new ZeroNetEventArgument(centerEvent, context, config));
            }
            catch (Exception e)
            {
                ZeroTrace.WriteException("ZeroNetEvent", e, centerEvent, context, config);
            }
        }

        /// 
        /// 发出事件
        /// 
        /// 
        internal static void RaiseEvent(ZeroNetEventType centerEvent)
        {
            try
            {
                ZeroNetEvent?.Invoke(Config, new ZeroNetEventArgument(centerEvent, null, null));
            }
            catch (Exception e)
            {
                ZeroTrace.WriteException("ZeroNetEvent", e, centerEvent);
            }
        }
        #endregion
    }
}