/// <summary> /// 创建主方法 /// </summary> /// <param name="path">dll 路径</param> /// <param name="outPutDir">输出proxy.cs 文件路径</param> /// <param name="template">模板</param> /// <param name="templateBody">模板主体</param> /// <param name="interfaceBody">接口主体</param> /// <returns>返回是否创建成功</returns> public bool Create(string path, string outPutDir, string template, string templateBody, string interfaceBody) { try { var asLoad = LoadAssembly(path); Type[] types = asLoad.GetTypes(); string assShortName = AssemblyToolProxy.GetCurrentAppName(asLoad); StringBuilder body = new StringBuilder(); StringBuilder interfaceBodySb = new StringBuilder(); body.AppendLine(string.Format("private const string serviceName=\"{0}\";", assShortName)); body.AppendLine(); // 加载所有继承了AppBase的类 var useTypes = types.Where(t => RpcDistributer.isChildAppBase(t) && !t.IsAbstract).ToList(); return(WriteFile(outPutDir, template, templateBody, interfaceBody, useTypes, body, interfaceBodySb, assShortName)); } catch (ReflectionTypeLoadException rtlEx) { logger.LogError(rtlEx, $"无法加载程序集:{rtlEx.Message}"); if (rtlEx.LoaderExceptions != null && rtlEx.LoaderExceptions.Length > 0) { foreach (var lex in rtlEx.LoaderExceptions) { logger.LogError(lex, $"无法加载程序集:{lex.Message}"); } } } catch (TypeLoadException tlEx) { logger.LogError(tlEx, $"无法加载程序集: {tlEx.TypeName}"); } catch (FileNotFoundException fNtEx) { logger.LogError(fNtEx, $"无法加载程序集: {fNtEx.FileName}"); } return(false); }
/// <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); } }