mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
支持限流持续时间
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# changelog
|
||||
|
||||
## 2.4.0
|
||||
|
||||
- 支持限流持续时间(每n秒允许m个请求,需要执行`sop-2.4.0.sql`升级脚本)
|
||||
|
||||
## 2.3.2
|
||||
|
||||
- 支持spring cloud gateway下restful接口调用
|
||||
|
1
sop-2.4.0.sql
Normal file
1
sop-2.4.0.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE `sop`.`config_limit` ADD COLUMN `duration_seconds` INT NOT NULL DEFAULT 1 COMMENT '限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效)' AFTER `exec_count_per_second`;
|
@@ -39,6 +39,12 @@ public class LimitNewAddParam {
|
||||
@ApiDocField(description = "每秒可处理请求数")
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效) */
|
||||
@ApiDocField(description = "限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效")
|
||||
@NotNull(message = "durationSeconds不能为空")
|
||||
@Min(value = 1, message = "durationSeconds最小是1")
|
||||
private Integer durationSeconds;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
@ApiDocField(description = "返回的错误码")
|
||||
@Length(max = 64, message = "limitCode长度不能超过64")
|
||||
|
@@ -44,6 +44,12 @@ public class LimitNewUpdateParam {
|
||||
@ApiDocField(description = "每秒可处理请求数")
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效) */
|
||||
@ApiDocField(description = "限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效")
|
||||
@NotNull(message = "durationSeconds不能为空")
|
||||
@Min(value = 1, message = "durationSeconds最小是1")
|
||||
private Integer durationSeconds;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
@ApiDocField(description = "返回的错误码")
|
||||
@Length(max = 64, message = "limitCode长度不能超过64")
|
||||
|
@@ -27,6 +27,9 @@ public class ConfigLimitDto {
|
||||
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效), 数据库字段:durationSeconds */
|
||||
private Integer durationSeconds;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
private String limitCode;
|
||||
|
||||
|
@@ -43,6 +43,9 @@ public class ConfigLimit {
|
||||
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效), 数据库字段:durationSeconds */
|
||||
private Integer durationSeconds;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
private String limitCode;
|
||||
|
||||
@@ -66,4 +69,5 @@ public class ConfigLimit {
|
||||
|
||||
/** 数据库字段:gmt_modified */
|
||||
private Date gmtModified;
|
||||
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.c6dfb7ee.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],d=0,l=[];d<a.length;d++)c=a[d],u[c]&&l.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);h&&h(n);while(l.length)l.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-09380dd0":"6637f3dc","chunk-25908fca":"05d6b15b","chunk-2c1f2e8f":"f092c0a0","chunk-2d2085ef":"91d75f3c","chunk-2d221c34":"20057287","chunk-4de1c2b6":"e74e3d03","chunk-6f78c9fe":"3ac83b41","chunk-73b2dcec":"05b5ee28","chunk-9b31c83a":"e60adb43","chunk-9f479afe":"0d0ed757","chunk-c3ce42fe":"9517b588"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-09380dd0":1,"chunk-25908fca":1,"chunk-2c1f2e8f":1,"chunk-4de1c2b6":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1,"chunk-c3ce42fe":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-09380dd0":"390fcb96","chunk-25908fca":"89ab33e8","chunk-2c1f2e8f":"0314067f","chunk-2d2085ef":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-4de1c2b6":"a37cd815","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b","chunk-9f479afe":"31d6cfe0","chunk-c3ce42fe":"6b789903"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],d=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(d===r||d===u))return n()}var l=document.getElementsByTagName("style");for(a=0;a<l.length;a++){i=l[a],d=i.getAttribute("data-href");if(d===r||d===u)return n()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=n,h.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),t(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,d=document.createElement("script");d.charset="utf-8",d.timeout=120,f.nc&&d.setAttribute("nonce",f.nc),d.src=a(e),i=function(n){d.onerror=d.onload=null,clearTimeout(l);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var l=setTimeout(function(){i({type:"timeout",target:d})},12e4);d.onerror=d.onload=i,document.head.appendChild(d)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],d=i.push.bind(i);i.push=n,i=i.slice();for(var l=0;l<i.length;l++)n(i[l]);var h=d;t()})([]);</script><script src=static/js/chunk-elementUI.298ac98c.js></script><script src=static/js/chunk-libs.75deb05f.js></script><script src=static/js/app.eb1d37b5.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>SOP Admin</title><link href=static/css/chunk-elementUI.81cf475c.css rel=stylesheet><link href=static/css/chunk-libs.3dfb7769.css rel=stylesheet><link href=static/css/app.c6dfb7ee.css rel=stylesheet></head><body><noscript><strong>We're sorry but SOP Admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script>(function(e){function n(n){for(var r,c,a=n[0],f=n[1],i=n[2],d=0,l=[];d<a.length;d++)c=a[d],u[c]&&l.push(u[c][0]),u[c]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);h&&h(n);while(l.length)l.shift()();return o.push.apply(o,i||[]),t()}function t(){for(var e,n=0;n<o.length;n++){for(var t=o[n],r=!0,c=1;c<t.length;c++){var a=t[c];0!==u[a]&&(r=!1)}r&&(o.splice(n--,1),e=f(f.s=t[0]))}return e}var r={},c={runtime:0},u={runtime:0},o=[];function a(e){return f.p+"static/js/"+({}[e]||e)+"."+{"chunk-0faf9ba2":"88458f58","chunk-25908fca":"05d6b15b","chunk-2c1f2e8f":"f092c0a0","chunk-2d2085ef":"91d75f3c","chunk-2d221c34":"20057287","chunk-4de1c2b6":"e74e3d03","chunk-6f78c9fe":"3ac83b41","chunk-73b2dcec":"05b5ee28","chunk-9b31c83a":"e60adb43","chunk-9f479afe":"0d0ed757","chunk-c3ce42fe":"9517b588"}[e]+".js"}function f(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var n=[],t={"chunk-0faf9ba2":1,"chunk-25908fca":1,"chunk-2c1f2e8f":1,"chunk-4de1c2b6":1,"chunk-73b2dcec":1,"chunk-9b31c83a":1,"chunk-c3ce42fe":1};c[e]?n.push(c[e]):0!==c[e]&&t[e]&&n.push(c[e]=new Promise(function(n,t){for(var r="static/css/"+({}[e]||e)+"."+{"chunk-0faf9ba2":"ed1510dd","chunk-25908fca":"89ab33e8","chunk-2c1f2e8f":"0314067f","chunk-2d2085ef":"31d6cfe0","chunk-2d221c34":"31d6cfe0","chunk-4de1c2b6":"a37cd815","chunk-6f78c9fe":"31d6cfe0","chunk-73b2dcec":"99cf6327","chunk-9b31c83a":"3b12267b","chunk-9f479afe":"31d6cfe0","chunk-c3ce42fe":"6b789903"}[e]+".css",u=f.p+r,o=document.getElementsByTagName("link"),a=0;a<o.length;a++){var i=o[a],d=i.getAttribute("data-href")||i.getAttribute("href");if("stylesheet"===i.rel&&(d===r||d===u))return n()}var l=document.getElementsByTagName("style");for(a=0;a<l.length;a++){i=l[a],d=i.getAttribute("data-href");if(d===r||d===u)return n()}var h=document.createElement("link");h.rel="stylesheet",h.type="text/css",h.onload=n,h.onerror=function(n){var r=n&&n.target&&n.target.src||u,o=new Error("Loading CSS chunk "+e+" failed.\n("+r+")");o.code="CSS_CHUNK_LOAD_FAILED",o.request=r,delete c[e],h.parentNode.removeChild(h),t(o)},h.href=u;var s=document.getElementsByTagName("head")[0];s.appendChild(h)}).then(function(){c[e]=0}));var r=u[e];if(0!==r)if(r)n.push(r[2]);else{var o=new Promise(function(n,t){r=u[e]=[n,t]});n.push(r[2]=o);var i,d=document.createElement("script");d.charset="utf-8",d.timeout=120,f.nc&&d.setAttribute("nonce",f.nc),d.src=a(e),i=function(n){d.onerror=d.onload=null,clearTimeout(l);var t=u[e];if(0!==t){if(t){var r=n&&("load"===n.type?"missing":n.type),c=n&&n.target&&n.target.src,o=new Error("Loading chunk "+e+" failed.\n("+r+": "+c+")");o.type=r,o.request=c,t[1](o)}u[e]=void 0}};var l=setTimeout(function(){i({type:"timeout",target:d})},12e4);d.onerror=d.onload=i,document.head.appendChild(d)}return Promise.all(n)},f.m=e,f.c=r,f.d=function(e,n,t){f.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:t})},f.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,n){if(1&n&&(e=f(e)),8&n)return e;if(4&n&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var r in e)f.d(t,r,function(n){return e[n]}.bind(null,r));return t},f.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return f.d(n,"a",n),n},f.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},f.p="",f.oe=function(e){throw console.error(e),e};var i=window["webpackJsonp"]=window["webpackJsonp"]||[],d=i.push.bind(i);i.push=n,i=i.slice();for(var l=0;l<i.length;l++)n(i[l]);var h=d;t()})([]);</script><script src=static/js/chunk-elementUI.298ac98c.js></script><script src=static/js/chunk-libs.75deb05f.js></script><script src=static/js/app.f05d6d01.js></script></body></html>
|
@@ -1 +1 @@
|
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-0fad0a08]{cursor:pointer;margin-left:10px}
|
||||
.custom-tree-node{-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;font-size:14px;padding-right:8px}.el-input.is-disabled .el-input__inner,.el-radio__input.is-disabled+span.el-radio__label{color:#909399}.limit-tip[data-v-9527c228]{cursor:pointer;margin-left:10px}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -206,8 +206,9 @@
|
||||
<i class="el-icon-question limit-tip"></i>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isWindowType()" label="每秒可处理请求数" prop="execCountPerSecond" :rules="isWindowType() ? rulesLimit.execCountPerSecond : []">
|
||||
<el-input-number v-model="limitDialogFormData.execCountPerSecond" controls-position="right" :min="1" />
|
||||
<el-form-item v-show="isWindowType()" label="请求数" prop="execCountPerSecond" :rules="isWindowType() ? rulesLimit.execCountPerSecond : []">
|
||||
每 <el-input-number v-model="limitDialogFormData.durationSeconds" controls-position="right" :min="1" /> 秒可处理
|
||||
<el-input-number v-model="limitDialogFormData.execCountPerSecond" controls-position="right" :min="1" /> 个请求
|
||||
</el-form-item>
|
||||
<el-form-item v-show="isWindowType()" label="错误码" prop="limitCode" :rules="isWindowType() ? rulesLimit.limitCode : []">
|
||||
<el-input v-model="limitDialogFormData.limitCode" />
|
||||
@@ -275,6 +276,7 @@ export default {
|
||||
limitIp: '',
|
||||
limitKey: '',
|
||||
execCountPerSecond: 5,
|
||||
durationSeconds: 1,
|
||||
limitCode: '',
|
||||
limitMsg: '',
|
||||
tokenBucketCount: 5,
|
||||
@@ -438,15 +440,14 @@ export default {
|
||||
this.limitDialogFormData.limitStatus = 0
|
||||
},
|
||||
infoRender: function(row) {
|
||||
const html = []
|
||||
if (row.limitType === 1) {
|
||||
html.push('每秒可处理请求数:' + row.execCountPerSecond)
|
||||
html.push('<br>subCode:' + row.limitCode)
|
||||
html.push('<br>subMsg:' + row.limitMsg)
|
||||
const durationSeconds = row.durationSeconds
|
||||
return `每 ${durationSeconds} 秒可处理 ${row.execCountPerSecond} 个请求
|
||||
<br>subCode:${row.limitCode}
|
||||
<br>subMsg:${row.limitMsg}`
|
||||
} else if (row.limitType === 2) {
|
||||
html.push('令牌桶容量:' + row.tokenBucketCount)
|
||||
return `令牌桶容量:${row.tokenBucketCount}`
|
||||
}
|
||||
return html.join('')
|
||||
},
|
||||
onLimitDialogSave: function() {
|
||||
this.$refs['limitDialogForm'].validate((valid) => {
|
||||
|
@@ -43,6 +43,9 @@ public class ConfigLimitDto {
|
||||
/** 每秒可处理请求数, 数据库字段:exec_count_per_second */
|
||||
private Integer execCountPerSecond;
|
||||
|
||||
/** 限流过期时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效), 数据库字段:durationSeconds */
|
||||
private Integer durationSeconds;
|
||||
|
||||
/** 返回的错误码, 数据库字段:limit_code */
|
||||
private String limitCode;
|
||||
|
||||
@@ -66,16 +69,42 @@ public class ConfigLimitDto {
|
||||
|
||||
|
||||
/**
|
||||
* 漏桶计数器
|
||||
* 窗口计数器
|
||||
*/
|
||||
private LoadingCache<Long, AtomicLong> counter = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(2, TimeUnit.SECONDS)
|
||||
private volatile LoadingCache<Long, AtomicLong> counter;
|
||||
|
||||
/**
|
||||
* 获取持续时间,1秒内限制请求,则duration设置2
|
||||
*
|
||||
* @return 返回缓存保存的值。
|
||||
*/
|
||||
public int fetchDuration() {
|
||||
Integer durationSeconds = this.durationSeconds;
|
||||
if (durationSeconds == null || durationSeconds < 1) {
|
||||
durationSeconds = 1;
|
||||
}
|
||||
// 1秒内限制请求,则duration设置2
|
||||
return durationSeconds + 1;
|
||||
}
|
||||
|
||||
public LoadingCache<Long, AtomicLong> getCounter() {
|
||||
if (counter == null) {
|
||||
synchronized (this) {
|
||||
if (counter == null) {
|
||||
int duration = fetchDuration();
|
||||
counter = CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(duration, TimeUnit.SECONDS)
|
||||
.build(new CacheLoader<Long, AtomicLong>() {
|
||||
@Override
|
||||
public AtomicLong load(Long seconds) throws Exception {
|
||||
return new AtomicLong(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 令牌桶
|
||||
|
@@ -50,7 +50,7 @@ public class RedisLimitManager extends DefaultLimitManager {
|
||||
public boolean acquire(ConfigLimitDto routeConfig) {
|
||||
String key = "sop:lmt:" + routeConfig.getRouteId();
|
||||
int limitCount = routeConfig.getExecCountPerSecond();
|
||||
|
||||
int duration = routeConfig.fetchDuration();
|
||||
Object result = redisTemplate.execute(
|
||||
new RedisScript<Long>() {
|
||||
@Override
|
||||
@@ -71,7 +71,9 @@ public class RedisLimitManager extends DefaultLimitManager {
|
||||
// KEYS[1] key
|
||||
Collections.singletonList(key),
|
||||
// ARGV[1] limit
|
||||
String.valueOf(limitCount)
|
||||
String.valueOf(limitCount),
|
||||
// ARGV[2] expire
|
||||
String.valueOf(duration)
|
||||
);
|
||||
return REDIS_SUCCESS.equals(result);
|
||||
}
|
||||
|
@@ -3,8 +3,8 @@ local limit = tonumber(ARGV[1]) --限流大小
|
||||
local current = tonumber(redis.call("get", key)) or 0
|
||||
if current + 1 > limit then --如果超出限流大小
|
||||
return 0
|
||||
else --请求数+1,并设置2秒过期
|
||||
else --请求数+1,并设置n秒过期
|
||||
redis.call("INCRBY", key, "1")
|
||||
redis.call("expire", key,"2")
|
||||
redis.call("expire", key, ARGV[2])
|
||||
return 1
|
||||
end
|
@@ -1,6 +1,7 @@
|
||||
package com.gitee.sop.test;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.gitee.sop.test.alipay.AlipaySignature;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -34,8 +35,10 @@ public class LimitDemoPostTest extends TestBase {
|
||||
try {
|
||||
countDownLatch.await(); // 等在这里,执行countDownLatch.countDown();集体触发
|
||||
// 业务方法
|
||||
doBusiness(Thread.currentThread().getName());
|
||||
boolean result = doBusiness(Thread.currentThread().getName());
|
||||
if (result) {
|
||||
success.incrementAndGet();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} finally {
|
||||
count.countDown();
|
||||
@@ -46,10 +49,11 @@ public class LimitDemoPostTest extends TestBase {
|
||||
countDownLatch.countDown();
|
||||
count.await();
|
||||
System.out.println("成功次数:" + success);
|
||||
|
||||
}
|
||||
|
||||
// 这个请求会路由到story服务
|
||||
public void doBusiness(String threadName) throws Exception {
|
||||
public boolean doBusiness(String threadName) throws Exception {
|
||||
|
||||
// 公共请求参数
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
@@ -75,6 +79,8 @@ public class LimitDemoPostTest extends TestBase {
|
||||
|
||||
String responseData = post(url, params);// 发送请求
|
||||
System.out.println(responseData);
|
||||
JSONObject jsonObject = JSON.parseObject(responseData).getJSONObject("alipay_story_get_response");
|
||||
return "10000".equals(jsonObject.getString("code"));
|
||||
}
|
||||
|
||||
}
|
||||
|
1
sop.sql
1
sop.sql
@@ -95,6 +95,7 @@ CREATE TABLE `config_limit` (
|
||||
`service_id` varchar(64) NOT NULL DEFAULT '' COMMENT '服务id',
|
||||
`limit_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '限流策略,1:漏桶策略,2:令牌桶策略',
|
||||
`exec_count_per_second` int(11) DEFAULT NULL COMMENT '每秒可处理请求数',
|
||||
`duration_seconds` int(11) NOT NULL DEFAULT '1' COMMENT '限流持续时间,默认1秒,即每durationSeconds秒允许多少请求(当limit_type=1时有效)',
|
||||
`limit_code` varchar(64) DEFAULT NULL COMMENT '返回的错误码',
|
||||
`limit_msg` varchar(100) DEFAULT NULL COMMENT '返回的错误信息',
|
||||
`token_bucket_count` int(11) DEFAULT NULL COMMENT '令牌桶容量',
|
||||
|
Reference in New Issue
Block a user