npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@wecity/mp-fe-gateway

v1.0.4

Published

小程序前端网关,提供给微信小程序的前端限流 SDK,通过限流配置对 wx.request/wx.cloud.callContainer 进行前置拦截,从而对后端网关进行特殊时期的保护。

Downloads

1

Readme

前端网关

提供给微信小程序的前端缓存/限流 SDK,通过重写 wx.request/wx.cloud.callContainer ,对请求进行前置和后置处理,从而对后端网关进行特殊时期的保护。

  1. 名词解释
缓存:对接口返回的内容(data、header、statusCode)进行缓存。

常用场景:在一定时间内不会变化的数据即可缓存,降低接口压力

主动限流:有多大比例用户可以访问到接口。

常用场景:非关键接口在流量高峰时直接不请求后端接口、抢购场景

被动限流:根据接口返回的http状态码或者业务错误码,冻结用户一段时间不能访问接口(发出请求的接口会被丢弃)。

常用场景:提前根据后端状态配置好熔断策略,不需要临时配置

快速上手

1、npm 下载

npm install @wecity/mp-fe-gateway --save-dev

2、初始化

在 app.js 里初始化

// 引入rum
// 备注:sdk要在aegis之后miniprogram-api-promise(如果有使用该库包装wx)之前
import Aegis from 'aegis-mp-sdk'
const aegis = new Aegis({
  id: 'xxxx',
  // 上报 id
  reportApiSpeed: false,
  // 接口测速
  spa: false, // spa 应用页面跳转的时候开启 pv 计算
});
const mpRateLimit = require('@wecity/mp-fe-gateway/rateLimit.min');
// 如需使用定时清理缓存需单独引入`cronCachePlugin`
const cronCachePlugin = require('@wecity/mp-fe-gateway/cronCachePlugin.min');
// 初始化sdk
mpRateLimit.init({
  url: '<%= YOUR CONFIG URL %>', // get请求策略配置信息的地址
  enable: true, // 是否关闭sdk,关闭后不会拉取配置信息,即缓存/限流等功能都不会生效,默认开启(true),开启:true,关闭:false
  debugger: true, //  是否开启控制台日志,默认关闭(false),这样在console控制台可以看到打印的信息,开启:true,关闭:false
  plugins: [cronCachePlugin], // 选择希望支持的插件
  // 全局处理函数, 写入缓存/命中缓存/被动限流/主动限流,这里可以用来做上报逻辑
  globalHandler: function (type, params) {
    switch (type) {
      // 写入缓存
      case mpRateLimit.enum.writeCache:
      // 命中缓存
      case mpRateLimit.enum.hitCache:
        // request 请求配置
        // response 返回的内容
        // cacheStorageKey 缓存Key
        // cacheTime 缓存有效时间
        const { request, cacheStorageKey = '', cacheTime } = params;
        const tempArr = cacheStorageKey.split('|');
        aegis.reportEvent({
          name: type,
          ext1: tempArr[0],
          ext2: tempArr[1],
        });
        break;
      // 被动限流
      case mpRateLimit.enum.passiveLimit:
        /*
          apiUrl:接口地址
          limitData:限流信息
              hitTime: 命中限流时间戳
              coolingTime: 冷却时间(秒)
              limitConfig: 限流配置
                 statusCode/errCode: 状态码/错误码
                 effect: 影响范围1:访问当前接口被限流,2:访问上次限流的同域名接口会被限流,不填或者填写不符合规范,默认1
        */
        const { apiUrl, limitData } = params;
        aegis.reportEvent({
          name: type,
          ext1: apiUrl,
          ext2: limitData.coolingTime,
          ext3: limitData.limitConfig.statusCode || limitData.limitConfig.errCode,
        });
        break;
      // 主动限流
      case mpRateLimit.enum.activeLimit:
        /*
         apiUrl:接口地址
         access:是否限流,false:命中限流 true:正常通行
       */
        aegis.reportEvent({
          name: type,
          ext1: params.apiUrl,
          ext2: params.access ? 'success' : 'fail',
        });
        break;
    }
  },
})
App({
  onLaunch() {
    // 包装一个自定义的全局request
    // 后续的接口请求都通过这个自定义的request
    wx.myRequest = function(options) {
      return wx.request({
        ...options,
        success: (res) => {
          // 返回了limitData({"hitTime":1651134682386,"coolingTime":10,"statusCode":503,limitType:1}),说明触发了被动限流
          // hitTime:触发时的时间戳,coolingTime:总的冷却时间(秒),被动限流才有该字段
          // remainTime:剩余多久解封(毫秒) statusCode:触发时的状态码,被动限流才有该字段
          // limitType: 1,主动限流 2、被动限流
          if (res.limitData) {
            // 被动限流处理
            if (res.limitData.limitType === 2) {
              wx.showModal({
                title: '提示',
                content: `当前访问人数太多,还需要冷却${(res.limitData.remainTime/1000).toFixed(1)}秒,请稍候再试`,
                showCancel: false,
                confirmText: '关闭',
              });
            }
          }
          options.success(res);
        },
        fail: (res) => {
          if (res.limitData) {
            // 主动限流处理
            wx.showModal({
              title: '提示',
              content: `主动限流`,
              showCancel: false,
              confirmText: '关闭',
            });
          }
          options.fail(res);
        },
      });
    }
  }
})

