degrade-ssr-task.js 2.38 KB
const schedule = require('node-schedule');
const Operation = require('../logger/operation');
const _ = require('lodash');
const {DegradeServer} = require('../models');
const setter = require('../zookeeper/setter');
const {client} = require('../../lib/redis');

module.exports = (koaApp) => {
  schedule.scheduleJob('* * * * * *', async () => {
    const appsData = await client.getAsync('degradeSSRKeys');

    const apps = JSON.parse(appsData || '[]');

    let server = await DegradeServer.findOne({
        type: 'qcloud'
    });
    

    _.forEach(apps, async app => {
      try {
        const zkDegradePath = `/wap/webapp/${app}-degrade`;
        const degradeKey = `${app}:degradessr`;
        const isDegradeKey = `${degradeKey}:isdegrade`;
        const [degradeJson, isDegrade] = await Promise.all([client.getAsync(degradeKey), client.getAsync(isDegradeKey)]);
        const zkIsDegrade = _.get(koaApp, `locals.wap.webapp.${app}-degrade`, false);

        const degrades = JSON.parse(degradeJson || '[]');


        if (!isDegrade && zkIsDegrade) { // isdegrade的redis key已过期,且没有触发限制刷新key过期时间,则降级开关关闭
          setter(`${server.ip}:${server.port}`, zkDegradePath, 'false');
          console.log('SSR降级恢复')
          Operation.action({
            _id: 0,
            username: 'ssr-degrade'
          }, 'SSR降级恢复', '降级恢复' , {app});
        }

        _.forEach(degrades, async item => {
          const key = `${degradeKey}:${item.time}`;
          const result = await client.getAsync(key);

          if (item.time * item.tick < +result) { // 大于qps限制,降级
            const degradeData = {
              ...item,
              maxTick: +result
            };
            
            console.log('触发降级策略')
            Operation.action({
              _id: 0,
              username: 'ssr-degrade'
            }, 'SSR降级', '触发降级策略' ,`${isDegradeKey},${JSON.stringify(degradeData)}`);
            client.setexAsync(isDegradeKey, item.delay * 60, JSON.stringify(degradeData));
            client.delAsync(key);
            setter(`${server.ip}:${server.port}`, zkDegradePath, 'true');
          }
        });
        return new Promise(resolve => {
          setTimeout(() => {
            resolve();
          }, 1000);
        });
      } catch (error) {
        console.log(error);
      }
    });
  });
}