Beispiel #1
0
        public static void Register(string programNamespace)
        {
            ServicePointManager.SetTcpKeepAlive(true, 5 * 60 * 1000, 5 * 60 * 1000); // 设置系统socket如果5分钟没有交互,需要发送心跳包,进行保活

            //初始化线程池最小大小 为 1000
            ThreadPool.GetMinThreads(out var wt, out var ct);
            if (wt < 1000 || ct < 1000)
            {
                ThreadPool.SetMinThreads(Math.Max(wt, 1000), Math.Max(ct, 1000));
            }
            var    rpcServer = ServerSetting.GetRpcServer();
            string assPath   = string.IsNullOrEmpty(programNamespace)
                ? rpcServer.AssemblyPath
                : programNamespace.EndsWith(".dll")
                    ? programNamespace
                    : programNamespace + ".dll";

            if (rpcServer != null)
            {
                SuperGMSServerConfig s = new SuperGMSServerConfig()
                {
                    Port         = rpcServer.Port,
                    ServerType   = rpcServer.ServerType,
                    AssemblyPath = assPath,
                    Pool         = rpcServer.Pool,
                    Ip           = rpcServer.Ip,
                    TimeOut      = rpcServer.TimeOut,
                    Enable       = rpcServer.Enable,
                    PortList     = rpcServer.PortList,
                };
                Register(s);
            }
            logger.LogInformation($"ThreadPool.GetMinThreads: worker-{Math.Max(wt, 1000)}; io-{Math.Max(ct, 1000)}");
        }
Beispiel #2
0
        public static void Register(SuperGMSServerConfig config)
        {
            switch (config.ServerType)
            {
            default:
            case ServerType.Thrift:
                server = new ThriftRpcServer();
                break;

            case ServerType.Grpc:
                break;

            case ServerType.WCF:
                break;

            case ServerType.TaskWorker:
                server = new TaskWorker.TaskWorker();
                break;

            case ServerType.HttpWebApi:
                server = new WebApiServer();
                break;
            }

            if (server == null)
            {
            }
            else
            {
                // 开启线程去监听,要不当前主线程会被hang住
                Thread th = new Thread(new ThreadStart(() =>
                {
                    server.RpcServerRegister(config);
                }));
                th.IsBackground = true;
                th.Name         = string.Format("rpc_thread_{0}", config.AssemblyPath);
                th.Start();
                Console.CancelKeyPress += Console_CancelKeyPress;
            }
        }
Beispiel #3
0
        /// <summary>
        /// 注册服务
        /// </summary>
        /// <param name="server">服务配置</param>
        public void RpcServerRegister(SuperGMSServerConfig server)
        {
            try
            {
                distributer = new RpcDistributer(server);  // 这里会初始化serverSetting和zk连接以及其他配置

                // 注册zk登记自己(包括serverName,ip,port,pool)
                server.ServerName = distributer.ShortName; // 兼容集中配置
                if (server.PortList != null && server.PortList.ContainsKey(server.ServerName))
                {
                    server.Port = server.PortList[server.ServerName];
                    ServerSetting.UpdateRpcPort(server.Port);
                }

                bool IsExit = false;
                // 要先初始化系统相关组件之后才能注册Rpc端口,要不请·求上来了,还没有初始化其他的,会有问题
                // 去zk注册自己
                if (ServerSetting.ConfigCenter.ConfigType == ConfigType.Zookeeper)
                {
                    Task.Run(() =>
                    {
                        Random r = new Random();
                        // rpc注册socket是阻塞的,只能提前通过线程注册, 等待1s 再注册路由,这个过程中,如果rpc端口不成功,将会撤销资源退出,这个注册也就失败了,防止先注册路由,然后再rpc注册异常,导致路由瞬间抖动,造成瞬间无效广播;
                        Thread.Sleep(r.Next(1500, 2500));  // 随机等待在1s--2s之间吧,防止集群一瞬间同时重启,容易形成广播风暴,形成雪崩;
                        if (IsExit)
                        {
                            return;
                        }
                        ServerSetting.RegisterRouter(server.ServerName, server.Ip, server.Port,
                                                     ServerSetting.GetRpcServer().Enable, server.TimeOut);
                        logger.LogInformation($"\r\n服务名:{server.ServerName},开始监听Ip是:{server.Ip},端口是:{server.Port}\r\n*******************▄︻┻┳══━一zookeeper路由注册成功,系统启动成功!▄︻┻┳══━一*******************");
                    });
                }
                else
                {
                    Task.Run(() =>
                    {
                        Thread.Sleep(1500);
                        if (IsExit)
                        {
                            return;
                        }
                        logger.LogInformation($"\r\n服务名:{server.ServerName},开始监听Ip是:{server.Ip},端口是:{server.Port}\r\n*******************▄︻┻┳══━一启用本地配置,系统启动成功!▄︻┻┳══━一*******************");
                    });
                }
                ServerRegister(server); // 底层通讯和业务进行绑定
                // 只有socket才会阻塞
                if (server.ServerType == ServerType.Thrift || server.ServerType == ServerType.Grpc)
                {
                    IsExit = true; // 通知所有注册方,停止注册,系统要撤销所有资源了,防止其他异常,优雅一点点,不能太暴力
                    logger.LogWarning($"\r\n rpc端口监听异常退出:{server.ServerName}{server.Port}{server.AssemblyPath}" + "  \r\n time=" +
                                      DateTime.Now.ToString("yy-MM-dd HH:mm:ss:ffff"));

                    if (ServerSetting.ConfigCenter.ConfigType == ConfigType.Zookeeper)
                    {
                        ZookeeperManager.ClearRouter(server.ServerName, server.Ip);
                    }

                    // rpc监听是hold住当前线程的,因为底层吞掉异常了,跑到这里来就说明异常了,要彻底释放
                    // 让他等一下,把日志写完
                    System.Threading.Thread.Sleep(1000);

                    // 如果启动失败,一定要彻底清理退出,因为在线程中,只能这样,要不只是线程退出,主程序还运行
                    Environment.Exit(0);
                }
            }
            catch (Exception ex)
            {
                logger.LogCritical(ex, "\r\n Error 服务异常退出  " + DateTime.Now.ToString("yy-MM-dd HH:mm:ss:ffff"));

                // 让他等一下,把日志写完
                System.Threading.Thread.Sleep(1000);

                // 如果启动失败,一定要彻底清理退出,因为在线程中,只能这样,要不只是线程退出,主程序还运行
                Environment.Exit(0);
            }
        }
Beispiel #4
0
 /// <summary>
 /// 注册服务
 /// </summary>
 /// <param name="server">服务配置</param>
 protected abstract void ServerRegister(SuperGMSServerConfig server);