Authored by 周少峰

asynchronous request must

@@ -5,6 +5,7 @@ const logger = global.yoho.logger; @@ -5,6 +5,7 @@ const logger = global.yoho.logger;
5 const ip = require('./rules/ip-list'); 5 const ip = require('./rules/ip-list');
6 const userAgent = require('./rules/useragent'); 6 const userAgent = require('./rules/useragent');
7 const qpsLimiter = require('./rules/qps-limit'); 7 const qpsLimiter = require('./rules/qps-limit');
  8 +const asynchronous = require('./rules/asynchronous');
8 9
9 // const fakerLimiter = require('./rules/faker-limit'); 10 // const fakerLimiter = require('./rules/faker-limit');
10 const captchaPolicy = require('./policies/captcha'); 11 const captchaPolicy = require('./policies/captcha');
@@ -53,7 +54,8 @@ module.exports = (req, res, next) => { @@ -53,7 +54,8 @@ module.exports = (req, res, next) => {
53 Promise.all([ 54 Promise.all([
54 limiter(userAgent, captchaPolicy, context), 55 limiter(userAgent, captchaPolicy, context),
55 limiter(ip, captchaPolicy, context), 56 limiter(ip, captchaPolicy, context),
56 - limiter(qpsLimiter, captchaPolicy, context) 57 + limiter(qpsLimiter, captchaPolicy, context),
  58 + limiter(asynchronous, captchaPolicy, context)
57 59
58 // limiter(fakerLimiter, reporterPolicy, context) 60 // limiter(fakerLimiter, reporterPolicy, context)
59 ]).then((results) => { 61 ]).then((results) => {
  1 +'use strict';
  2 +
  3 +const cache = global.yoho.cache.master;
  4 +const _ = require('lodash');
  5 +const logger = global.yoho.logger;
  6 +
  7 +
  8 +const ASYNCHRONOUSPAGES = {
  9 + '/product/index/isFavoriteShop': 1,
  10 + '/common/suggestfeedback': 1,
  11 + '/product/detail/hotarea': 1
  12 +};
  13 +
  14 +function isNormalSpider(userAgent) {
  15 + let normalReg = /(spider)|(bot.html)/i;
  16 +
  17 + if (normalReg.test(userAgent)) {
  18 + return true;
  19 + } else {
  20 + return false;
  21 + }
  22 +
  23 +}
  24 +
  25 +module.exports = (limiter, policy) => {
  26 + const ua = limiter.req.header('User-Agent');
  27 + const synchronizeKey = `pc:limiter:synchronize:${limiter.remoteIp}`; // 同步
  28 + const asynchronousKey = `pc:limiter:asynchronous:${limiter.remoteIp}`; // 异步
  29 + const spiderKey = `pc:limiter:spider:${limiter.remoteIp}`; // 异步
  30 +
  31 + // 正常蜘蛛直接过
  32 + if (isNormalSpider(ua)) {
  33 + return Promise.resolve(true);
  34 + }
  35 +
  36 +
  37 + const req = limiter.req,
  38 + res = limiter.res;
  39 +
  40 + res.on('render', function() {
  41 + cache.incrAsync(synchronizeKey, 1).catch(e=>console.log(e)); // eslint-disable-line
  42 + });
  43 +
  44 + return cache.getMultiAsync([synchronizeKey, asynchronousKey, spiderKey]).then((results) => {
  45 + logger.debug(results);
  46 +
  47 + if (results[spiderKey]) {
  48 + return Promise.resolve(policy);
  49 + }
  50 +
  51 + // 默认数据设置
  52 + if (!results[synchronizeKey] && !_.isNumber(results[synchronizeKey])) {
  53 + cache.setAsync(synchronizeKey, 1, 600); // 设置key,1m失效
  54 + }
  55 +
  56 + // 默认数据设置
  57 + if (ASYNCHRONOUSPAGES[req.path] > 0) {
  58 + cache.setAsync(asynchronousKey, 1, 600); // 设置key,1m失效
  59 + }
  60 +
  61 + if (results[synchronizeKey] > 10 && !results[asynchronousKey]) {
  62 + cache.setAsync(spiderKey, 1, 60*60*24);
  63 + return Promise.reject(policy);
  64 + }
  65 +
  66 + });
  67 +};