check-api.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /// 每个小时检查下api接口及数据一致性
  2. const axios = require('axios');
  3. const { sendEmail } = require('./email')
  4. const { sendSms } = require('./sms')
  5. const SmsTemplate = require('./sms-templates');
  6. const onlineHost = 'app2.pcoloring.com';
  7. const offlineHost = 'color.jccytech.cn';
  8. const artLatestUri = 'napi/number/v9/list/art/content?column=latest';
  9. const jigsawLatestUri = 'napi/jigsaw/mobi/list/latest';
  10. const artPuzzleLatestUri = 'napi/puzzle/mobi/list/latest';
  11. async function checkArtLatest() {
  12. let onlineUrl = `https://${onlineHost}/${artLatestUri}`;
  13. let offlineUrl = `https://${offlineHost}/${artLatestUri}`;
  14. let onlineData, offlineData;
  15. try {
  16. let resp = await axios.get(onlineUrl);
  17. onlineData = resp.data;
  18. } catch (e) {
  19. console.error('Art线上latest数据请求出错, 请及时检查:', [e.message]);
  20. return {
  21. result: false,
  22. errcode: 100,
  23. title: 'Art线上latest数据请求出错, 请及时检查',
  24. sms: SmsTemplate.SMS_API_ERROR,
  25. data: [e.message],
  26. }
  27. }
  28. try {
  29. let resp = await axios.get(offlineUrl);
  30. offlineData = resp.data;
  31. } catch (e) {
  32. console.error('Art 线下latest数据请求出错, 请及时检查:', [e.message]);
  33. return {
  34. result: false,
  35. errcode: 100,
  36. title: 'Art 线下latest数据请求出错, 请及时检查',
  37. sms: SmsTemplate.SMS_API_ERROR,
  38. data: [e.message],
  39. }
  40. }
  41. // 检查数据是否一致: 看第一条即可
  42. if (!onlineData.data || onlineData.data.length <= 0) {
  43. return {
  44. result: false,
  45. errcode: 100,
  46. title: 'Art 线上latest数据有误, 请及时检查',
  47. sms: SmsTemplate.SMS_API_ERROR,
  48. data: ['latest数据为空'],
  49. }
  50. }
  51. if (!offlineData.data || offlineData.data.length <= 0) {
  52. return {
  53. result: false,
  54. errcode: 100,
  55. title: 'Art 线下latest数据有误, 请及时检查',
  56. sms: SmsTemplate.SMS_API_ERROR,
  57. data: ['latest数据为空'],
  58. }
  59. }
  60. if (onlineData.data[0]._id != offlineData.data[0]._id) {
  61. return {
  62. result: false,
  63. errcode: 100,
  64. title: 'Art latest 线上线下数据不一致, 请及时检查',
  65. sms: SmsTemplate.SMS_SYNC_ERROR,
  66. data: [onlineUrl, offlineUrl],
  67. }
  68. }
  69. return {
  70. result: true,
  71. errcode: 0,
  72. title: 'Art 服务恢复正常运行',
  73. sms: SmsTemplate.SMS_RESUME,
  74. data: ['Art 服务一切正常']
  75. }
  76. }
  77. async function checkJigsawLatest() {
  78. let onlineUrl = `https://${onlineHost}/${jigsawLatestUri}`;
  79. let offlineUrl = `https://${offlineHost}/${jigsawLatestUri}`;
  80. let onlineData, offlineData;
  81. try {
  82. let resp = await axios.get(onlineUrl);
  83. onlineData = resp.data;
  84. } catch (e) {
  85. console.error('Jigsaw 线上latest数据请求出错, 请及时检查:', e.message);
  86. return {
  87. result: false,
  88. errcode: 200,
  89. title: 'Jigsaw 线上latest数据请求出错, 请及时检查',
  90. sms: SmsTemplate.SMS_API_ERROR,
  91. data: [e.message],
  92. }
  93. }
  94. try {
  95. let resp = await axios.get(offlineUrl);
  96. offlineData = resp.data;
  97. } catch (e) {
  98. console.error('Jigsaw 线下latest数据请求出错, 请及时检查:', e.message);
  99. return {
  100. result: false,
  101. errcode: 200,
  102. title: 'Jigsaw 线下latest数据请求出错, 请及时检查',
  103. sms: SmsTemplate.SMS_API_ERROR,
  104. data: [e.message],
  105. }
  106. }
  107. // 检查数据是否一致: 看第一条即可
  108. if (!onlineData.data || onlineData.data.length <= 0) {
  109. return {
  110. result: false,
  111. errcode: 200,
  112. title: 'Jigsaw 线上latest数据有误, 请及时检查',
  113. sms: SmsTemplate.SMS_API_ERROR,
  114. data: ['latest数据为空'],
  115. }
  116. }
  117. if (!offlineData.data || offlineData.data.length <= 0) {
  118. return {
  119. result: false,
  120. errcode: 200,
  121. title: 'Jigsaw 线下latest数据有误, 请及时检查',
  122. sms: SmsTemplate.SMS_API_ERROR,
  123. data: ['latest数据为空'],
  124. }
  125. }
  126. if (onlineData.data[0]._id != offlineData.data[0]._id) {
  127. return {
  128. result: false,
  129. errcode: 200,
  130. title: 'Jigsaw latest 线上线下数据不一致, 请及时检查',
  131. sms: SmsTemplate.SMS_SYNC_ERROR,
  132. data: [onlineUrl, offlineUrl],
  133. }
  134. }
  135. return {
  136. result: true,
  137. errcode: 0,
  138. title: 'Jigsaw 服务恢复正常运行',
  139. sms: SmsTemplate.SMS_RESUME,
  140. data: ['Jigsaw 服务一切正常']
  141. }
  142. }
  143. async function checkArtPuzzleLatest() {
  144. let onlineUrl = `https://${onlineHost}/${artPuzzleLatestUri}`;
  145. let offlineUrl = `https://${offlineHost}/${artPuzzleLatestUri}`;
  146. let onlineData, offlineData;
  147. try {
  148. let resp = await axios.get(onlineUrl);
  149. onlineData = resp.data;
  150. } catch (e) {
  151. console.error('ArtPuzzle 线上latest数据请求出错, 请及时检查:', e.message);
  152. return {
  153. result: false,
  154. errcode: 300,
  155. title: 'ArtPuzzle 线上latest数据请求出错, 请及时检查',
  156. sms: SmsTemplate.SMS_API_ERROR,
  157. data: [e.message],
  158. }
  159. }
  160. try {
  161. let resp = await axios.get(offlineUrl);
  162. offlineData = resp.data;
  163. } catch (e) {
  164. console.error('ArtPuzzle 线下latest数据请求出错, 请及时检查:', e.message);
  165. return {
  166. result: false,
  167. errcode: 300,
  168. title: 'ArtPuzzle 线下latest数据请求出错, 请及时检查',
  169. sms: SmsTemplate.SMS_API_ERROR,
  170. data: [e.message],
  171. }
  172. }
  173. if (!onlineData.data || onlineData.data.length <= 0) {
  174. return {
  175. result: false,
  176. errcode: 300,
  177. title: 'ArtPuzzle 线上latest数据有误, 请及时检查',
  178. sms: SmsTemplate.SMS_API_ERROR,
  179. data: ['latest数据为空'],
  180. }
  181. }
  182. if (!offlineData.data || offlineData.data.length <= 0) {
  183. return {
  184. result: false,
  185. errcode: 300,
  186. title: 'ArtPuzzle 线下latest数据有误, 请及时检查',
  187. sms: SmsTemplate.SMS_API_ERROR,
  188. data: ['latest数据为空'],
  189. }
  190. }
  191. // 检查数据是否一致: 看第一条即可
  192. if (onlineData.data[0]._id != offlineData.data[0]._id) {
  193. return {
  194. result: false,
  195. errcode: 300,
  196. title: 'ArtPuzzle latest 线上线下数据不一致, 请及时检查',
  197. sms: SmsTemplate.SMS_SYNC_ERROR,
  198. data: [onlineUrl, offlineUrl],
  199. }
  200. }
  201. return {
  202. result: true,
  203. errcode: 0,
  204. title: 'Jigsaw 服务恢复正常运行',
  205. sms: SmsTemplate.SMS_RESUME,
  206. data: ['Jigsaw 服务一切正常']
  207. }
  208. }
  209. async function run(lastErrCode = 0) {
  210. console.log("check api...", new Date());
  211. try {
  212. let result = null;
  213. // 如果出现异常,连续检测3次才发送通知,减少误报,因为出现不少次因为网络原因一时半会请求不到数据就报警的情况
  214. for (let i = 0; i < 3; i++) {
  215. result = await checkArtLatest();
  216. console.log(result);
  217. if (!result.result) {
  218. console.warn("检查Art服务出现异常,一分钟后重试");
  219. await delay(60 * 1000);
  220. } else {
  221. console.warn("Art服务一切正常");
  222. break;
  223. }
  224. }
  225. if (!result.result) {
  226. console.error("连续3次检查Art服务异常,发送通知");
  227. sendEmail(result.title, result.data);
  228. sendSms(result.sms);
  229. console.log("5分钟后再试");
  230. setTimeout(run, 5 * 60 * 1000, result.errcode);
  231. return;
  232. } else {
  233. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  234. if (lastErrCode == 100) {
  235. sendEmail(result.title, result.data);
  236. sendSms(result.sms);
  237. }
  238. }
  239. for (let i = 0; i < 3; i++) {
  240. result = await checkJigsawLatest();
  241. console.log(result);
  242. if (!result.result) {
  243. console.warn("检查Jigsaw服务出现异常,一分钟后重试");
  244. await delay(60 * 1000);
  245. } else {
  246. console.warn("Jigsaw服务一切正常");
  247. break;
  248. }
  249. }
  250. if (!result.result) {
  251. console.error("连续3次检查Jigsaw服务异常,发送通知");
  252. sendEmail(result.title, result.data);
  253. sendSms(result.sms);
  254. console.log("5分钟后再试");
  255. setTimeout(run, 5 * 60 * 1000, result.errcode);
  256. return;
  257. } else {
  258. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  259. if (lastErrCode == 200) {
  260. sendEmail(result.title, result.data);
  261. sendSms(result.sms);
  262. }
  263. }
  264. for (let i = 0; i < 3; i++) {
  265. result = await checkArtPuzzleLatest();
  266. console.log(result);
  267. if (!result.result) {
  268. console.warn("检查ArtPuzzle服务出现异常,一分钟后重试");
  269. await delay(60 * 1000);
  270. } else {
  271. console.warn("ArtPuzzle服务一切正常");
  272. break;
  273. }
  274. }
  275. if (!result.result) {
  276. console.error("连续3次检查ArtPuzzle服务异常,发送通知");
  277. sendEmail(result.title, result.data);
  278. sendSms(result.sms);
  279. console.log("5分钟后再试");
  280. setTimeout(run, 5 * 60 * 1000, result.errcode);
  281. return;
  282. } else {
  283. // 如果上次时出错的情况, 那么属于服务恢复,发送恢复通知
  284. if (lastErrCode == 300) {
  285. sendEmail(result.title, result.data);
  286. sendSms(result.sms);
  287. }
  288. }
  289. } catch (err) {
  290. console.error(err.stack);
  291. }
  292. }
  293. function delay(ms) {
  294. return new Promise(done => setTimeout(done, ms));
  295. }
  296. module.exports = { run }
  297. if (require.main == module) {
  298. run();
  299. }