Sync develop

This commit is contained in:
hongqiaowei
2022-04-27 23:09:01 +08:00
committed by GitHub
21 changed files with 393 additions and 164 deletions

View File

@@ -4,7 +4,7 @@ English | [简体中文](./README.md)
<a href="https://www.fizzgate.com"><img src="https://raw.githubusercontent.com/wiki/wehotel/fizz-gateway-community/img/icon-color.png" width="70%"></a>
</p>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-2.6.1-blue.svg?cacheSeconds=2592000" />
<img alt="Version" src="https://img.shields.io/badge/version-2.6.2-blue.svg?cacheSeconds=2592000" />
<a href="http://www.fizzgate.com/fizz-gateway-community/" target="_blank">
<img alt="Documentation" src="https://img.shields.io/badge/documentation-yes-brightgreen.svg" />
</a>
@@ -122,6 +122,7 @@ Starting from v1.3.0, the frontend and backend of the management backend are mer
| v2.5.2 | v2.5.2 |
| v2.6.0 | v2.6.0 |
| v2.6.1 | v2.6.1 |
| v2.6.2 | v2.6.2 |
Please download the corresponding management backend version according to the version of the community version

View File

@@ -3,7 +3,7 @@
<a href="https://www.fizzgate.com"><img src="https://raw.githubusercontent.com/wiki/wehotel/fizz-gateway-community/img/icon-color.png" width="70%"></a>
</p>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-2.6.1-blue.svg?cacheSeconds=2592000" />
<img alt="Version" src="https://img.shields.io/badge/version-2.6.2-blue.svg?cacheSeconds=2592000" />
<a href="http://www.fizzgate.com/fizz-gateway-community/" target="_blank">
<img alt="Documentation" src="https://img.shields.io/badge/documentation-yes-brightgreen.svg" />
</a>
@@ -120,6 +120,7 @@ API地址http://demo.fizzgate.com/proxy/[服务名]/[API_Path]
| v2.5.2 | v2.5.2 |
| v2.6.0 | v2.6.0 |
| v2.6.1 | v2.6.1 |
| v2.6.2 | v2.6.2 |
请根据社区版的版本下载对应的管理后台版本

View File

@@ -2,7 +2,7 @@ version: "3.6"
services:
fizz-mysql:
image: "fizzgate/fizz-mysql:2.6.1"
image: "fizzgate/fizz-mysql:2.6.2"
container_name: fizz-mysql
restart: always
hostname: fizz-mysql
@@ -27,7 +27,7 @@ services:
- fizz
fizz-gateway-community:
image: "fizzgate/fizz-gateway-community:2.6.1"
image: "fizzgate/fizz-gateway-community:2.6.2"
container_name: fizz-gateway-community
restart: always
hostname: fizz-gateway-community
@@ -48,7 +48,7 @@ services:
- fizz
fizz-manager-professional:
image: "fizzgate/fizz-manager-professional:2.6.1"
image: "fizzgate/fizz-manager-professional:2.6.2"
container_name: fizz-manager-professional
restart: always
hostname: fizz-manager-professional

View File

@@ -12,15 +12,15 @@
<groupId>com.fizzgate</groupId>
<artifactId>fizz-bootstrap</artifactId>
<version>2.6.1</version>
<version>2.6.2</version>
<properties>
<java.version>1.8</java.version>
<spring-framework.version>5.2.20.RELEASE</spring-framework.version>
<spring-framework.version>5.2.21.RELEASE</spring-framework.version>
<spring-session-bom.version>Dragonfruit-SR3</spring-session-bom.version>
<reactor-bom.version>Dysprosium-SR25</reactor-bom.version>
<lettuce.version>5.3.7.RELEASE</lettuce.version>
<netty.version>4.1.75.Final</netty.version>
<netty.version>4.1.76.Final</netty.version>
<httpcore.version>4.4.15</httpcore.version>
<log4j2.version>2.17.2</log4j2.version>
<slf4j.version>1.7.36</slf4j.version>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>fizz-gateway-community</artifactId>
<groupId>com.fizzgate</groupId>
<version>2.6.1</version>
<version>2.6.2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -17,6 +17,11 @@
</properties>
<dependencies>
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>

View File

