/// <summary> /// 获取一个可以工作的机器人 /// </summary> /// <param name="clientKey">客户的唯一标识</param> /// <param name="type">申请机器人的类型</param> /// <returns>一台可工作的机器人</returns> public IRobot ApplyOneAvailableRobot(RobotType type, string clientKey = null) { IRobot robot = null; if (String.IsNullOrEmpty(clientKey)) { throw new ArgumentException("Client Key 不能为空"); } // 1. 如果之前有注册机器人,则继续使用 if (_roster.ContainsKey(clientKey)) { string apiKey = _roster[clientKey]; RobotStruct robotStruct = _robots[apiKey]; if (robotStruct.RobotType != type) { throw new UnmatchedTypeException(robotStruct.RobotType, "已经注册了不同类型的机器人"); } robot = robotStruct.Robot; return(robot); } // 2. 如果是共享类型的机器人,则搜索 if (RobotType.Public == type) { foreach (string apiKey in _robots.Keys) { RobotStruct robotStruct = _robots[apiKey]; if (RobotType.Public == robotStruct.RobotType && robotStruct.CanRegister()) { if (robotStruct.Register(clientKey)) { robot = robotStruct.Robot; return(robot); } } } } // 3. 找不到合适的机器人,则创建新的机器人,并加入池中 robot = CreateRobot(clientKey, type); return(robot); }
/// <summary> /// 机器人每个1秒自动回收闲置时长超过规定分钟数的机器人 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { lock (_locker) { List <string> idledApiKey = new List <string>(); foreach (string apiKey in _robots.Keys) { RobotStruct robotStruct = _robots[apiKey]; IRobot robot = robotStruct.Robot; if (robot.IdledMinutes >= _maxIdleMinutes) { idledApiKey.Add(apiKey); foreach (string clientKey in robotStruct.RegisteredClientKeys) { if (_roster.ContainsKey(clientKey)) { if (apiKey == _roster[clientKey]) { // 先从花名册中删除 Client Key _roster.Remove(clientKey); } } } } } // 后从机器人池删除机器人 foreach (string apiKey in idledApiKey) { _robots.Remove(apiKey); } // 创建最少数量的共享类型机器人 lock (this) { int newRobotCount = (_minRobot) - (_robots.Count); foreach (string apiKey in APIKeys) { if (newRobotCount <= 0) { break; } // 确保此轮回收暂不使用失效的机器人 //if (idledApiKey.Contains(apiKey)) //{ // continue; //} if (!_robots.ContainsKey(apiKey)) { newRobotCount--; IRobot robot = new Robot(APIBaseURL, apiKey); RobotStruct robotStruct = new RobotStruct(robot, RobotType.Public, _maxClientPerRobot); _robots.Add(apiKey, robotStruct); } } } // 后从机器人池删除机器人 //foreach (string apiKey in idledApiKey) //{ // _robots.Remove(apiKey); //} } }
/// <summary> /// 创建机器人实例 /// </summary> private IRobot CreateRobot(string clientKey, RobotType type) { IRobot registeredRobot = null; // 加锁,主要防止同时并发创建机器人实例对象 lock (this) { if (_robots.Count >= _maxRobot) { throw new MaxRobotException(_maxRobot); } int newRobotCount = 0; if (RobotType.Private == type) { newRobotCount = 1; } else if (RobotType.Public == type) { newRobotCount = _newRobot; if (_robots.Count + _newRobot >= _maxRobot) { newRobotCount = _maxRobot - _robots.Count; } } // 创建机器人 int maxClientPerRobot = _maxClientPerRobot; if (RobotType.Private == type) { maxClientPerRobot = 1; } foreach (string key in APIKeys) { if (newRobotCount <= 0) { break; } if (!_robots.ContainsKey(key)) { newRobotCount--; IRobot robot = new Robot(APIBaseURL, key); RobotStruct robotStruct = new RobotStruct(robot, type, maxClientPerRobot); if (null == registeredRobot) { robotStruct.Register(clientKey); registeredRobot = robotStruct.Robot; _roster.Add(clientKey, key); } _robots.Add(key, robotStruct); } } } return(registeredRobot); }