/// <summary> /// 部署 /// </summary> /// <param name="appid">应用程序appid</param> /// <param name="type">应用程序类型</param> /// <param name="serAdress">远程服务地址</param> /// <param name="zipFileFullName">压缩包地址</param> /// <returns>部署结果</returns> public async Task <Result <string> > DeployAsync(string appid, string type, string serAdress, string zipFileFullName) { return(await Task.Run((() => { Result <string> res = new Result <string>(); try { string url = $"{serAdress}/UploadZip"; FileInfo zipFile = new FileInfo(zipFileFullName); NameValueCollection dic = new NameValueCollection(); dic.Add("Type", type); dic.Add("AppId", appid); string uploadResStr = HttpHelper.HttpPostData(url, 30000, zipFile.Name, zipFileFullName, dic); var executeRes = uploadResStr.DeserializeObject <Result>(); res.IsSucceed = executeRes.IsSucceed; res.Data = $"{appid}-{serAdress}"; res.Message = executeRes.Message; } catch (Exception e) { TxtLogService.WriteLog(e, "执行版本回退异常,信息:" + new { appid, type }.SerializeObject()); } finally { TxtLogService.SaveLog("GetExeAppView", new { appid, type, serAdress }, res); } return res; }))); }
/// <summary> /// 版本回退接口 /// </summary> /// <param name="appId">appId</param> /// <param name="type">程序类型</param> /// <returns>回退类型</returns> public string VersionRollBack(string appId, string type) { Result res = new Result(); try { switch (type.ToUpper()) { case "IIS": { res = appId.IISAppVersionRollBack(); break; } case "EXE": { res = appId.ExeAppVersionRollBack(); break; } default: res.Message = "暂不支持该程序类型"; break; } } catch (Exception e) { TxtLogService.WriteLog(e, "版本回退异常,信息:" + new { appId, type }.SerializeObject()); } return(res.SerializeObject()); }
/// <summary> /// 查询指定服务器组所有负载程序信息 /// </summary> /// <param name="appId">本地程序appid</param> /// <param name="type">类型</param> /// <param name="groupId">服务器组id</param> /// <returns>程序信息集合</returns> public ActionResult QueryRemoteAppInfoList(string appId, string type, string groupId) { List <AppSerView> res = new List <AppSerView>(); try { var serList = SettingLogic.GetRemoteAppList(appId).FirstOrDefault(n => n.SerGroupId == groupId); if (serList != null) { foreach (var appSerListMap in serList.ServiceAdressList) { var remoteAppInfo = new Service().GetRemoteAppInfoById(appSerListMap.AppId, appSerListMap.AppType, appSerListMap.ServiceAdress); res.Add(new AppSerView { AppId = appId, AppType = type, GroupGuid = groupId, RemoteAppView = remoteAppInfo, ServiceAdress = appSerListMap.ServiceAdress, }); } } } catch (Exception e) { TxtLogService.WriteLog(e, "查询指定服务器组上所有负载程序信息异常,信息:" + new { appId, type, groupId }.SerializeObject()); } return(new MyJsonResult { Data = res }); }
/// <summary> /// 单个程序回退 /// </summary> /// <param name="remoteAppId">远程服务器上的appid</param> /// <param name="type">远程服务器上的type</param> /// <param name="serAdress">远程服务器地址</param> /// <returns></returns> public ActionResult RollBack(string remoteAppId, string type, string serAdress) { Result <string> res = new Result <string>(); try { if (string.IsNullOrWhiteSpace(remoteAppId)) { res.Message = "请选择要回退的程序"; return(new MyJsonResult { Data = res }); } var rollbackRes = new Service().RollBackAsync(remoteAppId, type, serAdress).Result; res = rollbackRes; } catch (Exception e) { TxtLogService.WriteLog(e, "回退单个程序异常,信息:" + new { remoteAppId, type, serAdress }.SerializeObject()); } return(new MyJsonResult { Data = res }); }
public string UploadZip() { string type = string.Empty; string appId = string.Empty; string fileName = string.Empty; Result res = new Result(); try { if (Request.Files.Count <= 0) { throw new Exception("未接收到文件"); } var fileInfo = Request.Files[0]; if (fileInfo == null) { throw new Exception("文件已损坏"); } fileName = Path.GetFileName(fileInfo.FileName); if (string.IsNullOrWhiteSpace(fileName)) { throw new Exception("文件名无法读取"); } if (!Request.Form.AllKeys.Contains("Type") || !Request.Form.AllKeys.Contains("AppId")) { throw new Exception("缺少参数"); } type = Request["Type"].TrimEnd('\r', '\n'); appId = Request["AppId"].TrimEnd('\r', '\n'); switch (type.ToUpper()) { case "IIS": { res = DoIIS(appId, fileName, fileInfo); break; } case "EXE": { res = DoExe(appId, fileName, fileInfo); break; } default: res.Message = "暂不支持该程序类型"; break; } } catch (Exception e) { TxtLogService.WriteLog(e, "上传并自动切版本异常,信息:" + new { type, appId, fileName }.SerializeObject()); res.Message = e.Message; } return(res.SerializeObject()); }
/// <summary> /// 批量回退版本 /// </summary> /// <param name="appId">本地程序的appid</param> /// <param name="serGroupId">服务器环境组</param> /// <returns>回退结果</returns> public ActionResult BatchRollBack(string appId, string serGroupId) { Result <List <Result <string> > > res = new Result <List <Result <string> > >(); try { if (string.IsNullOrWhiteSpace(appId)) { res.Message = "请选择要回退的程序"; return(new MyJsonResult { Data = res }); } if (string.IsNullOrWhiteSpace(serGroupId)) { res.Message = "请选择要部署的环境"; return(new MyJsonResult { Data = res }); } var map = SettingLogic.GetRemoteAppList().FirstOrDefault(n => n.AppId == appId && n.SerGroupId == serGroupId); if (map?.ServiceAdressList == null || !map.ServiceAdressList.Any()) { res.Message = "请先配置服务器信息"; return(new MyJsonResult { Data = res }); } Task <Result <string> >[] allTasks = new Task <Result <string> > [map.ServiceAdressList.Count]; for (int i = 0; i < map.ServiceAdressList.Count; i++) { var task = new Service().RollBackAsync(map.ServiceAdressList[i].AppId, map.ServiceAdressList[i].AppType, map.ServiceAdressList[i].ServiceAdress); allTasks[i] = task; } Task.WaitAll(allTasks); List <Result <string> > opRes = new List <Result <string> >(); foreach (var task in allTasks) { opRes.Add(task.Result); } res.IsSucceed = opRes.Exists(n => n.IsSucceed == false); res.Message = !res.IsSucceed ? "部分程序版本回退失败" : ""; res.Data = opRes; } catch (Exception e) { res.IsSucceed = false; res.Message = "批量回退失败"; TxtLogService.WriteLog(e, "批量回退异常,信息:" + new { appId, serGroupId }.SerializeObject()); } return(new MyJsonResult { Data = res }); }
/// <summary> /// 获取app信息 /// </summary> /// <param name="appId">appid</param> /// <param name="type">app类型</param> /// <returns>app信息</returns> public AppView GetAppInfoById(string appId, string type) { AppView res = new AppView(); try { switch (type.ToUpper()) { case "IIS": return(appId.GetIISAppInfoById()); case "EXE": return(appId.GetExeAppInfoById()); } } catch (Exception e) { TxtLogService.WriteLog(e, "获取app信息异常,信息:" + new { appId, type }.SerializeObject()); } return(res); }
/// <summary> /// 获取远程负载服务器app信息 /// </summary> /// <param name="remoteAppId">appid</param> /// <param name="type">app类型</param> /// <param name="serAdress">负载服务器地址</param> /// <returns>app信息</returns> public AppView GetRemoteAppInfoById(string remoteAppId, string type, string serAdress) { AppView res = new AppView(); try { switch (type.ToUpper()) { case "IIS": return(remoteAppId.GetRemoteIISAppInfoById(serAdress)); case "EXE": return(remoteAppId.GetRemoteExeAppInfoById(serAdress)); } } catch (Exception e) { TxtLogService.WriteLog(e, "获取远程负载服务器app信息异常,信息:" + new { remoteAppId, type }.SerializeObject()); } return(res); }
/// <summary> /// 回退版本(单个程序,异步) /// </summary> /// <param name="appid">远程服务器上的程序appid</param> /// <param name="type">程序类型</param> /// <param name="serAdress">远程服务器地址</param> /// <returns>回退结果</returns> public async Task <Result <string> > RollBackAsync(string appid, string type, string serAdress) { return(await Task.Run((() => { Result <string> res = new Result <string>(); try { string url = $"{serAdress}/GetExeAppView?appId={appid}&type={type}"; var executeRes = new HttpHelper().HttpGet(url, null, Encoding.UTF8, false, false, 60000).DeserializeObject <Result>(); res.IsSucceed = executeRes.IsSucceed; res.Data = $"{appid}-{serAdress}"; res.Message = executeRes.Message; } catch (Exception e) { TxtLogService.WriteLog(e, "执行版本回退异常,信息:" + new { appid, type }.SerializeObject()); } finally { TxtLogService.SaveLog("GetExeAppView", new { appid, type, serAdress }, res); } return res; }))); }
private Result DoExe(string appId, string fileName, HttpPostedFileBase fileInfo) { Result res = new Result(); try { var allProcesses = Process.GetProcesses(); // 读取进程守护信息 string mgeProcessFileName = SettingLogic.GetMgeProcessFullName(); string processMgeXmlFullName = Path.Combine(Directory.GetParent(mgeProcessFileName).FullName, "ProcessInfo.xml"); XElement element = XElement.Load(processMgeXmlFullName); var appProcessXml = element.Elements().FirstOrDefault(n => n.Attribute("ID")?.Value == appId); if (appProcessXml == null) { throw new Exception("该进程未纳入到守护进程中,无法自动部署"); } var appProcess = allProcesses.FirstOrDefault(n => n.Id.ToString() == appProcessXml.Attribute("PID").Value); if (appProcess == null) { throw new Exception("未找到该进程"); } string appFullPath = appProcess.MainModule.FileName; string appPath = Directory.GetParent(appFullPath).FullName; string newAppPath = appPath.AddVersion(); string zipPath = Path.Combine(newAppPath, fileName); appPath.CopyDirectoryTo(newAppPath); fileInfo.SaveAs(zipPath); // 复制一份压缩包到本网站目录,部署外网的时候就直接从网站目录里面拿取压缩包了。 string zipBackDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ZipFiles"); if (!Directory.Exists(zipBackDir)) { Directory.CreateDirectory(zipBackDir); } string zipBackPath = Path.Combine(zipBackDir, fileName); fileInfo.SaveAs(zipBackPath); SettingLogic.SetAppZipFilePath($"EXE-{appId}", zipBackPath); ZipHelper.UnZip(zipPath, Directory.GetParent(zipPath).FullName); // 关闭进程守护 var mgeProcess = allProcesses.FirstOrDefault(n => String.Equals(n.ProcessName, "ProcessManageApplication", StringComparison.CurrentCultureIgnoreCase)); mgeProcess?.Kill(); // 更新版本号 appProcessXml.Attribute("Path").Value = newAppPath; element.Save(processMgeXmlFullName); // 关闭源程序 appProcess.Kill(); // 启动进程守护 Process.Start(mgeProcessFileName); res.IsSucceed = true; } catch (Exception e) { TxtLogService.WriteLog(e, "切换exe版本异常,信息:" + new { appId, fileName }.SerializeObject()); res.Message = e.Message; } return(res); }
public ActionResult BatchDeploy(string appId, string serGroupId) { Result <List <Result <string> > > res = new Result <List <Result <string> > >(); try { if (string.IsNullOrWhiteSpace(appId)) { res.Message = "请选择要部署的程序"; return(new MyJsonResult { Data = res }); } if (string.IsNullOrWhiteSpace(serGroupId)) { res.Message = "请选择要部署的环境"; return(new MyJsonResult { Data = res }); } var map = SettingLogic.GetRemoteAppList().FirstOrDefault(n => n.AppId == appId && n.SerGroupId == serGroupId); if (map?.ServiceAdressList == null || !map.ServiceAdressList.Any()) { res.Message = "请先配置服务器信息"; return(new MyJsonResult { Data = res }); } // 读取压缩文件路径 string key = $"{map.AppType}-{map.AppId}"; var zipFile = SettingLogic.GetAppZipFilePath(key); if (string.IsNullOrWhiteSpace(zipFile)) { var appInfo = new Service().GetAppInfoById(map.AppId, map.AppType); zipFile = appInfo.AppName + ".zip"; ZipHelper.ZipDir(appInfo.AppPhysicalPath, zipFile); } Task <Result <string> >[] allTasks = new Task <Result <string> > [map.ServiceAdressList.Count]; for (int i = 0; i < map.ServiceAdressList.Count; i++) { var task = new Service().DeployAsync(map.ServiceAdressList[i].AppId, map.ServiceAdressList[i].AppType, map.ServiceAdressList[i].ServiceAdress, zipFile); allTasks[i] = task; } Task.WaitAll(allTasks); List <Result <string> > opRes = new List <Result <string> >(); foreach (var task in allTasks) { opRes.Add(task.Result); } res.IsSucceed = opRes.Exists(n => n.IsSucceed == false); res.Message = !res.IsSucceed ? "部分程序版本切换失败" : ""; res.Data = opRes; } catch (Exception e) { res.IsSucceed = false; res.Message = "批量部署失败"; TxtLogService.WriteLog(e, "批量部署异常,信息:" + new { appId, serGroupId }.SerializeObject()); } return(new MyJsonResult { Data = res }); }