@@ -101,6 +101,12 @@ public final class Consts {
public static final String PROD = "prod";
}
public static final class UN {
public static final int KB = 1024;
public static final int MB = 1024 * KB;
public static final int GB = 1024 * MB;
}
public static final String HTTP_SERVER = "http_server";
public static final String HTTP_CLIENT = "http_client";
public static final String MYSQL = "mysql";

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>fizz-gateway-community</artifactId>
<groupId>com.fizzgate</groupId>
<version>2.6.1</version>
<version>2.6.2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -17,6 +17,7 @@
package we.controller;
import org.openjdk.jol.info.GraphLayout;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -27,11 +28,22 @@ import we.plugin.auth.ApiConfig2appsService;
import we.plugin.auth.ApiConfigService;
import we.plugin.auth.AppService;
import we.plugin.auth.GatewayGroupService;
import we.stats.FlowStat;
import we.stats.ResourceStat;
import we.stats.circuitbreaker.CircuitBreakManager;
import we.stats.ratelimit.ResourceRateLimitConfig;
import we.stats.ratelimit.ResourceRateLimitConfigService;
import we.util.Consts;
import we.util.JacksonUtils;
import we.util.ResourceIdUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
/**
* @author hongqiaowei
@@ -62,6 +74,9 @@ public class CacheCheckController {
@Resource
private CircuitBreakManager circuitBreakManager;
@Resource
private FlowStat flowStat;
@GetMapping("/gatewayGroups")
public Mono<String> gatewayGroups(ServerWebExchange exchange) {
return Mono.just(JacksonUtils.writeValueAsString(gatewayGroupService.gatewayGroupMap));
@@ -101,4 +116,95 @@ public class CacheCheckController {
public Mono<String> circuitBreakers(ServerWebExchange exchange) {
return Mono.just(JacksonUtils.writeValueAsString(circuitBreakManager.getResource2circuitBreakerMap()));
}
@GetMapping("/resourceStats")
public Mono<String> resourceStats(ServerWebExchange exchange) {
Map<String, Object> map = new HashMap<>();
int nodeCnt = 0, serviceDefaultCnt = 0, serviceCnt = 0, servicePathCnt = 0, appDefaultCnt = 0, appCnt = 0, ipCnt = 0, hostCnt = 0;
ConcurrentMap<String, ResourceStat> resourceStats = flowStat.resourceStats;
Set<Map.Entry<String, ResourceStat>> entrySet = resourceStats.entrySet();
for (Map.Entry<String, ResourceStat> entry : entrySet) {
String resource = entry.getKey();
ResourceRateLimitConfig config = resourceRateLimitConfigService.getResourceRateLimitConfig(resource);
if (config == null) {
String app = ResourceIdUtils.getApp(resource);
String ip = ResourceIdUtils.getIp(resource);
String node = ResourceIdUtils.getNode(resource);
String service = ResourceIdUtils.getService(resource);
if (node == null) {
if (app != null) {
ResourceRateLimitConfig appConfig = resourceRateLimitConfigService.getResourceRateLimitConfig(ResourceIdUtils.APP_DEFAULT_RESOURCE);
if (appConfig != null && appConfig.isEnable()) {
appDefaultCnt++;
} else {
appCnt++;
}
continue;
}
if (ip != null) {
ipCnt++;
continue;
}
if (service != null) {
serviceDefaultCnt++;
}
} else {
if (node.equals(ResourceIdUtils.NODE)) {
nodeCnt++;
} else {
hostCnt++;
}
}
} else {
byte t = config.type;
if (t == ResourceRateLimitConfig.Type.NODE) {
nodeCnt++;
} else if (t == ResourceRateLimitConfig.Type.SERVICE_DEFAULT) {
serviceDefaultCnt++;
} else if (t == ResourceRateLimitConfig.Type.SERVICE) {
serviceCnt++;
} else if (t == ResourceRateLimitConfig.Type.APP_DEFAULT) {
appDefaultCnt++;
} else if (t == ResourceRateLimitConfig.Type.APP) {
appCnt++;
} else if (t == ResourceRateLimitConfig.Type.IP) {
ipCnt++;
} else if (t == ResourceRateLimitConfig.Type.API) {
servicePathCnt++;
} else {
hostCnt++;
}
}
}
map.put("node", nodeCnt);
map.put("serviceDefault", serviceDefaultCnt);
map.put("service", serviceCnt);
map.put("appDefault", appDefaultCnt);
map.put("app", appCnt);
map.put("ip", ipCnt);
map.put("host", hostCnt);
map.put("servicePathCnt", servicePathCnt);
int totalResources = appCnt + appDefaultCnt + ipCnt + nodeCnt + hostCnt + serviceCnt + serviceDefaultCnt + servicePathCnt;
map.put("totalResources", totalResources);
long size = GraphLayout.parseInstance(resourceStats).totalSize();
BigDecimal bigDecimalSize = new BigDecimal(size);
String resourceStatsSize;
if (size >= Consts.UN.GB) {
float r = bigDecimalSize.divide(new BigDecimal(Consts.UN.GB), 2, RoundingMode.HALF_UP).floatValue();
resourceStatsSize = r + " GB";
} else if (size >= Consts.UN.MB) {
float r = bigDecimalSize.divide(new BigDecimal(Consts.UN.MB), 2, RoundingMode.HALF_UP).floatValue();
resourceStatsSize = r + " MB";
} else if (size >= Consts.UN.KB) {
float r = bigDecimalSize.divide(new BigDecimal(Consts.UN.KB), 2, RoundingMode.HALF_UP).floatValue();
resourceStatsSize = r + " KB";
} else {
resourceStatsSize = size + " B";
}
map.put("resourceStatsSize", resourceStatsSize);
return Mono.just(JacksonUtils.writeValueAsString(map));
}
}

View File

@@ -324,12 +324,13 @@ public class FlowControlFilter extends FizzWebFilter {
List<ResourceConfig> resourceConfigs = new ArrayList<>(sz);
StringBuilder b = ThreadContext.getStringBuilder();
if (hasHost) {
// String resourceId = ResourceIdUtils.buildResourceId(app, ip, node, service, path);
String resourceId = ResourceIdUtils.buildResourceId(null, null, node, null, null);
ResourceConfig resourceConfig = new ResourceConfig(resourceId, 0, 0);
resourceConfigs.add(resourceConfig);
}
checkRateLimitConfigAndAddTo(resourceConfigs, b, null, null, ResourceIdUtils.NODE, null, null, null);
if (hasHost) {
String resourceId = ResourceIdUtils.buildResourceId(app, ip, node, service, path);
ResourceConfig resourceConfig = new ResourceConfig(resourceId, 0, 0);
resourceConfigs.add(resourceConfig);
}
checkRateLimitConfigAndAddTo(resourceConfigs, b, null, null, null, service, null, ResourceIdUtils.SERVICE_DEFAULT);
checkRateLimitConfigAndAddTo(resourceConfigs, b, null, null, null, service, path, null);
@@ -396,34 +397,16 @@ public class FlowControlFilter extends FizzWebFilter {
}
}
/*if (checkDegradeRule) {
DegradeRule degradeRule = degradeRuleService.getDegradeRule(resource);
if (degradeRule != null && degradeRule.isEnable()) {
if (rc == null) {
rc = new ResourceConfig(resource, 0, 0);
resourceConfigs.add(rc);
}
fillDegradeRuleData(rc, degradeRule);
} else {
if (defaultRateLimitConfigId != null && defaultRateLimitConfigId.equals(ResourceIdUtils.SERVICE_DEFAULT)) {
degradeRule = degradeRuleService.getDegradeRule(ResourceIdUtils.SERVICE_DEFAULT_RESOURCE);
if (degradeRule != null && degradeRule.isEnable()) {
fillDegradeRuleData(rc, degradeRule);
}
}
}
}*/
if (checkDegradeRule && resourceConfigs.size() == prevSize) {
CircuitBreaker cb = circuitBreakManager.getCircuitBreaker(resource);
if (cb == null) {
/*if (cb == null) {
if (defaultRateLimitConfigId != null && defaultRateLimitConfigId.equals(ResourceIdUtils.SERVICE_DEFAULT)) {
cb = circuitBreakManager.getCircuitBreaker(ResourceIdUtils.SERVICE_DEFAULT_RESOURCE);
if (cb == null || !cb.serviceDefaultEnable) {
cb = null;
}
}
}
}*/
if (cb != null) {
rc = new ResourceConfig(resource, 0, 0);
resourceConfigs.add(rc);
@@ -452,12 +435,12 @@ public class FlowControlFilter extends FizzWebFilter {
String service = ResourceIdUtils.getService(prev);
if (service == null) {
something4(resourceConfigs, rateLimitConfig.app, null, rateLimitConfig.service);
} else {
} /*else {
app = ResourceIdUtils.getApp(prevPrev);
if (app == null) {
something4(resourceConfigs, rateLimitConfig.app, null, null);
}
}
}*/
}
}
@@ -478,12 +461,12 @@ public class FlowControlFilter extends FizzWebFilter {
String service = ResourceIdUtils.getService(prev);
if (service == null) {
something4(resourceConfigs, null, rateLimitConfig.ip, rateLimitConfig.service);
} else {
} /*else {
ip = ResourceIdUtils.getIp(prevPrev);
if (ip == null) {
something4(resourceConfigs, null, rateLimitConfig.ip, null);
}
}
}*/
}
}
}

