GateServer.cs 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  1. using DeepCore;
  2. using DeepCore.IO;
  3. using DeepCore.Log;
  4. using DeepCore.Reflection;
  5. using DeepCrystal.FuckPomeloServer;
  6. using DeepCrystal.ORM.Generic;
  7. using DeepCrystal.RPC;
  8. using DeepMMO.Data;
  9. using DeepMMO.Protocol.Client;
  10. using DeepMMO.Server.SystemMessage;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. namespace DeepMMO.Server.Gate
  18. {
  19. public class GateServer : IService
  20. {
  21. /// <summary>
  22. /// 控制账号是否可以登录,默认为false,特殊权限账号忽略该配置.
  23. /// </summary>
  24. private bool mServerOpenFlag = false;
  25. public bool ServerOpenFlag { get => mServerOpenFlag; set => mServerOpenFlag = value; }
  26. private static Random random = new Random();
  27. protected readonly Logger log;
  28. protected readonly IServer acceptor;
  29. protected readonly ConnectorNodeMap groupMap;
  30. protected IRemoteNodeInfo[] realmNodes;
  31. protected bool isReady = false;
  32. /// <summary>
  33. /// 最小连接数量,由GM系统控制。
  34. /// </summary>
  35. public static int MIN_CLIENT_NUMBER_SOFT_LIMIT = 50;
  36. /// <summary>
  37. /// 最大连接数量,由GM系统控制。
  38. /// </summary>
  39. public static int MAX_CLIENT_NUMBER_SOFT_LIMIT = 100;
  40. /// <summary>
  41. /// 最大连接数量,由GM系统控制。
  42. /// </summary>
  43. public static int CLIENT_NUMBER_HARD_LIMIT = 100;
  44. /// <summary>
  45. /// 最大连接数量软限制,由GM系统控制。
  46. /// </summary>
  47. public static int CLIENT_NUMBER_SOFT_LIMIT = 10;
  48. /// <summary>
  49. /// 排队的最大数量限制,由GM系统控制。
  50. /// </summary>
  51. public static int QUEUE_MAX_LIMIT = 1;
  52. /// <summary>
  53. /// 每一名角色增加时间,由GM系统控制。
  54. /// </summary>
  55. public static int QUEUE_ADD_TIME = 30;
  56. /// <summary>
  57. /// 每一名角色增加时间,由GM系统控制。
  58. /// </summary>
  59. public static int QUEUE_MAX_HARD_ADD_TIME = 300;
  60. /// <summary>
  61. /// 间隔数量
  62. /// </summary>
  63. public static int POST_SERVER_NUMBER_INTERVAL = 5;
  64. /// <summary>
  65. /// 软进入百分比
  66. /// </summary>
  67. public static float SOFT_ENTER_PERCENTAGE = 0.1f;
  68. /// <summary>
  69. /// 硬进入百分比
  70. /// </summary>
  71. public static float HARD_ENTER_PERCENTAGE = 0.1f;
  72. /// <summary>
  73. /// 硬进入最大百分比
  74. /// </summary>
  75. public static float MAX_HARD_ENTER_PERCENTAGE = 0.08f;
  76. //------------------------------------------------------------------------------------------
  77. //public override bool IsConcurrent => false;
  78. //------------------------------------------------------------------------------------------
  79. public GateServer(ServiceStartInfo start) : base(start)
  80. {
  81. var factory = ServerFactory.Instance;
  82. var codec = ReflectionUtil.CreateInterface<IExternalizableFactory>(start.Config["NetCodec"].ToString());
  83. this.log = LoggerFactory.GetLogger(start.Address.FullPath);
  84. if (!string.IsNullOrEmpty(DeepMMO.Server.GlobalConfig.ReplaceNetHost))
  85. {
  86. start.Config["Host"] = DeepMMO.Server.GlobalConfig.ReplaceNetHost;
  87. }
  88. this.acceptor = factory.CreateServer(new HashMap<string, string>(start.Config), codec);
  89. this.acceptor.OnSessionConnected += Acceptor_OnSessionConnected;
  90. this.acceptor.OnSessionDisconnected += Acceptor_OnSessionDisconnected;
  91. this.acceptor.OnServerError += Acceptor_OnServerError;
  92. this.groupMap = new ConnectorNodeMap(log);
  93. // H.Q.Cai 添加代码开始
  94. start.Config.TryGetAsInt("ClientNumberHardLimit", out CLIENT_NUMBER_HARD_LIMIT);
  95. start.Config.TryGetAsInt("ClientNumberSoftLimit", out CLIENT_NUMBER_SOFT_LIMIT);
  96. start.Config.TryGetAsInt("QueueMaxLimit", out QUEUE_MAX_LIMIT);
  97. start.Config.TryGetAsInt("QueueAddTime", out QUEUE_ADD_TIME);
  98. start.Config.TryGetAsInt("QueueMaxHardAddTime", out QUEUE_MAX_HARD_ADD_TIME);
  99. start.Config.TryGetAsInt("PostServerNumberInterval", out POST_SERVER_NUMBER_INTERVAL);
  100. start.Config.TryGetAsFloat("SoftEnterPercentage", out SOFT_ENTER_PERCENTAGE);
  101. start.Config.TryGetAsFloat("HardEnterPercentage", out HARD_ENTER_PERCENTAGE);
  102. start.Config.TryGetAsFloat("MaxHardEnterPercentage", out MAX_HARD_ENTER_PERCENTAGE);
  103. if(start.Config.TryGetAsInt("MinClientNumberSoftLimit", out var minClientNumberSoftLimit))
  104. {
  105. MIN_CLIENT_NUMBER_SOFT_LIMIT = minClientNumberSoftLimit;
  106. }
  107. if (start.Config.TryGetAsInt("MaxClientNumberSoftLimit", out var maxClientNumberSoftLimit))
  108. {
  109. MAX_CLIENT_NUMBER_SOFT_LIMIT = maxClientNumberSoftLimit;
  110. }
  111. // H.Q.Cai 添加代码结束
  112. }
  113. protected override void OnDisposed()
  114. {
  115. this.groupMap.Dispose();
  116. }
  117. protected override Task OnStartAsync()
  118. {
  119. foreach (var server in RPGServerTemplateManager.Instance.GetAllServers())
  120. {
  121. log.WarnFormat("Templates Server:{0} Group:{1} State:{2}", server.id, server.group, server.state);
  122. }
  123. var interval = TimeSpan.FromSeconds(TimerConfig.timer_sec_GateUpdateQueue);
  124. //var interval = TimeSpan.FromSeconds(3);
  125. this.Provider.CreateTimer(UpdateInQueue, this, interval, interval);
  126. return Task.CompletedTask;
  127. }
  128. protected override Task OnStopAsync(ServiceStopInfo reason)
  129. {
  130. this.acceptor.Dispose();
  131. return Task.FromResult(0);
  132. }
  133. public override bool GetState(TextWriter output)
  134. {
  135. this.groupMap.WriteStatus(output);
  136. return true;
  137. }
  138. //------------------------------------------------------------------------------------------
  139. [RpcHandler(typeof(SystemShutdownNotify))]
  140. public virtual void rpc_HandleSystem(SystemShutdownNotify shutdown)
  141. {
  142. this.acceptor.StopAsync(shutdown.reason);
  143. }
  144. [RpcHandler(typeof(SystemGateReloadServerList))]
  145. public virtual void rpc_HandleReloadServerList(SystemGateReloadServerList reload)
  146. {
  147. this.groupMap.ReloadServerGroups();
  148. }
  149. [RpcHandler(typeof(SystemStaticServicesStartedNotify))]
  150. public virtual void rpc_HandleSystem(SystemStaticServicesStartedNotify shutdown)
  151. {
  152. base.Execute(async () =>
  153. {
  154. using (var log = StringBuilderObjectPool.AllocAutoRelease())
  155. {
  156. log.WriteLine(CUtils.SequenceChar('-', 100));
  157. log.WriteLine("- 获取查询远端服务示例");
  158. log.WriteLine(CUtils.SequenceChar('-', 100));
  159. {
  160. log.WriteLine("Provider.GetServicesWithAddressPatternAsync(\"\\w+@\\w+@ConnectServer\")");
  161. var svcs = await base.Provider.GetServicesWithAddressPatternAsync(@"\w+@\w+@ConnectServer");
  162. foreach (var svc in svcs) { log.WriteLine(svc); }
  163. }
  164. log.WriteLine(CUtils.SequenceChar('-', 100));
  165. {
  166. log.WriteLine("Provider.GetServicesWithInfoLinqAsync(\"Address.ServiceType =\\\"AreaService\\\"\", \"Address.ServiceName\")");
  167. var svcs = await base.Provider.GetServicesWithInfoLinqAsync("Address.ServiceType=\"AreaService\"", "Address.ServiceName");
  168. foreach (var svc in svcs) { log.WriteLine(svc); }
  169. }
  170. log.WriteLine(CUtils.SequenceChar('-', 100));
  171. {
  172. log.WriteLine("Provider.GetStaticServicesAsync()");
  173. var svcs = await base.Provider.GetStaticServicesAsync();
  174. foreach (var svc in svcs) { log.WriteLine(svc); }
  175. }
  176. log.WriteLine(CUtils.SequenceChar('-', 100));
  177. {
  178. log.WriteLine("Provider.FindStaticServiceWithTypeAsync(\"RankingService\")");
  179. log.WriteLine("根据分组1,获取Ranking服务分片");
  180. var group = 1;
  181. var svc = await base.Provider.FindStaticServiceWithTypeAsync(ServerNames.RankingServiceType, (list) =>
  182. {
  183. if (list.Length == 1) return list[0];
  184. if (list.Length > 0)
  185. {
  186. var rank_group = (group % list.Length).ToString();
  187. return Array.Find(list, e =>
  188. {
  189. return e.Config["IndexId"] == rank_group;
  190. });
  191. }
  192. return null;
  193. });
  194. log.WriteLine(svc);
  195. }
  196. log.WriteLine(CUtils.SequenceChar('-', 100));
  197. this.log.Info("\n" + log.ToString());
  198. }
  199. });
  200. }
  201. //------------------------------------------------------------------------------------------
  202. [RpcHandler(typeof(Ping), typeof(Pong))]
  203. public virtual Task<Pong> rpc_OnHandlePing(Ping msg)
  204. {
  205. log.Info("ping index = " + msg.index);
  206. //log.Info("on rpc_OnHandle All : " + msg);
  207. //await Task.Delay(random.Next()%1000);
  208. return Task.FromResult(new Pong() { time = msg.time, index = msg.index });
  209. }
  210. [RpcHandler(typeof(SyncConnectToGateNotify), ServerNames.ConnectServerType)]
  211. public virtual void rpc_OnHandleConnector(SyncConnectToGateNotify msg)
  212. {
  213. // log.Info("on SyncConnectToGateNotify : " + msg.connectAddress);
  214. if (groupMap.SyncConnect(msg))
  215. {
  216. if (isReady == false)
  217. {
  218. isReady = true;
  219. this.acceptor.StartAsync();
  220. log.Info($"Gate Service Is Ready ! Port={this.StartConfig["Port"]}");
  221. }
  222. }
  223. this.LogState();
  224. }
  225. //------------------------------------------------------------------------------------------
  226. [RpcHandler(typeof(SyncGateServerOpen))]
  227. public virtual void rpc_HandleSystem(SyncGateServerOpen notify)
  228. {
  229. this.ServerOpenFlag = notify.status;
  230. }
  231. [RpcHandler(typeof(SyncGateClientNumberLimit))]
  232. public virtual void rpc_HandleClientLimit(SyncGateClientNumberLimit notify)
  233. {
  234. this.groupMap.SetClientLimit(notify);
  235. }
  236. [RpcHandler(typeof(SyncGateClientAccountExpire), ServerNames.LogicServiceType)]
  237. public virtual void rpc_HandleClientLimit(SyncGateClientAccountExpire notify)
  238. {
  239. PushOtherAccountExpire(notify.accountUUid, notify.ExpectTime);
  240. }
  241. //------------------------------------------------------------------------------------------
  242. /// <summary>
  243. /// 选择最优服务器
  244. /// </summary>
  245. /// <returns></returns>
  246. protected virtual async Task<EnterToken> SelectConnectAsync(ClientEnterGateRequest login, ISession session)
  247. {
  248. //log.Log(login);
  249. try
  250. {
  251. //账号/密码/客户端信息为空//
  252. if (string.IsNullOrEmpty(login.c2s_account) || string.IsNullOrEmpty(login.c2s_token) || login.c2s_clientInfo == null)
  253. {
  254. log.Warn("账号/密码/客户端信息为空");
  255. return new EnterToken(login, new ClientEnterGateResponse()
  256. {
  257. s2c_code = ClientEnterGateResponse.CODE_ACCOUNT_OR_PASSWORD,
  258. });
  259. }
  260. //login.c2s_serverID = "19";
  261. //ServerGroup是否存在//
  262. var serverGroupID = RPGServerTemplateManager.Instance.GetServerGroupID(login.c2s_serverID);
  263. if (serverGroupID == null)
  264. {
  265. log.Warn("ServerGroup不存在");
  266. return new EnterToken(login, new ClientEnterGateResponse()
  267. {
  268. s2c_code = ClientEnterGateResponse.CODE_SERVER_NOT_OPEN,
  269. });
  270. }
  271. //第三方/一号通验证//
  272. var serverPassportResult = await RPGServerManager.Instance.Passport.VerifyAsync(login);
  273. //保存渠道Account.
  274. string platformAccount = login.c2s_account;
  275. if (serverPassportResult.Verified == false)
  276. {
  277. log.Warn("一号通验证失败");
  278. return new EnterToken(login, new ClientEnterGateResponse()
  279. {
  280. s2c_code = ClientEnterGateResponse.CODE_ACCOUNT_OR_PASSWORD,
  281. });
  282. }
  283. //统一登陆用户名,解决多渠道名称冲突//
  284. var accountUUID = await RPGServerManager.Instance.Passport.FormatAccountAsync(login);
  285. if (accountUUID == null)
  286. {
  287. log.Warn("AccountID不合法");
  288. return new EnterToken(login, new ClientEnterGateResponse()
  289. {
  290. s2c_code = ClientEnterGateResponse.CODE_ACCOUNT_OR_PASSWORD,
  291. });
  292. }
  293. using (var saveAcc = new MappingReference<AccountData>(RPGServerPersistenceManager.TYPE_ACCOUNT_DATA, accountUUID, this))
  294. {
  295. var accountData = await RPGServerPersistenceManager.Instance.GetOrCreateAccountDataAsync(saveAcc, accountUUID, login.c2s_token);
  296. if (accountData == null)
  297. {
  298. log.Warn("无法创建账号");
  299. return new EnterToken(login, new ClientEnterGateResponse()
  300. {
  301. s2c_code = ClientEnterGateResponse.CODE_NO_ACCOUNT,
  302. });
  303. }
  304. //特殊密码进入游戏时,修改权限.
  305. if (accountData.lastLoginServerID == null && serverPassportResult.Privilege != 0)
  306. {
  307. accountData.privilege = (RolePrivilege)serverPassportResult.Privilege;
  308. saveAcc.SetField(nameof(AccountData.privilege), accountData.privilege);
  309. }
  310. //var privilege = accountData.privilege;
  311. //是否有白名单权限.//
  312. bool hasPrivilege = RPGServerTemplateManager.Instance.IsValidOfPrivilege((int)accountData.privilege, "white_list");
  313. //服务器状态是否开启.//
  314. if (!hasPrivilege && !ServerOpenFlag)
  315. {
  316. log.Warn("服务器未开启");
  317. return new EnterToken(login, new ClientEnterGateResponse()
  318. {
  319. s2c_code = ClientEnterGateResponse.CODE_SERVER_NOT_OPEN,
  320. });
  321. }
  322. //获取Connector负载//
  323. if (!groupMap.TryDispatchConnect(serverGroupID, accountData.lastLoginConnectAddress, out var group, out var connect, out var inQueue, out var queueCount, out var inMaxQueue))
  324. {
  325. log.Warn("没有可用服务器");
  326. return new EnterToken(login, new ClientEnterGateResponse()
  327. {
  328. s2c_code = ClientEnterGateResponse.CODE_NO_CONNECT_SERVER,
  329. });
  330. }
  331. var loginToken = CMD5.CalculateMD5(random.Next().ToString() + accountUUID);
  332. saveAcc.SetField(nameof(AccountData.lastLoginRemoteAddress), session.RemoteAddress.ToString());
  333. saveAcc.SetField(nameof(AccountData.lastLoginTime), DateTime.Now);
  334. saveAcc.SetField(nameof(AccountData.lastLoginConnectAddress), connect.Sync.connectServiceAddress);
  335. saveAcc.SetField(nameof(AccountData.lastLoginToken), loginToken);
  336. saveAcc.SetField(nameof(AccountData.lastLoginServerID), login.c2s_serverID);
  337. saveAcc.SetField(nameof(AccountData.lastLoginServerGroupID), serverGroupID);
  338. await saveAcc.FlushAsync();
  339. //角色列表//
  340. List<RoleIDSnap> roleList = new List<RoleIDSnap>();
  341. using (var accountRoleSnapSave = new MappingReference<AccountRoleSnap>(RPGServerPersistenceManager.TYPE_ACCOUNT_ROLE_SNAP_DATA, accountUUID, this))
  342. {
  343. var accountRoleSnap = await accountRoleSnapSave.LoadOrCreateDataAsync(() => new AccountRoleSnap());
  344. foreach (var item in accountRoleSnap.roleIDMap)
  345. {
  346. roleList.Add(item.Value);
  347. }
  348. }
  349. //软性连接数限制//
  350. var isContains = ContainsAccount(session, accountUUID);
  351. var s2c_code = ClientEnterGateResponse.CODE_OK;
  352. if (inQueue && isContains == false)
  353. {
  354. s2c_code = ClientEnterGateResponse.CODE_OK_IN_QUEUE;
  355. }
  356. //if (inMaxQueue && isContains == false)
  357. //{
  358. // s2c_code = ClientEnterGateResponse.CODE_SERVER_MAX_QUEUE;
  359. //}
  360. return new EnterToken(login, new ClientEnterGateResponse()
  361. {
  362. s2c_code = s2c_code,
  363. s2c_accountUUID = accountUUID,
  364. s2c_connectHost = connect.Sync.connectHost,
  365. s2c_connectPort = connect.Sync.connectPort,
  366. s2c_connectToken = connect.Sync.connectToken,
  367. s2c_lastLoginToken = accountData.lastLoginToken,
  368. s2c_lastLoginRoleID = accountData.lastLoginRoleID,
  369. s2c_platformAccount = platformAccount,
  370. s2c_roleIDList = roleList,
  371. s2c_queueCount = queueCount,
  372. s2c_queuetTime = TimeSpan.FromSeconds(10),
  373. }, group, connect, saveAcc.Data);
  374. }
  375. }
  376. catch (Exception err)
  377. {
  378. log.Error(err.Message, err);
  379. throw;
  380. }
  381. }
  382. //----------------------------------------------------------------------------------------------------------------------------------------------
  383. //----------------------------------------------------------------------------------------------------------------------------------------------
  384. public class ConnectorNodeMap : Disposable
  385. {
  386. protected Logger log;
  387. private ReaderWriterLockSlim connect_lock = new ReaderWriterLockSlim();
  388. // 强制ServerGroup进入指定Node
  389. private ValueSortedMap<string, GroupInfo> groupMap;
  390. // 用于记录老的Session重新连接后,匹配到之前进入的Node信息
  391. private ValueSortedMap<string, NodeInfo> nodeMap;
  392. // 所有Connector信息
  393. private ValueSortedMap<string, ConnectInfo> connectorMap;
  394. public ConnectorNodeMap(Logger log)
  395. {
  396. this.log = log;
  397. this.groupMap = new ValueSortedMap<string, GroupInfo>((a, b) => a.ClientNumber - b.ClientNumber);
  398. this.nodeMap = new ValueSortedMap<string, NodeInfo>((a, b) => a.ClientNumber - b.ClientNumber);
  399. this.connectorMap = new ValueSortedMap<string, ConnectInfo>((a, b) => a.ClientNumber - b.ClientNumber);
  400. this.ReloadServerGroups();
  401. }
  402. public void ReloadServerGroups()
  403. {
  404. log.Warn("ConnectorNodeMap: ReloadServerGroups");
  405. using (connect_lock.EnterWrite())
  406. {
  407. foreach (var server in RPGServerTemplateManager.Instance.GetAllServers())
  408. {
  409. var group = groupMap.GetOrAdd(server.group, (g) => new GroupInfo(g));
  410. if (server.nodes != null)
  411. {
  412. foreach (var node in server.nodes)
  413. {
  414. if (!string.IsNullOrEmpty(node))
  415. {
  416. var nodeConnectors = nodeMap.GetOrAdd(node, (name) => new NodeInfo(name));
  417. group.BindNode(nodeConnectors);
  418. }
  419. }
  420. }
  421. }
  422. }
  423. }
  424. protected override void Disposing()
  425. {
  426. connect_lock.Dispose();
  427. }
  428. public void SetClientLimit(SyncGateClientNumberLimit notify)
  429. {
  430. using (connect_lock.EnterWrite())
  431. {
  432. if (groupMap.TryGetValue(notify.serverGroupID, out var group))
  433. {
  434. // H.Q.Cai 修改开始
  435. //group.SetClientLimit(notify.clientLimit);
  436. group.SetClientLimit(notify.clientLimit, notify.clientSoftLimit, notify.queueMaxLimit, notify.queueAddTime);
  437. // H.Q.Cai 修改结束
  438. }
  439. }
  440. }
  441. public bool SyncConnect(SyncConnectToGateNotify msg)
  442. {
  443. var msgAddr = RemoteAddress.Parse(msg.connectServiceAddress);
  444. using (connect_lock.EnterWrite())
  445. {
  446. bool ret = false;
  447. //纯数据同步//
  448. {
  449. var exist = connectorMap.TryGetOrCreate(msg.connectServiceAddress, out var conn, (addr) => new ConnectInfo(msg));
  450. if (exist) { conn.Sync = (msg); }
  451. var nodeConnectors = nodeMap.GetOrAdd(msgAddr.ServiceNode, (name) => new NodeInfo(name));
  452. nodeConnectors.SyncConnect(msgAddr, conn);
  453. ret = !exist;
  454. }
  455. //刷新每个Group用户数量//
  456. {
  457. foreach (var g in groupMap.Values)
  458. {
  459. g.Sync(connectorMap);
  460. }
  461. }
  462. //刷新排序//
  463. {
  464. connectorMap.MarkSort();
  465. nodeMap.MarkSort();
  466. groupMap.MarkSort();
  467. }
  468. return ret;
  469. }
  470. }
  471. public void UpdateInQueue(object state)
  472. {
  473. using (connect_lock.EnterWrite())
  474. {
  475. //处理ServerGroup中等待队列//
  476. foreach (var g in groupMap.Values)
  477. {
  478. try
  479. {
  480. g.UpdateInQueue(state);
  481. }
  482. catch (Exception err)
  483. {
  484. log.Error(err.Message, err);
  485. }
  486. }
  487. }
  488. }
  489. public bool TryDispatchConnect(string serverGroupID, string expectConnectAddress, out GroupInfo group, out ConnectInfo conn, out bool inQueue, out int queueCount, out bool inMaxQueue)
  490. {
  491. var expectAddr = RemoteAddress.Parse(expectConnectAddress);
  492. using (connect_lock.EnterRead())
  493. {
  494. // 通过ServerGroupID匹配 //
  495. if (groupMap.TryGetValue(serverGroupID, out group))
  496. {
  497. if (group.TryDispatchConnect(expectAddr, out conn))
  498. {
  499. inQueue = group.IsNeedQueue;
  500. queueCount = group.QueueCount;
  501. group.PushClientNumber();
  502. inMaxQueue = group.IsMaxQueue;
  503. return group.IsAllowHardEnter;
  504. //return true;
  505. }
  506. else
  507. {
  508. // 如果预期进入场景 //
  509. if (expectAddr.NotNull)
  510. {
  511. if (nodeMap.TryGetValue(expectAddr.ServiceNode, out var connectors))
  512. {
  513. if (connectors.TryDispatchConnect(expectAddr, out conn))
  514. {
  515. inQueue = group.IsNeedQueue;
  516. queueCount = group.QueueCount;
  517. group.PushClientNumber();
  518. inMaxQueue = group.IsMaxQueue;
  519. return group.IsAllowHardEnter;
  520. //return true;
  521. }
  522. }
  523. }
  524. // 兜底取所有Connect //
  525. if (connectorMap.TryGetRandomFirst(random, out conn))
  526. {
  527. inQueue = group.IsNeedQueue;
  528. queueCount = group.QueueCount;
  529. group.PushClientNumber();
  530. inMaxQueue = group.IsMaxQueue;
  531. return group.IsAllowHardEnter;
  532. //return true;
  533. }
  534. }
  535. }
  536. }
  537. inQueue = false;
  538. queueCount = 0;
  539. conn = null;
  540. inMaxQueue = false;
  541. return false;
  542. }
  543. public void WriteStatus(TextWriter sb)
  544. {
  545. using (connect_lock.EnterRead())
  546. {
  547. sb.WriteLine(CUtils.SequenceChar('-', 100));
  548. sb.WriteLine("- Group Map -");
  549. sb.WriteLine(CUtils.SequenceChar('-', 100));
  550. foreach (var group in groupMap.ToSortedArray())
  551. {
  552. group.WriteStatus(sb, string.Empty);
  553. }
  554. sb.WriteLine(CUtils.SequenceChar('-', 100));
  555. sb.WriteLine("- Node Map -");
  556. sb.WriteLine(CUtils.SequenceChar('-', 100));
  557. foreach (var conns in nodeMap.ToSortedArray())
  558. {
  559. conns.WriteStatus(sb, string.Empty);
  560. }
  561. sb.WriteLine(CUtils.SequenceChar('-', 100));
  562. sb.WriteLine("- Connector Map -");
  563. sb.WriteLine(CUtils.SequenceChar('-', 100));
  564. foreach (var conn in connectorMap.ToSortedArray())
  565. {
  566. conn.WriteStatus(sb, string.Empty);
  567. }
  568. sb.WriteLine(CUtils.SequenceChar('-', 100));
  569. }
  570. }
  571. /// <summary>
  572. /// 链接负载分组
  573. /// </summary>
  574. public class GroupInfo
  575. {
  576. private readonly ValueSortedMap<string, NodeInfo> connectorMap;
  577. private readonly LinkedList<ViewSession> inQueueSessions = new LinkedList<ViewSession>();
  578. public int NodeCount { get => connectorMap.Count; }
  579. public string GroupID { get; private set; }
  580. public int QueueCount { get => inQueueSessions.Count; }
  581. /// <summary>
  582. /// 当前连接数量
  583. /// </summary>
  584. public int ClientNumber { get; private set; }
  585. #region H.Q.Cai 代码添加
  586. // H.Q.Cai 代码添加开始
  587. /// <summary>
  588. /// 是否需要排队
  589. /// </summary>
  590. //public bool IsNeedQueue { get => this.ClientNumberLimit > 0 && this.ClientNumber >= this.ClientNumberLimit; }
  591. public bool IsNeedQueue => IsAllowSoftEnter == false;
  592. //public bool IsNeedQueue => true;
  593. //public bool IsNeedQueue => false;
  594. private readonly HashSet<ViewSession> checkInQueueSessions = new HashSet<ViewSession>();
  595. /// <summary>
  596. /// 是否已满最大的排队系统
  597. /// </summary>
  598. public bool IsMaxQueue => QueueCount >= QUEUE_MAX_LIMIT;
  599. /// <summary>
  600. /// 第一个进入列队的时间
  601. /// </summary>
  602. public DateTime? FirstInQueueTime { get; set; }
  603. /// <summary>
  604. /// 是否允许软进入
  605. /// </summary>
  606. public bool IsAllowSoftEnter => CLIENT_NUMBER_SOFT_LIMIT <= 0 || ClientNumber < CLIENT_NUMBER_SOFT_LIMIT * SOFT_ENTER_PERCENTAGE;
  607. /// <summary>
  608. /// 是否允许硬进入
  609. /// </summary>
  610. public bool IsAllowHardEnter => CLIENT_NUMBER_HARD_LIMIT <= 0 || ClientNumber < CLIENT_NUMBER_HARD_LIMIT * HARD_ENTER_PERCENTAGE;
  611. /// <summary>
  612. /// 是否超过硬上线
  613. /// </summary>
  614. public bool IsExceedHardLine => CLIENT_NUMBER_HARD_LIMIT > 0 && ClientNumber > CLIENT_NUMBER_HARD_LIMIT * MAX_HARD_ENTER_PERCENTAGE;
  615. /// <summary>
  616. /// 设置客户端限制
  617. /// </summary>
  618. internal void SetClientLimit(int hardLimit, int softLimit, int queueMaxLimit, int queueAddTime)
  619. {
  620. if (softLimit < MIN_CLIENT_NUMBER_SOFT_LIMIT) softLimit = MIN_CLIENT_NUMBER_SOFT_LIMIT;
  621. if (softLimit > MAX_CLIENT_NUMBER_SOFT_LIMIT) softLimit = MAX_CLIENT_NUMBER_SOFT_LIMIT;
  622. CLIENT_NUMBER_HARD_LIMIT = hardLimit;
  623. CLIENT_NUMBER_SOFT_LIMIT = softLimit;
  624. QUEUE_MAX_LIMIT = queueMaxLimit;
  625. QUEUE_ADD_TIME = queueAddTime;
  626. }
  627. // H.Q.Cai 代码添加结束
  628. #endregion
  629. public GroupInfo(string group)
  630. {
  631. this.GroupID = group;
  632. this.connectorMap = new ValueSortedMap<string, NodeInfo>((a, b) =>
  633. {
  634. return a.ClientNumber - b.ClientNumber;
  635. });
  636. }
  637. internal void BindNode(NodeInfo node)
  638. {
  639. connectorMap.Put(node.NodeName, node);
  640. }
  641. internal void Sync(IDictionary<string, ConnectInfo> connectorMap)
  642. {
  643. // H.Q.Cai 添加代码开始
  644. var oldClientNumber = ClientNumber;
  645. // H.Q.Cai 添加代码结束
  646. this.ClientNumber = 0;
  647. foreach (var c in connectorMap.Values)
  648. {
  649. foreach (var gn in c.Sync.groupClientNumbers)
  650. {
  651. if (gn.Key == this.GroupID)
  652. {
  653. this.ClientNumber += gn.Value;
  654. }
  655. }
  656. }
  657. // H.Q.Cai 添加代码开始
  658. if (oldClientNumber != ClientNumber)
  659. {
  660. var subtraction = oldClientNumber - ClientNumber;
  661. if (subtraction > POST_SERVER_NUMBER_INTERVAL || subtraction < -POST_SERVER_NUMBER_INTERVAL)
  662. RPGServerTemplateManager.Instance.PostGroupServerNumber(GroupID, ClientNumber);
  663. }
  664. // H.Q.Cai 添加代码结束
  665. }
  666. internal bool TryDispatchConnect(RemoteAddress addr, out ConnectInfo conn)
  667. {
  668. // 从当前分组里找到对应的Node链接负载 //
  669. if (addr.NotNull && connectorMap.TryGetValue(addr.ServiceNode, out var node))
  670. {
  671. if (node.TryDispatchConnect(addr, out conn))
  672. {
  673. return true;
  674. }
  675. }
  676. // 尝试从最小负载Node链接负载 //
  677. if (connectorMap.TryGetRandomFirst(random, out node))
  678. {
  679. if (node.TryDispatchConnect(addr, out conn))
  680. {
  681. return true;
  682. }
  683. }
  684. conn = null;
  685. return false;
  686. }
  687. internal void WriteStatus(TextWriter sb, string prefix)
  688. {
  689. sb.WriteLine($"{prefix}{GetType().Name} : {GroupID}");
  690. sb.WriteLine($"{prefix} ClientNumber={ClientNumber}");
  691. sb.WriteLine($"{prefix} ClientInQueue={inQueueSessions.Count}");
  692. foreach (var conn in connectorMap.ToSortedArray())
  693. {
  694. conn.WriteStatus(sb, prefix + " - ");
  695. }
  696. }
  697. //开始排队等待//
  698. public void PushInQueue(ViewSession session)
  699. {
  700. inQueueSessions.AddLast(session);
  701. checkInQueueSessions.Add(session);
  702. }
  703. internal void PushClientNumber()
  704. {
  705. if (!IsNeedQueue)
  706. {
  707. this.ClientNumber += 1;
  708. }
  709. }
  710. internal void UpdateInQueue(object state)
  711. {
  712. // H.Q.Cai 添加开始
  713. var gateServer = state as GateServer;
  714. if (gateServer == null) return;
  715. DateTime nowTime = DateTime.Now;
  716. TimeSpan constExpectTime = TimeSpan.FromSeconds(QUEUE_ADD_TIME);
  717. TimeSpan constExpectHardTime = TimeSpan.FromSeconds(QUEUE_MAX_HARD_ADD_TIME);
  718. int queueIndexNew = 0;
  719. for (var it = inQueueSessions.First; it != null;)
  720. {
  721. var subTimeSpan = FirstInQueueTime.HasValue ? nowTime - FirstInQueueTime.Value : TimeSpan.Zero;
  722. bool isEnter;
  723. if (IsExceedHardLine)
  724. isEnter = subTimeSpan >= constExpectHardTime;
  725. else
  726. isEnter = subTimeSpan >= constExpectTime;
  727. if (gateServer.ContainsSession(it.Value.Session) == false)
  728. {
  729. var rm = it;
  730. it = it.Next;
  731. inQueueSessions.Remove(rm);
  732. checkInQueueSessions.Remove(rm.Value);
  733. if (it == null) FirstInQueueTime = null;
  734. else FirstInQueueTime = nowTime;
  735. }
  736. else if (it.Value.IsConnected == false)
  737. {
  738. gateServer.RemoveSessionAccount(it.Value.Session);
  739. var rm = it;
  740. it = it.Next;
  741. inQueueSessions.Remove(rm);
  742. checkInQueueSessions.Remove(rm.Value);
  743. if (it == null) FirstInQueueTime = null;
  744. else FirstInQueueTime = nowTime;
  745. }
  746. else if (isEnter)
  747. {
  748. if (IsAllowHardEnter == false)
  749. {
  750. continue;
  751. }
  752. if (gateServer.ContainsSession(it.Value.Session) == false)
  753. {
  754. continue;
  755. }
  756. gateServer.PushAccountExpire(it.Value.Session, it.Value.Enter.response.s2c_accountUUID, nowTime + constExpectTime);
  757. it.Value.UpdateInQueue(queueIndexNew, true, TimeSpan.Zero);
  758. ClientNumber += 1;
  759. var rm = it;
  760. it = it.Next;
  761. inQueueSessions.Remove(rm);
  762. checkInQueueSessions.Remove(rm.Value);
  763. if (it == null) FirstInQueueTime = null;
  764. else FirstInQueueTime = nowTime;
  765. }
  766. else
  767. {
  768. if (gateServer.ContainsSession(it.Value.Session) == false)
  769. {
  770. continue;
  771. }
  772. subTimeSpan = constExpectTime - subTimeSpan;
  773. TimeSpan expectTime = TimeSpan.FromSeconds(constExpectTime.TotalSeconds * queueIndexNew) + subTimeSpan;
  774. it.Value.UpdateInQueue(queueIndexNew, false, expectTime);
  775. it = it.Next;
  776. queueIndexNew++;
  777. }
  778. //log.Warn("queueIndexNew : " + queueIndexNew);
  779. }
  780. return;
  781. // H.Q.Cai 添加结束
  782. /*
  783. int allowCount = CLIENT_NUMBER_HARD_LIMIT > 0 ? CLIENT_NUMBER_HARD_LIMIT - ClientNumber : int.MaxValue;
  784. int queueIndex = 0;
  785. for (var it = inQueueSessions.First; it != null;)
  786. {
  787. var isEnter = allowCount > 0;
  788. if (it.Value.IsConnected == false)
  789. {
  790. var rm = it;
  791. it = it.Next;
  792. inQueueSessions.Remove(rm);
  793. }
  794. else if (isEnter)
  795. {
  796. it.Value.UpdateInQueue(queueIndex, isEnter);
  797. allowCount--;
  798. this.ClientNumber += 1;
  799. var rm = it;
  800. it = it.Next;
  801. inQueueSessions.Remove(rm);
  802. }
  803. else
  804. {
  805. it.Value.UpdateInQueue(queueIndex, isEnter);
  806. it = it.Next;
  807. queueIndex++;
  808. }
  809. }
  810. */
  811. }
  812. }
  813. /// <summary>
  814. /// 链接负载
  815. /// </summary>
  816. public class NodeInfo
  817. {
  818. private readonly ValueSortedMap<string, ConnectInfo> connectorMap;
  819. public int ConnectorCount { get => connectorMap.Count; }
  820. public int ClientNumber { get; private set; }
  821. public string NodeName { get; private set; }
  822. public NodeInfo(string name)
  823. {
  824. this.NodeName = name;
  825. this.connectorMap = new ValueSortedMap<string, ConnectInfo>((a, b) =>
  826. {
  827. return a.ClientNumber - b.ClientNumber;
  828. });
  829. }
  830. internal bool SyncConnect(RemoteAddress addr, ConnectInfo msg)
  831. {
  832. msg.Node = this;
  833. var ret = this.connectorMap.TryAddOrUpdate(addr.ServiceName, msg);
  834. this.ClientNumber = connectorMap.Sum(e => e.Value.ClientNumber);
  835. connectorMap.MarkSort();
  836. return ret;
  837. }
  838. internal bool TryDispatchConnect(RemoteAddress addr, out ConnectInfo conn)
  839. {
  840. //从指定的ServiceName,获得链接//
  841. if (addr.NotNull && connectorMap.TryGetValue(addr.ServiceName, out conn))
  842. {
  843. return true;
  844. }
  845. // 尝试从最小负载获得链接 //
  846. if (connectorMap.TryGetRandomFirst(random, out conn))
  847. {
  848. return true;
  849. }
  850. return false;
  851. }
  852. internal void WriteStatus(TextWriter sb, string prefix)
  853. {
  854. sb.WriteLine($"{prefix}{GetType().Name} : {NodeName}");
  855. sb.WriteLine($"{prefix} ClientNumber={ClientNumber}");
  856. foreach (var conn in connectorMap.ToSortedArray())
  857. {
  858. conn.WriteStatus(sb, prefix + " - ");
  859. }
  860. }
  861. }
  862. /// <summary>
  863. /// 连接服信息
  864. /// </summary>
  865. public class ConnectInfo
  866. {
  867. public SyncConnectToGateNotify Sync
  868. {
  869. get; internal set;
  870. }
  871. public NodeInfo Node
  872. {
  873. get; internal set;
  874. }
  875. public int ClientNumber
  876. {
  877. get => Sync.clientNumber;
  878. }
  879. public ConnectInfo(SyncConnectToGateNotify sync)
  880. {
  881. this.Sync = sync;
  882. }
  883. internal void WriteStatus(TextWriter sb, string prefix)
  884. {
  885. sb.WriteLine($"{prefix}{GetType().Name} : {Sync.connectServiceAddress} ClientNumber={ClientNumber}");
  886. }
  887. }
  888. }
  889. //----------------------------------------------------------------------------------------------------------------------------------------------
  890. /// <summary>
  891. /// 账号列队到期时间
  892. /// </summary>
  893. private readonly HashMap<string, (DateTime ExpectTime, bool IsEnetered, ISession Session)> inAccountExpire = new HashMap<string, (DateTime ExpectTime, bool IsEnetered, ISession Session)>();
  894. /// <summary>
  895. /// 账号列队到期时间(其它)
  896. /// </summary>
  897. private readonly HashMap<string, DateTime> inAccountExpireOther = new HashMap<string, DateTime>();
  898. /// <summary>
  899. /// 通过当前的Session获取账号Uuid
  900. /// </summary>
  901. private readonly HashMap<ISession, string> inSessionAccount = new HashMap<ISession, string>();
  902. /// <summary>
  903. /// 推入会议账号结束期
  904. /// </summary>
  905. private void InsertSessionAccountExpire(ISession session, string account, DateTime expire)
  906. {
  907. inSessionAccount.TryAddOrUpdate(session, account);
  908. inAccountExpire.TryAddOrUpdate(account, (expire, false, session));
  909. }
  910. /// <summary>
  911. /// 推入会议结束期
  912. /// </summary>
  913. private void PushAccountExpire(ISession session, string account, DateTime expire)
  914. {
  915. inAccountExpire.TryAddOrUpdate(account, (expire, true, session));
  916. }
  917. /// <summary>
  918. /// 推入会议结束期
  919. /// </summary>
  920. private void PushOtherAccountExpire(string account, DateTime expire)
  921. {
  922. if(expire == DateTime.MinValue)
  923. inAccountExpireOther.RemoveByKey(account);
  924. else
  925. inAccountExpireOther.TryAddOrUpdate(account, expire);
  926. }
  927. /// <summary>
  928. /// 移除会议
  929. /// </summary>
  930. /// <param name="session"></param>
  931. private bool ContainsSession(ISession session)
  932. {
  933. return inSessionAccount.ContainsKey(session);
  934. }
  935. /// <summary>
  936. /// 移除账号
  937. /// </summary>
  938. /// <param name="session"></param>
  939. private void RemoveSessionAccount(ISession session)
  940. {
  941. if (inSessionAccount.ContainsKey(session))
  942. {
  943. var sessionAccount = inSessionAccount[session];
  944. inSessionAccount.RemoveByKey(session);
  945. if (inAccountExpire.ContainsKey(sessionAccount))
  946. {
  947. var dateTime = inAccountExpire[sessionAccount];
  948. if (dateTime.IsEnetered == false)
  949. inAccountExpire.RemoveByKey(sessionAccount);
  950. }
  951. }
  952. }
  953. /// <summary>
  954. /// 包含账号
  955. /// </summary>
  956. /// <param name="session"></param>
  957. /// <param name="account"></param>
  958. private bool ContainsAccount(ISession session, string account)
  959. {
  960. if (inAccountExpire.ContainsKey(account))
  961. {
  962. var dateTime = inAccountExpire[account];
  963. var result = dateTime.IsEnetered && dateTime.ExpectTime >= DateTime.Now;
  964. return result;
  965. }
  966. if (inAccountExpireOther.ContainsKey(account))
  967. return true;
  968. return false;
  969. }
  970. /// <summary>
  971. ///
  972. /// </summary>
  973. /// <param name="state"></param>
  974. private void UpdateInQueue(object state)
  975. {
  976. DateTime nowTime = DateTime.Now;
  977. List<string> delAccountList = new List<string>();
  978. foreach (var dateTime in inAccountExpire)
  979. {
  980. var dateTimeValue = dateTime.Value;
  981. if (dateTimeValue.ExpectTime < nowTime)
  982. {
  983. delAccountList.Add(dateTime.Key);
  984. }
  985. }
  986. foreach (var account in delAccountList)
  987. {
  988. inAccountExpire.Remove(account);
  989. }
  990. delAccountList.Clear();
  991. foreach (var dateTime in inAccountExpireOther)
  992. {
  993. if (dateTime.Value < nowTime)
  994. {
  995. delAccountList.Add(dateTime.Key);
  996. }
  997. }
  998. foreach (var account in delAccountList)
  999. {
  1000. inAccountExpireOther.Remove(account);
  1001. }
  1002. groupMap.UpdateInQueue(state);
  1003. }
  1004. //----------------------------------------------------------------------------------------------------------------------------------------------
  1005. protected virtual void Acceptor_OnSessionConnected(ISession session)
  1006. {
  1007. //if (DeepCore.Log.Logger.SHOW_LOG)
  1008. {
  1009. log.Info("Acceptor_OnSessionConnected : " + session);
  1010. }
  1011. Acceptor_CreateViewSession(session);
  1012. }
  1013. protected virtual void Acceptor_OnSessionDisconnected(ISession session)
  1014. {
  1015. //if (DeepCore.Log.Logger.SHOW_LOG)
  1016. {
  1017. log.Info("Acceptor_OnSessionDisconnected : " + session);
  1018. }
  1019. // H.Q.Cai 添加开始
  1020. RemoveSessionAccount(session);
  1021. groupMap.UpdateInQueue(this);
  1022. // H.Q.Cai 添加结束
  1023. }
  1024. protected virtual void Acceptor_OnServerError(IServer server, Exception err)
  1025. {
  1026. log.Error("Acceptor_OnServerError : " + err.Message, err);
  1027. }
  1028. protected virtual ViewSession Acceptor_CreateViewSession(ISession session)
  1029. {
  1030. return new ViewSession(this, session, log);
  1031. }
  1032. //------------------------------------------------------------------------------------------
  1033. public class EnterToken
  1034. {
  1035. public readonly ClientEnterGateRequest request;
  1036. public readonly ClientEnterGateResponse response;
  1037. public readonly ConnectorNodeMap.GroupInfo group;
  1038. public readonly ConnectorNodeMap.ConnectInfo connect;
  1039. public readonly AccountData account;
  1040. public EnterToken(ClientEnterGateRequest request, ClientEnterGateResponse response, ConnectorNodeMap.GroupInfo group = null, ConnectorNodeMap.ConnectInfo connect = null, AccountData account = null)
  1041. {
  1042. this.request = request;
  1043. this.response = response;
  1044. this.group = group;
  1045. this.connect = connect;
  1046. this.account = account;
  1047. }
  1048. }
  1049. public class ViewSession
  1050. {
  1051. protected readonly Logger log;
  1052. protected readonly GateServer server;
  1053. protected readonly ISession session;
  1054. protected readonly DateTime loginTime;
  1055. protected EnterToken enter;
  1056. public ISession Session => session;
  1057. public EnterToken Enter => enter;
  1058. public bool IsConnected
  1059. {
  1060. get => session.IsConnected;
  1061. }
  1062. public ViewSession(GateServer server, ISession session, Logger log)
  1063. {
  1064. this.log = log;
  1065. this.server = server;
  1066. this.session = session;
  1067. this.session.OnValidateAsync += Session_OnValidateAsync;
  1068. this.session.OnError += Session_OnError;
  1069. this.loginTime = DateTime.Now;
  1070. }
  1071. protected virtual async Task<Tuple<bool, ISerializable>> Session_OnValidateAsync(ISession session, ISerializable user)
  1072. {
  1073. if (user is ClientEnterGateRequest)
  1074. {
  1075. //TODO 尽量分配到之前登陆过的Connect
  1076. return await server.Provider.Execute(async () =>
  1077. {
  1078. this.enter = await server.SelectConnectAsync(user as ClientEnterGateRequest, session);
  1079. if (enter.response.s2c_code == ClientEnterGateResponse.CODE_OK_IN_QUEUE)
  1080. {
  1081. // H.Q.Cai 添加开始
  1082. var nowTime = DateTime.Now;
  1083. TimeSpan queueAddTime = TimeSpan.FromSeconds(QUEUE_ADD_TIME);
  1084. DateTime constExpectTime = nowTime + TimeSpan.FromMinutes(1.0f);
  1085. enter.group.PushInQueue(this);
  1086. server.InsertSessionAccountExpire(this.session, enter.response.s2c_accountUUID, constExpectTime);
  1087. if (enter.group.QueueCount == 1)
  1088. {
  1089. enter.group.FirstInQueueTime = nowTime;
  1090. }
  1091. Func<ConnectorNodeMap.GroupInfo, TimeSpan> getWaiteSecond = group =>
  1092. {
  1093. var subTimeSpan = group.FirstInQueueTime.HasValue ? nowTime - group.FirstInQueueTime.Value : TimeSpan.Zero;
  1094. var expectTime = TimeSpan.FromSeconds(queueAddTime.TotalSeconds * (enter.group.QueueCount - 1)) + subTimeSpan;
  1095. return expectTime;
  1096. };
  1097. ClientEnterGateInQueueNotify notify = new ClientEnterGateInQueueNotify()
  1098. {
  1099. IsEnetered = false,
  1100. QueueIndex = enter.group.QueueCount - 1,
  1101. ExpectTime = getWaiteSecond(enter.group)
  1102. };
  1103. //session.SendAsync(notify).NoWait();
  1104. session.Send(notify);
  1105. // H.Q.Cai 添加结束
  1106. var result = server.ServerCodec.CloneSerializable(enter.response);
  1107. result.s2c_connectHost = null;
  1108. result.s2c_connectPort = 0;
  1109. result.s2c_connectToken = null;
  1110. result.s2c_lastLoginToken = null;
  1111. return new Tuple<bool, ISerializable>(true, result);
  1112. }
  1113. else
  1114. {
  1115. return new Tuple<bool, ISerializable>(false, enter.response);
  1116. }
  1117. });
  1118. }
  1119. else
  1120. {
  1121. return new Tuple<bool, ISerializable>(false, null);
  1122. }
  1123. }
  1124. protected virtual void Session_OnError(ISession session, Exception err)
  1125. {
  1126. log.Error(err.Message, err);
  1127. }
  1128. public virtual void UpdateInQueue(int queueIndex, bool isEnter)
  1129. {
  1130. var notify = new ClientEnterGateInQueueNotify();
  1131. notify.IsEnetered = isEnter;
  1132. notify.QueueIndex = queueIndex;
  1133. if (isEnter)
  1134. {
  1135. notify.s2c_connectHost = enter.response.s2c_connectHost;
  1136. notify.s2c_connectPort = enter.response.s2c_connectPort;
  1137. notify.s2c_connectToken = enter.response.s2c_connectToken;
  1138. notify.s2c_lastLoginToken = enter.response.s2c_lastLoginToken;
  1139. session.Send(notify);
  1140. session.Disconnect("entered");
  1141. }
  1142. else
  1143. {
  1144. session.Send(notify);
  1145. }
  1146. }
  1147. // H.Q.Cai 添加开始
  1148. /// <summary>
  1149. ///
  1150. /// </summary>
  1151. public virtual void UpdateInQueue(int queueIndex, bool isEnter, TimeSpan expectTime)
  1152. {
  1153. var notify = new ClientEnterGateInQueueNotify
  1154. {
  1155. IsEnetered = isEnter,
  1156. QueueIndex = queueIndex,
  1157. ExpectTime = expectTime
  1158. };
  1159. if (isEnter)
  1160. {
  1161. notify.s2c_connectHost = enter.response.s2c_connectHost;
  1162. notify.s2c_connectPort = enter.response.s2c_connectPort;
  1163. notify.s2c_connectToken = enter.response.s2c_connectToken;
  1164. notify.s2c_lastLoginToken = enter.response.s2c_lastLoginToken;
  1165. session.Send(notify);
  1166. session.Disconnect("entered");
  1167. }
  1168. else
  1169. {
  1170. session.Send(notify);
  1171. }
  1172. }
  1173. // H.Q.Cai 添加结束
  1174. }
  1175. //------------------------------------------------------------------------------------------
  1176. }
  1177. }