// 页面中使用
Page({
  fetchUserList() {
    wx.myRequest({ url: '/api/fetchUserList' })
  }
})

API

mpRateLimit.init({url,enable,debugger,globalHandler})

限流 SDK 的初始化

入参说明

| 参数 | 简介 | 类型 | 备注 | | --- | --- | --- | --- | | url | get请求策略配置信息的地址 | string |地址返回的配置信息请看下面的策略配置| | urlNeedTimestamp | get请求策略配置信息的地址是否需要加上时间戳(url?t=Date.now()),默认false,是:true,否:false | bolean || | enable | 是否关闭sdk,关闭后不会拉取配置信息,即缓存/限流等功能都不会生效,默认开启(true),开启:true,关闭:false | bolean | | debugger | 是否开启限流日志,默认关闭(false),这样在console控制台可以看到打印的信息,开启:true,关闭:false | bolean |验证后建议关闭| | globalHandler | 全局自定义处理函数,可以做上报等功能 | function (type, params) ||

策略配置:

{
  // 是否开启主动限流, 是:1 否:0
  "openActiveLimit": 1,
  // 是否开启被动限流(当接口返回某些状态码/错误码时,自动触发被动限流), 是:1 否:0
  "openPassiveLimit": 1,

  // 插件配置
  "plugins": {
    // 实时与本地日志插件配置
    "ReportErrorLog": {
      // 是否开启小程序实时与本地日志上报,是:1 否:0
      // 关闭后实时和本地日志均不会写入上报
      "open": 1,

      // 当业务状态码不符合条件时上报
      // 影响范围:仅符合 bisDomains(业务域名白名单) 的请求才上报
      // 示例解释:!(response.data.errocde == 0 || response.data.code == '200') 时上报
      "errCodes": [
        {
          "codeKey": "errcode",
          "errCode": 0
        },
        {
          "codeKey": "code",
          "errCode": "200"
        }
      ],
      // 业务域名白名单
      "bisDomains": ["xxx.yy.com"],

      // 当存在 HTTP 状态码不符合条件时上报
      // 影响范围:所有域名的请求
      // 示例解释:[200].indexOf(response.statusCode) === -1 时上报
      "httpCodes": [
        {
          "statusCode": 200
        }
      ]
    }
  }

  // 多久后重新获取这个限流文件,单位秒
  "refreshConfigTime": 60, // 60秒后
  // 接口列表
  "apiList": [
    {
      // 路径,可以带域名
      // 同时支持 /path/** 方式,
      // 可匹配到/path/isLoginV1 或者/path/isLoginV2, 
      // ** 只能匹配到非/内的路径字符,无法匹配到/
      "path": "/path/isLoginV2",
      // 主动限流配置
      "activeLimit": {
        // 初始百分比
        "percent": 50,
        // 请求接口失败后,下次提升10%的成功率(接口请求成功后,成功率重置回原来初始百分比),默认是0
        "increaseNum": 10,
      },
      // 被动限流配置
      "passiveLimit": {
        // 根据接口返回的状态码进行被动限流
        "httpCodes": [
          // 下面配置解释(配置了当前接口限流后,后续请求的所有接口都会限流):
          // wx.request访问isLoginV2接口,回调函数(success)因为503状态码返回了限流信息limitData:{"statusCode":503,"limitData":{"hitTime":1651134682386,"remainTime":3000,"hitTime":1651134682386,"coolingTime":10,"statusCode":503}},
          // 那么10秒内,通过wx.request访问A/B/C接口,回调函数(fail)会直接返回限流信息limitData(刚刚isLoginV2接口返回的内容):{"statusCode":503,"limitData":{"hitTime":1651134682386,"remainTime":3000,"coolingTime":10,"statusCode":503}}
          // 业务方根据limitData去做定制处理
          {
            "statusCode": 503, // 必填:状态码
            "effect": 2, // 影响范围1:访问当前接口被限流,2:访问上次限流的同域名接口会被限流,不填或者填写不符合规范,默认1
            "coolingTime": 10, // 必填:秒,限流冷却时间,在这段时间发起的请求不会到达后端,不填或者填写不符合规范,默认6秒
          }
        ],
        // 根据接口body返回的errcode进行被动限流
        "errCodes": [
          {
            "codeKey": "errcode", // 必填:错误码的键 errcode code?
            "errCode": 10002, // 必填:body返回的错误码
            "effect": 2, // 必填:影响范围1:访问当前接口被限流,2:访问上次限流的同域名接口会被限流
            "coolingTime": 10, // 必填:秒,限流冷却时间,在这段时间发起的请求不会到达后端
          }
        ],
      },
      // 缓存配置   resp.statusCode / get(resp.data, codeKey)
      "cache": {
        // 必填:该请求缓存时间,单位为秒, 大于0的数字
        "cacheTime": 60,
        "cronCacheTime": '* 0 * * *', // 每日0点失效
        // 缓存参数值,会根据该值确定缓存是否生效
        // 必填:提供的参数为 query/data/header,可以通过模版进行组合
        "cacheKey": "${header.sid}-${data['x-table']}-${data.params[0]['x-table']}-${query.id}",

        // 必填:状态码
        "statusCode": 200, // 必填:http response 状态码
        "codeKey": "errcode", // 必填:http response data 业务状态码字段
        "errCode": 0 // // 必填:http response data 业务状态码
      }
    }
  ]
}