View File

@@ -439,9 +439,9 @@ public class FuncExecutor {
if (!Character.isWhitespace(argsStr.charAt(i))) {
if (")".equals(String.valueOf(argsStr.charAt(i)))) {
return true;
} else {
} /*else {
return false;
}
}*/
}
}
return false;

View File

@@ -17,6 +17,7 @@
package we.fizz.input.extension.request;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -365,8 +366,20 @@ public class RequestInput extends RPCInput implements IInput{
// add default headers
SystemConfig systemConfig = this.getCurrentApplicationContext().getBean(SystemConfig.class);
for (String hdr : systemConfig.getProxySetHeaders()) {
if(inputContext.getStepContext().getInputReqHeader(hdr) != null) {
headers.addIfAbsent(hdr, (String) inputContext.getStepContext().getInputReqHeader(hdr));
if(inputContext.getStepContext().getInputReqHeader(hdr) != null && !headers.containsKey(hdr)) {
Object o = inputContext.getStepContext().getInputReqHeader(hdr);
if (o instanceof String) {
headers.add(hdr, (String) o);
} else if (o instanceof List){
List<Object> list = (List<Object>) o;
List<String> vals = new ArrayList<>();
for (Object item : list) {
if (item != null) {
vals.add(item.toString());
}
}
headers.addAll(hdr, vals);
}
}
}

View File

@@ -17,11 +17,8 @@
package we.stats;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
@@ -55,15 +52,19 @@ public class FlowStat {
*/
public static long INTERVAL = 1000;
public boolean cleanResource = true;
public boolean createTimeSlotOnlyTraffic = true;
/**
* A string Resource ID as key
*/
public ConcurrentMap<String, ResourceStat> resourceStats = new ConcurrentHashMap<>(100);
public ConcurrentMap<String, ResourceStat> resourceStats = new ConcurrentHashMap<>(256);
/**
* Retention time of statistic data
*/
public static long RETENTION_TIME_IN_MINUTES = 10;
public static long RETENTION_TIME_IN_MINUTES = 5;
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock w = rwl.writeLock();
@@ -76,6 +77,12 @@ public class FlowStat {
runScheduleJob();
}
public FlowStat(boolean cleanResource, boolean createTimeSlotOnlyTraffic) {
this.cleanResource = cleanResource;
this.createTimeSlotOnlyTraffic = createTimeSlotOnlyTraffic;
runScheduleJob();
}
public FlowStat(CircuitBreakManager circuitBreakManager) {
this.circuitBreakManager = circuitBreakManager;
runScheduleJob();
@@ -175,7 +182,7 @@ public class FlowStat {
// check QPS
if (maxQPS > 0) {
long total = resourceStat.getTimeSlot(curTimeSlotId).getCounter().get();
long total = resourceStat.getTimeSlot(curTimeSlotId).getCounter();
if (total >= maxQPS) {
resourceStat.incrBlockRequestToTimeSlot(curTimeSlotId);
if (totalBlockFunc != null) {
@@ -197,7 +204,7 @@ public class FlowStat {
// increase request and concurrent request
for (ResourceConfig resourceConfig : resourceConfigs) {
ResourceStat resourceStat = getResourceStat(resourceConfig.getResourceId());
long cons = resourceStat.getConcurrentRequests().incrementAndGet();
int cons = resourceStat.getConcurrentRequests().incrementAndGet();
resourceStat.getTimeSlot(curTimeSlotId).updatePeakConcurrentReqeusts(cons);
resourceStat.getTimeSlot(curTimeSlotId).incr();
}
@@ -242,7 +249,7 @@ public class FlowStat {
// check QPS
if (maxQPS > 0) {
long total = resourceStat.getTimeSlot(curTimeSlotId).getCounter().get();
long total = resourceStat.getTimeSlot(curTimeSlotId).getCounter();
if (total >= maxQPS) {
resourceStat.incrBlockRequestToTimeSlot(curTimeSlotId);
if (totalBlockFunc != null) {
@@ -276,7 +283,7 @@ public class FlowStat {
// increase request and concurrent request
for (ResourceConfig resourceConfig : resourceConfigs) {
ResourceStat resourceStat = getResourceStat(resourceConfig.getResourceId());
long cons = resourceStat.getConcurrentRequests().incrementAndGet();
int cons = resourceStat.getConcurrentRequests().incrementAndGet();
resourceStat.getTimeSlot(curTimeSlotId).updatePeakConcurrentReqeusts(cons);
resourceStat.getTimeSlot(curTimeSlotId).incr();
}
@@ -564,25 +571,63 @@ public class FlowStat {
long n = FlowStat.RETENTION_TIME_IN_MINUTES * 60 * 1000 / FlowStat.INTERVAL * FlowStat.INTERVAL;
long lastSlotId = stat.currentTimeSlotId() - n;
while (true) {
// log.debug("housekeeping start");
long slotId = stat.currentTimeSlotId() - n;
/*if (log.isDebugEnabled()) {
log.debug("{} - {} resource stats size {}", lastSlotId, slotId, stat.resourceStats.size());
}
Set<Map.Entry<String, ResourceStat>> es = stat.resourceStats.entrySet();
for (Entry<String, ResourceStat> e : es) {
String resourceId = e.getKey();
ConcurrentMap<Long, TimeSlot> timeSlots = e.getValue().getTimeSlots();
if (log.isDebugEnabled()) {
log.debug("{} - {} {} has {} timeslot", lastSlotId, slotId, resourceId, timeSlots.size());
}
}*/
for (long i = lastSlotId; i < slotId;) {
Set<Map.Entry<String, ResourceStat>> entrys = stat.resourceStats.entrySet();
for (Entry<String, ResourceStat> entry : entrys) {
String resourceId = entry.getKey();
ConcurrentMap<Long, TimeSlot> timeSlots = entry.getValue().getTimeSlots();
// log.debug("housekeeping remove slot: resourceId={} slotId=={}", resourceId,
// i);
/*if (log.isDebugEnabled()) {
log.debug("{} - {} {} remove {} timeslot", lastSlotId, slotId, resourceId, i);
}*/
timeSlots.remove(i);
}
i = i + FlowStat.INTERVAL;
}
lastSlotId = slotId;
// log.debug("housekeeping done");
if (cleanResource) {
long currentTimeSlot = stat.currentTimeSlotId();
long startTimeSlot = currentTimeSlot - n;
for (Entry<String, ResourceStat> entry : stat.resourceStats.entrySet()) {
String resource = entry.getKey();
if (ResourceIdUtils.NODE_RESOURCE.equals(resource)) {
continue;
}
ResourceStat resourceStat = entry.getValue();
boolean noTraffic = true;
long timeSlot = startTimeSlot;
for (; timeSlot < currentTimeSlot; timeSlot += FlowStat.INTERVAL) {
int reqCnt = resourceStat.getTimeSlot(timeSlot).getCounter();
if (reqCnt > 0) {
noTraffic = false;
break;
}
}
if (noTraffic) {
stat.resourceStats.remove(resource);
log.info("HousekeepJob remove {}", resource);
}
}
}
try {
Thread.sleep(60 * 1000);
Thread.sleep(10 * 1000);
} catch (Exception e) {
e.printStackTrace();
log.error("HouseKeepJob error", e);
}
}
}
@@ -605,13 +650,18 @@ public class FlowStat {
// log.debug("PeakConcurrentJob start");
Set<Map.Entry<String, ResourceStat>> entrys = stat.resourceStats.entrySet();
for (Entry<String, ResourceStat> entry : entrys) {
String resourceId = entry.getKey();
String resource = entry.getKey();
// log.debug("PeakConcurrentJob: resourceId={} slotId=={}", resourceId,
// curTimeSlotId);
ResourceStat resourceStat = entry.getValue();
resourceStat.getTimeSlot(curTimeSlotId);
String resource = resourceStat.getResourceId();
ResourceStat resourceStat = entry.getValue();
if (createTimeSlotOnlyTraffic && resourceStat.getConcurrentRequests().get() > 0) {
resourceStat.getTimeSlot(curTimeSlotId);
} else {
resourceStat.getTimeSlot(curTimeSlotId);
}
// String resource = resourceStat.getResourceId();
CircuitBreaker cb = circuitBreakManager.getCircuitBreaker(resource);
if (cb != null) {
cb.correctState(curTimeSlotId, stat);
@@ -623,7 +673,7 @@ public class FlowStat {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
log.error("PeakConcurrentJob error", e);
}
}
}

View File

@@ -20,6 +20,7 @@ package we.stats;
import java.math.BigDecimal;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -45,12 +46,13 @@ public class ResourceStat {
/**
* Request count of time slot, the beginning timestamp(timeId) as key
*/
private ConcurrentMap<Long, TimeSlot> timeSlots = new ConcurrentHashMap<>(100);
private ConcurrentMap<Long, TimeSlot> timeSlots = new ConcurrentHashMap<>(256);
/**
* Concurrent requests
*/
private AtomicLong concurrentRequests = new AtomicLong(0);
// private AtomicLong concurrentRequests = new AtomicLong(0);
private AtomicInteger concurrentRequests = new AtomicInteger(0);
private ReentrantReadWriteLock rwl1 = new ReentrantReadWriteLock();
private ReentrantReadWriteLock rwl2 = new ReentrantReadWriteLock();
@@ -95,16 +97,16 @@ public class ResourceStat {
try {
boolean isExceeded = false;
if (maxCon != null && maxCon.intValue() > 0) {
long n = this.concurrentRequests.get();
int n = this.concurrentRequests.get();
if (n >= maxCon.longValue()) {
isExceeded = true;
this.incrBlockRequestToTimeSlot(timeSlotId);
} else {
long conns = this.concurrentRequests.incrementAndGet();
int conns = this.concurrentRequests.incrementAndGet();
this.getTimeSlot(timeSlotId).updatePeakConcurrentReqeusts(conns);
}
} else {
long conns = this.concurrentRequests.incrementAndGet();
int conns = this.concurrentRequests.incrementAndGet();
this.getTimeSlot(timeSlotId).updatePeakConcurrentReqeusts(conns);
}
return !isExceeded;
@@ -118,7 +120,7 @@ public class ResourceStat {
*
*/
public void decrConcurrentRequest(long timeSlotId) {
long conns = this.concurrentRequests.decrementAndGet();
int conns = this.concurrentRequests.decrementAndGet();
this.getTimeSlot(timeSlotId).updatePeakConcurrentReqeusts(conns);
}
@@ -127,7 +129,8 @@ public class ResourceStat {
*
*/
public void incrBlockRequestToTimeSlot(long timeSlotId) {
this.getTimeSlot(timeSlotId).getBlockRequests().incrementAndGet();
// this.getTimeSlot(timeSlotId).getBlockRequests().incrementAndGet();
this.getTimeSlot(timeSlotId).incrBlockRequests();
}
/**
@@ -135,7 +138,8 @@ public class ResourceStat {
*
*/
public void incrTotalBlockRequestToTimeSlot(long timeSlotId) {
this.getTimeSlot(timeSlotId).getTotalBlockRequests().incrementAndGet();
// this.getTimeSlot(timeSlotId).getTotalBlockRequests().incrementAndGet();
this.getTimeSlot(timeSlotId).incrTotalBlockRequests();
}
/**
@@ -156,7 +160,7 @@ public class ResourceStat {
// }
// time slot unit is one second
long total = this.getTimeSlot(timeSlotId).getCounter().get();
long total = this.getTimeSlot(timeSlotId).getCounter();
long max = Long.valueOf(maxRPS);
if (total >= max) {
isExceeded = true;
@@ -179,28 +183,28 @@ public class ResourceStat {
}
public void incrCircuitBreakNum(long timeSlot) {
getTimeSlot(timeSlot).getCircuitBreakNum().incrementAndGet();
getTimeSlot(timeSlot).incrCircuitBreakNum();
}
public void decrCircuitBreakNum(long timeSlot) {
getTimeSlot(timeSlot).getCircuitBreakNum().decrementAndGet();
}
public void incrGradualResumeNum(long timeSlot) {
getTimeSlot(timeSlot).getGradualResumeNum().incrementAndGet();
}
public void decrGradualResumeNum(long timeSlot) {
getTimeSlot(timeSlot).getGradualResumeNum().decrementAndGet();
}
public void incrGradualRejectNum(long timeSlot) {
getTimeSlot(timeSlot).getGradualRejectNum().incrementAndGet();
}
public void decrGradualRejectNum(long timeSlot) {
getTimeSlot(timeSlot).getGradualRejectNum().decrementAndGet();
}
// public void decrCircuitBreakNum(long timeSlot) {
// getTimeSlot(timeSlot).getCircuitBreakNum().decrementAndGet();
// }
//
// public void incrGradualResumeNum(long timeSlot) {
// getTimeSlot(timeSlot).getGradualResumeNum().incrementAndGet();
// }
//
// public void decrGradualResumeNum(long timeSlot) {
// getTimeSlot(timeSlot).getGradualResumeNum().decrementAndGet();
// }
//
// public void incrGradualRejectNum(long timeSlot) {
// getTimeSlot(timeSlot).getGradualRejectNum().incrementAndGet();
// }
//
// public void decrGradualRejectNum(long timeSlot) {
// getTimeSlot(timeSlot).getGradualRejectNum().decrementAndGet();
// }
public void incr2xxStatusCount(long timeSlot) {
getTimeSlot(timeSlot).get2xxStatusCount().incrementAndGet();
@@ -267,13 +271,13 @@ public class ResourceStat {
peakConcurrences = timeSlot.getPeakConcurrentRequests() > peakConcurrences
? timeSlot.getPeakConcurrentRequests()
: peakConcurrences;
peakRps = timeSlot.getCounter().get() > peakRps ? timeSlot.getCounter().get() : peakRps;
totalReqs = totalReqs + timeSlot.getCounter().get();
totalRt = totalRt + timeSlot.getTotalRt().get();
errors = errors + timeSlot.getErrors().get();
blockReqs = blockReqs + timeSlot.getBlockRequests().get();
totalBlockReqs = totalBlockReqs + timeSlot.getTotalBlockRequests().get();
compReqs = compReqs + timeSlot.getCompReqs().get();
peakRps = timeSlot.getCounter() > peakRps ? timeSlot.getCounter() : peakRps;
totalReqs = totalReqs + timeSlot.getCounter();
totalRt = totalRt + timeSlot.getTotalRt();
errors = errors + timeSlot.getErrors();
blockReqs = blockReqs + timeSlot.getBlockRequests();
totalBlockReqs = totalBlockReqs + timeSlot.getTotalBlockRequests();
compReqs = compReqs + timeSlot.getCompReqs();
_2xxStatus = _2xxStatus + timeSlot.get2xxStatusCount().get();
_4xxStatus = _4xxStatus + timeSlot.get4xxStatusCount().get();
@@ -333,11 +337,11 @@ public class ResourceStat {
this.timeSlots = timeSlots;
}
public AtomicLong getConcurrentRequests() {
public AtomicInteger getConcurrentRequests() {
return concurrentRequests;
}
public void setConcurrentRequests(AtomicLong concurrentRequests) {
public void setConcurrentRequests(AtomicInteger concurrentRequests) {
this.concurrentRequests = concurrentRequests;
}
}

View File

@@ -37,12 +37,14 @@ public class TimeSlot {
/**
* Request counter
*/
private AtomicLong counter = new AtomicLong();
// private AtomicLong counter = new AtomicLong();
private volatile int counter = 0;
/**
* Error request counter
*/
private AtomicLong errors = new AtomicLong();
// private AtomicLong errors = new AtomicLong();
private volatile int errors = 0;
/**
* Minimum response time
@@ -57,39 +59,45 @@ public class TimeSlot {
/**
* Total response time
*/
private AtomicLong totalRt = new AtomicLong(0);
// private AtomicLong totalRt = new AtomicLong(0);
private volatile int totalRt = 0;
/**
* Completed Request counter
*/
private AtomicLong compReqs = new AtomicLong();
// private AtomicLong compReqs = new AtomicLong();
private volatile int compReqs = 0;
/**
* Peak concurrent requests
*/
private long peakConcurrentRequests;
private volatile int peakConcurrentRequests;
/**
* Block requests <br/>
*/
private AtomicLong blockRequests = new AtomicLong(0);
// private AtomicLong blockRequests = new AtomicLong(0);
private volatile int blockRequests = 0;
/**
* Total block requests of the resource and its underlying resources <br/>
*/
private AtomicLong totalBlockRequests = new AtomicLong(0);
// private AtomicLong totalBlockRequests = new AtomicLong(0);
private volatile int totalBlockRequests = 0;
private AtomicReference<CircuitBreaker.State> circuitBreakState = new AtomicReference<>(CircuitBreaker.State.CLOSED);
private AtomicLong circuitBreakNum = new AtomicLong(0);
// private AtomicLong circuitBreakNum = new AtomicLong(0);
private volatile int circuitBreakNum = 0;
private AtomicLong gradualResumeNum = new AtomicLong(0);
// private AtomicLong gradualResumeNum = new AtomicLong(0);
private volatile int gradualResumeNum = 0;
private AtomicInteger resumeTrafficFactor = new AtomicInteger(1);
// private AtomicInteger resumeTrafficFactor = new AtomicInteger(1);
private volatile int resumeTrafficFactor = 1;
private AtomicLong gradualRejectNum = new AtomicLong(0);
// private AtomicLong gradualRejectNum = new AtomicLong(0);
private volatile int gradualRejectNum = 0;
private AtomicInteger _2xxStatusCount = new AtomicInteger(0);
@@ -119,22 +127,50 @@ public class TimeSlot {
return circuitBreakState;
}
public AtomicLong getCircuitBreakNum() {
public int getCircuitBreakNum() {
return circuitBreakNum;
}
public AtomicLong getGradualResumeNum() {
public void setCircuitBreakNum(int v) {
circuitBreakNum = v;
}
public void incrCircuitBreakNum() {
++circuitBreakNum;
}
public int getGradualResumeNum() {
return gradualResumeNum;
}
public AtomicInteger getResumeTrafficFactor() {
public int incrGradualResumeNum() {
return ++gradualResumeNum;
}
public int decrGradualResumeNum() {
return --gradualResumeNum;
}
public int getResumeTrafficFactor() {
return resumeTrafficFactor;
}
public AtomicLong getGradualRejectNum() {
public void incrResumeTrafficFactor() {
++resumeTrafficFactor;
}
public int getGradualRejectNum() {
return gradualRejectNum;
}
public int incrGradualRejectNum() {
return ++gradualRejectNum;
}
public int decrGradualRejectNum() {
return --gradualRejectNum;
}
public TimeSlot(long id) {
this.id = id;
@@ -149,7 +185,8 @@ public class TimeSlot {
*
*/
public void incr() {
counter.incrementAndGet();
// counter.incrementAndGet();
++counter;
}
/**
@@ -159,10 +196,10 @@ public class TimeSlot {
* @param isSuccess Whether the request is success or not
*/
public synchronized void addRequestRT(long rt, boolean isSuccess) {
totalRt.addAndGet(rt);
compReqs.incrementAndGet();
totalRt += rt;
++compReqs;
if (!isSuccess) {
errors.incrementAndGet();
++errors;
}
min = rt < min ? rt : min;
max = rt > max ? rt : max;
@@ -173,7 +210,7 @@ public class TimeSlot {
*
* @param concurrentRequests Current concurrent requests
*/
public synchronized void updatePeakConcurrentReqeusts(long concurrentRequests) {
public synchronized void updatePeakConcurrentReqeusts(int concurrentRequests) {
peakConcurrentRequests = concurrentRequests > peakConcurrentRequests ? concurrentRequests
: peakConcurrentRequests;
}
@@ -182,11 +219,11 @@ public class TimeSlot {
this.id = id;
}
public AtomicLong getCounter() {
public int getCounter() {
return counter;
}
public void setCounter(AtomicLong counter) {
public void setCounter(int counter) {
this.counter = counter;
}
@@ -206,11 +243,11 @@ public class TimeSlot {
this.max = max;
}
public AtomicLong getTotalRt() {
public int getTotalRt() {
return totalRt;
}
public void setTotalRt(AtomicLong totalRt) {
public void setTotalRt(int totalRt) {
this.totalRt = totalRt;
}
@@ -218,39 +255,47 @@ public class TimeSlot {
return peakConcurrentRequests;
}
public void setPeakConcurrentRequests(long peakConcurrentRequests) {
public void setPeakConcurrentRequests(int peakConcurrentRequests) {
this.peakConcurrentRequests = peakConcurrentRequests;
}
public AtomicLong getErrors() {
public int getErrors() {
return errors;
}
public void setErrors(AtomicLong errors) {
public void setErrors(int errors) {
this.errors = errors;
}
public AtomicLong getBlockRequests() {
public int getBlockRequests() {
return blockRequests;
}
public void setBlockRequests(AtomicLong blockRequests) {
public void setBlockRequests(int blockRequests) {
this.blockRequests = blockRequests;
}
public AtomicLong getCompReqs() {
public void incrBlockRequests() {
++blockRequests;
}
public int getCompReqs() {
return compReqs;
}
public void setCompReqs(AtomicLong compReqs) {
public void setCompReqs(int compReqs) {
this.compReqs = compReqs;
}
public AtomicLong getTotalBlockRequests() {
public int getTotalBlockRequests() {
return totalBlockRequests;
}
public void setTotalBlockRequests(AtomicLong totalBlockRequests) {
public void incrTotalBlockRequests() {
++totalBlockRequests;
}
public void setTotalBlockRequests(int totalBlockRequests) {
this.totalBlockRequests = totalBlockRequests;
}

View File

@@ -264,7 +264,7 @@ public class CircuitBreakManager {
}
}*/
public void correctCircuitBreakerStateAsError(ServerWebExchange exchange, long currentTimeWindow, FlowStat flowStat, String service, String path) {
/*public void correctCircuitBreakerStateAsError(ServerWebExchange exchange, long currentTimeWindow, FlowStat flowStat, String service, String path) {
String resource = ResourceIdUtils.buildResourceId(null, null, null, service, path);
// correctCircuitBreakerState4error(exchange, currentTimeWindow, flowStat, resource);
CircuitBreaker cb = resource2circuitBreakerMap.get(resource);
@@ -290,7 +290,7 @@ public class CircuitBreakManager {
}
cb.correctCircuitBreakerStateAsError(currentTimeWindow, flowStat);
}
}
}*/
/*public void correctCircuitBreakerState4error(ServerWebExchange exchange, long currentTimeWindow, FlowStat flowStat, String resource) {
while (true) {

View File

@@ -77,25 +77,31 @@ public class CircuitBreaker {
public boolean permit(ResourceStat resourceStat, long currentTimeWindow) {
TimeSlot timeSlot = resourceStat.getTimeSlot(currentTimeWindow);
AtomicLong resumeCount = timeSlot.getGradualResumeNum();
AtomicInteger resumeTrafficFactor = timeSlot.getResumeTrafficFactor();
long n = resumeTrafficFactor.get();
if (resumeCount.incrementAndGet() <= resumeTraffic * n) {
// AtomicLong resumeCount = timeSlot.getGradualResumeNum();
// AtomicInteger resumeTrafficFactor = timeSlot.getResumeTrafficFactor();
// long n = resumeTrafficFactor.get();
long n = timeSlot.getResumeTrafficFactor();
// if (resumeCount.incrementAndGet() <= resumeTraffic * n) {
if (timeSlot.incrGradualResumeNum() <= resumeTraffic * n) {
LOGGER.debug("{} current time window {}, resume traffic {}, resume traffic factor {}, resume count {}, resume current request",
resourceStat.getResourceId(), currentTimeWindow, resumeTraffic, n, resumeCount.get());
resourceStat.getResourceId(), currentTimeWindow, resumeTraffic, n, timeSlot.getGradualResumeNum());
return true;
}
AtomicLong rejectCount = timeSlot.getGradualRejectNum();
if (rejectCount.incrementAndGet() <= rejectTraffic * n) {
resumeCount.decrementAndGet();
// AtomicLong rejectCount = timeSlot.getGradualRejectNum();
// if (rejectCount.incrementAndGet() <= rejectTraffic * n) {
if (timeSlot.incrGradualRejectNum() <= rejectTraffic * n) {
// resumeCount.decrementAndGet();
timeSlot.decrGradualResumeNum();
LOGGER.debug("{} current time window {}, reject traffic {}, resume traffic factor {}, reject count {}, reject current request",
resourceStat.getResourceId(), currentTimeWindow, rejectTraffic, n, rejectCount.get());
resourceStat.getResourceId(), currentTimeWindow, rejectTraffic, n, timeSlot.getGradualRejectNum());
return false;
}
rejectCount.decrementAndGet();
resumeTrafficFactor.incrementAndGet();
// rejectCount.decrementAndGet();
timeSlot.decrGradualRejectNum();
// resumeTrafficFactor.incrementAndGet();
timeSlot.incrResumeTrafficFactor();
LOGGER.debug("{} current time window {}, resume traffic {}, reject traffic {}, resume traffic factor {}, resume count {}, reject count {}, resume current request",
resourceStat.getResourceId(), currentTimeWindow, resumeTraffic, rejectTraffic, n, resumeCount.get(), rejectCount.get());
resourceStat.getResourceId(), currentTimeWindow, resumeTraffic, rejectTraffic, n, timeSlot.getGradualResumeNum(), timeSlot.getGradualRejectNum());
return true;
}
@@ -286,7 +292,7 @@ public class CircuitBreaker {
}
}
public void correctCircuitBreakerStateAsError(long currentTimeWindow, FlowStat flowStat) {
/*public void correctCircuitBreakerStateAsError(long currentTimeWindow, FlowStat flowStat) {
if (stateRef.get() == State.CLOSED) {
long endTimeWindow = currentTimeWindow + 1000;
// TimeWindowStat timeWindowStat = flowStat.getTimeWindowStat(resource, endTimeWindow - monitorDuration, endTimeWindow);
@@ -309,16 +315,17 @@ public class CircuitBreaker {
}
}
}
}
}*/
public boolean transit(State current, State target, long currentTimeWindow, FlowStat flowStat) {
if (stateRef.compareAndSet(current, target)) {
stateStartTime = currentTimeWindow;
ResourceStat resourceStat = flowStat.getResourceStat(resource);
AtomicLong circuitBreakNum = resourceStat.getTimeSlot(currentTimeWindow).getCircuitBreakNum();
circuitBreakNum.set(0);
/*AtomicLong circuitBreakNum = resourceStat.getTimeSlot(currentTimeWindow).getCircuitBreakNum();
circuitBreakNum.set(0);*/
resourceStat.getTimeSlot(currentTimeWindow).setCircuitBreakNum(0);
resourceStat.updateCircuitBreakState(currentTimeWindow, current, target);
LOGGER.debug("transit {} current time window {} from {} which start at {} to {}", resource, currentTimeWindow, current, stateStartTime, target);
stateStartTime = currentTimeWindow;
return true;
}
return false;

View File

@@ -39,7 +39,7 @@ import we.util.JacksonUtils;
*/
public class FlowStatTests {
private FlowStat stat = new FlowStat();
private FlowStat stat = new FlowStat(false, false);
class FlowRuleCase {
public int threads = 3;

View File

@@ -68,6 +68,8 @@ public class CircuitBreakManagerTests {
@Test
void permitTest() {
FlowStat flowStat = new FlowStat(circuitBreakManager);
flowStat.cleanResource = false;
flowStat.createTimeSlotOnlyTraffic = false;
long currentTimeWindow = flowStat.currentTimeSlotId();
MockServerHttpRequest mockServerHttpRequest = MockServerHttpRequest.get("/xxx").build();
@@ -92,8 +94,8 @@ public class CircuitBreakManagerTests {
ResourceStat resourceStat = flowStat.getResourceStat(cb.resource);
TimeSlot timeSlot = resourceStat.getTimeSlot(currentTimeWindow);
timeSlot.getCompReqs().set(200);
timeSlot.getErrors().set(11);
timeSlot.setCompReqs(200);
timeSlot.setErrors(11);
boolean permit = circuitBreakManager.permit(mockServerWebExchange, currentTimeWindow, flowStat, service, path);
Assertions.assertFalse(permit);
@@ -101,6 +103,6 @@ public class CircuitBreakManagerTests {
permit = circuitBreakManager.permit(mockServerWebExchange, currentTimeWindow, flowStat, service, path);
Assertions.assertFalse(permit);
Assertions.assertEquals(CircuitBreaker.State.OPEN, timeSlot.getCircuitBreakState().get());
Assertions.assertEquals(2, timeSlot.getCircuitBreakNum().get());
Assertions.assertEquals(2, timeSlot.getCircuitBreakNum());
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>fizz-gateway-community</artifactId>
<groupId>com.fizzgate</groupId>
<version>2.6.1</version>
<version>2.6.2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>fizz-gateway-community</artifactId>
<groupId>com.fizzgate</groupId>
<version>2.6.1</version>
<version>2.6.2</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

12
pom.xml
View File

@@ -6,11 +6,11 @@
<properties>
<!--<java.version>1.8</java.version>-->
<spring-boot.version>2.2.13.RELEASE</spring-boot.version>
<spring-framework.version>5.2.20.RELEASE</spring-framework.version>
<spring-framework.version>5.2.21.RELEASE</spring-framework.version>
<reactor-bom.version>Dysprosium-SR25</reactor-bom.version>
<lettuce.version>5.3.7.RELEASE</lettuce.version>
<nacos.cloud.version>2.2.7.RELEASE</nacos.cloud.version>
<netty.version>4.1.75.Final</netty.version>
<netty.version>4.1.76.Final</netty.version>
<httpcore.version>4.4.15</httpcore.version>
<log4j2.version>2.17.2</log4j2.version>
<slf4j.version>1.7.36</slf4j.version>
@@ -37,7 +37,7 @@
<artifactId>fizz-gateway-community</artifactId>
<name>${project.artifactId}</name>
<description>fizz gateway community</description>
<version>2.6.1</version>
<version>2.6.2</version>
<packaging>pom</packaging>
<modules>
<module>fizz-common</module>
@@ -69,6 +69,12 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>