using System; using System.Collections.Generic; using System.Data.SqlTypes; using System.Diagnostics; using System.Linq; using System.Net; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using System.Threading.Tasks; namespace TPEPublicValuePriceCaller { // 注意: 您可以使用 [重構] 功能表上的 [重新命名] 命令同時變更程式碼、svc 和組態檔中的類別名稱 "Service1"。 // 注意: 若要啟動 WCF 測試用戶端以便測試此服務,請在 [方案總管] 中選取 Service1.svc 或 Service1.svc.cs,然後開始偵錯。 public class Service : IService { #region 宣告變數 //估計執行總時間: Stopwatch watch = new Stopwatch(); //用來避免重複執行start的 DateTime myUpdateDate; //臺北市的timer System.Timers.Timer tpeQueryTPETimer = new System.Timers.Timer(); System.Timers.Timer tpeAvgSpeedTimer = new System.Timers.Timer(); //新北市的timer System.Timers.Timer newTpeQueryTPETimer = new System.Timers.Timer(); System.Timers.Timer newTpeAvgSpeedTimer = new System.Timers.Timer(); bool tpeWCFCalling = false; bool newTpeWCFCalling = false; //臺北市的狀態記錄 int tpeNowCount;//現在執行完畢的筆數 int tpeOldCount;//五秒前的執行完畢的筆數 int tpeTotalCount;//臺北市總筆數 //新北市的狀態記錄 int newTpeNowCount;//現在執行完畢的筆數 int newTpeOldCount;//五秒前的執行完畢的筆數 int newTpeTotalCount;//新北市總筆數 //臺北市的平均執行速度狀態記錄 int tpeOldMinuteCount; //一分鐘前執行完畢的筆數 int tpeNowMinuteCount; //目前執行完畢的筆數 //新北市的平均執行速度狀態記錄 int newTpeOldMinuteCount; //一分鐘前執行完畢的筆數 int newTpeNowMinuteCount; //目前執行完畢的筆數 string tpeCityCode = "0000"; //臺北市城市代碼 string newTpeCityCode = "0001";//新北市程式代碼 #endregion #region operation contract public string StartBatchExe() { string serverStatus = "未知的狀態,請恰系統管理員!"; //檢查是否有其他伺服器正在發送 string yOrN = ""; string ip = ""; using (RobotEntities dbRobot = new RobotEntities()) { //同一時間只能有一個instance執行大量發送 var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault(); yOrN = exeSetup.CODE_VALUE.Trim(); ip = exeSetup.CODE_MEMO.Trim(); } if (yOrN == "N" && ip == "") { //表示沒其他主機再發送,因此可以繼續執行 //並記錄目前發送中的ip //修改db設定的yOrN, IP, UpdateDate以強制其他的instance終止,避免多個instance同時執行 UpdateExeSetup("Y", GetHostIP()); serverStatus = "批次執行成功!"; } else { //已經有其他台主機再發送,或是自己這台已經再發送 //修改db設定的yOrN, IP, UpdateDate以強制其他的instance終止,避免多個instance同時執行 UpdateExeSetup("Y", GetHostIP()); serverStatus = "批次執行成功!(已強制其他執行中的instance終止執行)"; } init(); //開始記錄總執行時間 watch.Start(); //開始查詢臺北 TPETimerStart(); tpeNowCount = GetTpeFinCountNow(); tpeOldCount = tpeNowCount; tpeNowMinuteCount = tpeNowCount; tpeOldMinuteCount = tpeNowCount; //開始查詢新北 NewTPETimerStart(); newTpeNowCount = GetNewTpeFinCountNow(); newTpeOldCount = newTpeNowCount; newTpeNowMinuteCount = newTpeNowCount; newTpeOldMinuteCount = newTpeNowCount; return serverStatus; } public string StopBatchExe() { string serverStatus = "未知的狀態,請恰系統管理員!"; //將目前執行中的主機設定為空字串 UpdateExeSetup("N", ""); serverStatus = "已成功停止執行!"; return serverStatus; } #endregion #region 其他 methods private void init() { //初始化筆數 using (rehouseEntities db = new rehouseEntities()) { //臺北市總筆數 tpeTotalCount = db.pft23.Where(p => p.city_code == tpeCityCode).Count(); //新北市總筆數 newTpeTotalCount = db.pft23.Where(p => p.city_code == newTpeCityCode).Count(); } //為timer設定事件 //臺北市 tpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢 this.tpeQueryTPETimer.Elapsed += new System.Timers.ElapsedEventHandler(tpeQueryTPETimer_Tick); tpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢 tpeAvgSpeedTimer.Elapsed += new System.Timers.ElapsedEventHandler(queryTPEAverageSpeed_Tick); //新北市 newTpeQueryTPETimer.Interval = Convert.ToInt16(Config.SleepTime);//10 secs檢查一次是否有正在查詢 newTpeQueryTPETimer.Elapsed += new System.Timers.ElapsedEventHandler(newTpeQueryTPETimer_Tick); newTpeAvgSpeedTimer.Interval = Convert.ToInt32(Config.AverageSpeedCheckTime);//60 secs檢查一次是否有正在查詢 newTpeAvgSpeedTimer.Elapsed += new System.Timers.ElapsedEventHandler(queryNewTPEAverageSpeed_Tick); } public string GetHostIP() { var result = string.Empty; // 取得本機名稱 var strHostName = Dns.GetHostName(); // 取得本機的 IpHostEntry 類別實體 var iphostentry = Dns.GetHostEntry(strHostName); var ipv4 = iphostentry.AddressList.Where((e) => e.AddressFamily.ToString().Equals("InterNetwork")).ToList(); if (ipv4.Any()) { result = ipv4.First().ToString().Trim(); } return result; } ///參數設定的部分參考winform的完整程式碼即可囉:/// 更新目前執行狀態 /// /// /// private void UpdateExeSetup(string yOrN, string ip) { using (RobotEntities dbRobot = new RobotEntities()) { var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault(); exeSetup.CODE_VALUE = yOrN; exeSetup.CODE_MEMO = ip; //資料庫型態開DateTime的話,millisecond精準度需用SqlDateTime轉換為sqlserver專用的,不然會差個0.00X毫秒 myUpdateDate = new SqlDateTime(DateTime.Now).Value; exeSetup.Update_Date = new SqlDateTime(myUpdateDate).Value; dbRobot.SaveChanges(); } } #endregion #region Timer 委派事件 //每3秒持續呼叫臺北wcf一次 private void tpeQueryTPETimer_Tick(object sender, System.Timers.ElapsedEventArgs e) { if (TimerCheckIfExe() == false) { return; } tpeNowCount = GetTpeFinCountNow();//現在執行完畢的筆數 //尚未達到總筆數的時候 if (tpeNowCount != tpeTotalCount) { //等上次呼叫的兩百筆執行完才繼續呼叫 if (tpeNowCount == tpeOldCount || tpeNowCount >= tpeOldCount + Convert.ToInt32(Config.OnceTakeCount) - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate)) { //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆 //呼叫之前,先記錄目前執行完畢的筆數 //如果正在呼叫中,就不要一直呼叫,不然iis會過載 if (tpeWCFCalling == false) { tpeOldCount = GetTpeFinCountNow(); tpeWCFCalling = true; //Task.Run(() => QueryTPEByService()); Task.Factory.StartNew(() => QueryTPEByService()); } } else if (tpeNowCount < tpeOldCount + Convert.ToInt32(Config.OnceTakeCount)) { //還沒執行完上次呼叫的兩百筆,什麼都不做 } else { // } } else { //已經到達總筆數 StopTpeTimer(); //如果新北市也已經查完了,就紀錄目前無伺服器在大量發送wcf if (newTpeTotalCount == GetNewTpeFinCountNow()) { //將目前執行中的主機設定為空字串 UpdateExeSetup("N", ""); } } } //確認每分鐘臺北查詢速度 private void queryTPEAverageSpeed_Tick(object sender, System.Timers.ElapsedEventArgs e) { using (rehouseEntities db = new rehouseEntities()) { tpeNowMinuteCount = GetTpeFinCountNow(); //每三分鐘檢查一次是否速度降為零 //是的話,就重送 if (DateTime.Now.Minute % 3 == 0 && tpeNowCount != tpeTotalCount) { if (tpeNowMinuteCount - tpeOldMinuteCount == 0) { tpeOldCount = tpeNowCount; } } tpeOldMinuteCount = GetTpeFinCountNow();//記錄一分鐘前執行完畢的筆數 } } //每五秒持續呼叫新北wcf一次 private void newTpeQueryTPETimer_Tick(object sender, EventArgs e) { if (TimerCheckIfExe() == false) { return; } newTpeNowCount = GetNewTpeFinCountNow();//現在執行完畢的筆數 //尚未達到總筆數的時候 if (newTpeNowCount != newTpeTotalCount) { //等上次呼叫的兩百筆執行完才繼續呼叫 if (newTpeNowCount == newTpeOldCount || newTpeNowCount >= newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount) - Convert.ToInt32(Config.OnceTakeCount) * Convert.ToDouble(Config.NoResponseRate)) { //上次呼叫的執行完的時候,接續著呼叫下一個兩百筆wcf //或是只差一點就執行完畢兩百筆的時候,接著呼叫下一個兩百筆 //呼叫之前,先記錄目前執行完畢的筆數 //如果正在呼叫中,就不要一直呼叫,不然iis會過載 if (newTpeWCFCalling == false) { newTpeOldCount = GetNewTpeFinCountNow(); newTpeWCFCalling = true; //Task.Run(() => QueryNewTPEByService()); Task.Factory.StartNew(() => QueryNewTPEByService()); } } else if (newTpeNowCount < newTpeOldCount + Convert.ToInt32(Config.OnceTakeCount)) { //還沒執行完上次呼叫的兩百筆,什麼都不做 } else { // } } else { //已經到達總筆數 StopNewTpeTimer(); //如果臺北市也已經查完了,就紀錄目前無伺服器在大量發送wcf if (tpeTotalCount == GetTpeFinCountNow()) { //將目前執行中的主機設定為空字串 UpdateExeSetup("N", ""); } } } //確認每分鐘新北查詢速度 private void queryNewTPEAverageSpeed_Tick(object sender, System.Timers.ElapsedEventArgs e) { using (rehouseEntities db = new rehouseEntities()) { newTpeNowMinuteCount = GetNewTpeFinCountNow(); string avgSpeedResult = DateTime.Now.ToString("hh:mm") + "完成筆數:" + Convert.ToString(newTpeNowMinuteCount - newTpeOldMinuteCount); //每三分鐘檢查一次是否速度降為零 //是的話,就重送 if (DateTime.Now.Minute % 3 == 0 && newTpeNowCount != newTpeTotalCount) { //如果新北市官網的回應太少導致ResponseRate太低導致該分鐘的速度為0的話,就再度重送 if (newTpeNowMinuteCount - newTpeOldMinuteCount == 0) { newTpeOldCount = newTpeNowCount; } } newTpeOldMinuteCount = GetNewTpeFinCountNow();//記錄一分鐘前執行完畢的筆數 } } #endregion #region timer method ////// timer週期性的檢查是否可以繼續執行 /// ///private bool TimerCheckIfExe() { bool result = false; //檢查是否被中斷 string yOrN = ""; string ip = ""; DateTime updateDate; using (RobotEntities dbRobot = new RobotEntities()) { //同一時間只能有一個instance執行大量發送 var exeSetup = dbRobot.All_Code.Where(a => a.CODE_KIND == "exe" & a.CODE_ID == "SLPVPSW").FirstOrDefault(); yOrN = exeSetup.CODE_VALUE.Trim(); ip = exeSetup.CODE_MEMO.Trim(); updateDate = exeSetup.Update_Date; } //依照db裡面的yOrN+ip+updateDate,來判斷是否多個instance重複執行 if (yOrN == "Y" && ip == GetHostIP() && myUpdateDate == updateDate) { //可以繼續執行 result = true; } else { //可能是 Y + 其他ip正在執行 //可能是 N + empty //以上狀況都要終止執行 //參數設定可能已經由其他instance取代,因此便不再執行UpdateExeSetup(); StopTpeTimer(); StopNewTpeTimer(); result = false; } //執行超過八小時一樣強制結束 if (watch.Elapsed.TotalHours > 8) { watch.Stop(); StopTpeTimer(); StopNewTpeTimer(); UpdateExeSetup("N", ""); result = false; } return result; } //啟動臺北timer private void TPETimerStart() { tpeQueryTPETimer.Start(); tpeAvgSpeedTimer.Start(); } //啟動新北timer private void NewTPETimerStart() { newTpeQueryTPETimer.Start(); newTpeAvgSpeedTimer.Start(); } private void StopTpeTimer() { tpeQueryTPETimer.Stop(); tpeAvgSpeedTimer.Stop(); } private void StopNewTpeTimer() { newTpeQueryTPETimer.Stop(); newTpeAvgSpeedTimer.Stop(); } #endregion #region 檢查目前查詢進度method //取得臺北目前查詢完畢的資料筆數 private int GetTpeFinCountNow() { using (rehouseEntities db = new rehouseEntities()) { return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == tpeCityCode).Count(); } } //取得新北目前查詢完畢的資料筆數 private int GetNewTpeFinCountNow() { using (rehouseEntities db = new rehouseEntities()) { return db.pft23.Where(p => (p.devo_value != null || p.ground_price != null) && p.city_code == newTpeCityCode).Count(); } } #endregion #region 呼叫WCF查詢臺北市、新北市 //呼叫wcf查詢臺北 private void QueryTPEByService() { TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient(); using (rehouseEntities db = new rehouseEntities()) { var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == tpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount)); foreach (var p23 in pft23s) { sc.GetTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no); } } sc.Close(); tpeWCFCalling = false;//呼叫完畢 } //呼叫wcf查詢臺北 private void QueryNewTPEByService() { TPELandPublicValuePriceService.ServiceClient sc = new TPELandPublicValuePriceService.ServiceClient(); using (rehouseEntities db = new rehouseEntities()) { var pft23s = db.pft23.Where(p => p.devo_value == null && p.ground_price == null && p.city_code == newTpeCityCode).Take(Convert.ToInt16(Config.OnceTakeCount)); foreach (var p23 in pft23s) { sc.GetNewTPELandPublicValuePrice(p23.zip_code, p23.session_id, p23.area_no); } } sc.Close(); newTpeWCFCalling = false;//呼叫完畢 } #endregion } }
http://saltsourcecenter.blogspot.tw/2015/11/webservicewebservice.html
沒有留言:
張貼留言