mpRateLimit.safeFetchCfg(apiUrl)

获取限流配置,返回promise对象

使用场景:利用sdk的配置下发能力,把业务配置放到限流配置里,实现业务逻辑

apiUrl传入则获取对应api的配置规则,不传则返回整个json配置文件
// 读取配置文件
rateLimit.safeFetchCfg("/path/isLoginV2").then(res=> {
  //会返回配置文件apiList中/path/isLoginV2的配置
console.log(res)
}).catch(()=> {})

mpRateLimit.clearCache()

清除所有rateLimit设置的缓存数据, 可以使用在不同用户登陆时 又没有不同用户唯一标识情况下数据错乱时,做清除用户处理。

mpRateLimit.checkCacheByDate("2022-05-05 12:30:45")

根据服务器时间更正 cache是否依然在缓存有效期,如果不在则清理

mpRateLimit.clearCacheByUrlPath(urlPath)

清理urlPath 匹配成功的所有缓存内容,使用正则表达式匹配 例如

// 如果json里 apiList 里 path 配置为 /api/fetchUserList/get /api/fetchUserList/put  
mpRateLimit.clearCacheByUrlPath('/api/fetchUserList/get') // 清理路径/api/fetchUserList/get的缓存
mpRateLimit.clearCacheByUrlPath('/api/fetchUserList/([a-z]+)') // 清理/api/fetchUserList/get, /api/fetchUserList/put的缓存 

mpRateLimit.clearCacheByUrlPath('/api/fetchUserList/get', {
  cacheKeyData: {
    header: {
      sid: '1212',
    },
    query: {
      qid: '222',
    },
    data: {
      did: '333'
    }
  }
}) // 精准清理 具体某一条的 缓存

内置插件

点击查看插件详细介绍

1. 实时与本地日志上报插件

2. Cron 格式缓存时间插件

其他说明

  1. 因限流配置为异步拉取,首次生效期可能会有一定的延迟,取决于限流配置拉取回来的时间。
  2. 用户登录/退出建议清理下缓存。另外根据具体业务情况清理缓存。
  3. 当cdn挂了,使用上次请求回来的配置规则。
  4. 改小cacheTime会重新加载数据,不会走缓存;如果不想走缓存,把cacheTime设置为0。