From 1c21dc97ae5cad6fa9417ced76ad54c400b26f95 Mon Sep 17 00:00:00 2001 From: hongqiaowei Date: Mon, 20 Feb 2023 18:18:15 +0800 Subject: [PATCH 01/10] Support request path end with or without / --- .../fizzgate/plugin/auth/ServiceConfig.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/fizz-core/src/main/java/com/fizzgate/plugin/auth/ServiceConfig.java b/fizz-core/src/main/java/com/fizzgate/plugin/auth/ServiceConfig.java index 292522e..1396879 100644 --- a/fizz-core/src/main/java/com/fizzgate/plugin/auth/ServiceConfig.java +++ b/fizz-core/src/main/java/com/fizzgate/plugin/auth/ServiceConfig.java @@ -18,6 +18,7 @@ package com.fizzgate.plugin.auth; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fizzgate.util.Consts; import com.fizzgate.util.ThreadContext; import com.fizzgate.util.UrlTransformUtils; @@ -124,18 +125,22 @@ public class ServiceConfig { } private void checkPathPattern(Map> pathPattern2apiConfigMap, boolean dedicatedLineRequest, String path, ArrayList result) { + String path0 = path; + if (!path.equals(Consts.S.FORWARD_SLASH_STR)) { + int lastCharPos = path.length() - 1; + char c = path.charAt(lastCharPos); + if (c == Consts.S.FORWARD_SLASH) { + path0 = path.substring(0, lastCharPos); + } else { + path0 = path + Consts.S.FORWARD_SLASH; + } + } Set>> entries = pathPattern2apiConfigMap.entrySet(); - // boolean clear = false; for (Map.Entry> entry : entries) { String pathPattern = entry.getKey(); Set apiConfigs = entry.getValue(); - if (pathPattern.equals(path)) { + if (pathPattern.equals(path) || pathPattern.equals(path0)) { for (ApiConfig ac : apiConfigs) { -// if (ac.allowAccess) { - /*if (!clear && !result.isEmpty()) { - result.clear(); - clear = true; - }*/ if (dedicatedLineRequest) { if (ac.dedicatedLine) { result.add(ac); @@ -145,14 +150,9 @@ public class ServiceConfig { result.add(ac); } } -// } } - /*if (clear && !result.isEmpty()) { - return; - }*/ - } else if (UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path)) { + } else if (UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path) || UrlTransformUtils.ANT_PATH_MATCHER.match(pathPattern, path0)) { for (ApiConfig ac : apiConfigs) { -// if (ac.allowAccess) { if (dedicatedLineRequest) { if (ac.dedicatedLine) { result.add(ac); @@ -162,9 +162,8 @@ public class ServiceConfig { result.add(ac); } } -// } } } - } // end for + } } } From 4629b2410139f0b484426c19c583b3dfe788c42b Mon Sep 17 00:00:00 2001 From: Francis Dong Date: Thu, 16 Mar 2023 11:59:25 +0800 Subject: [PATCH 02/10] Support HMAC algorithm functions #470 --- .../com/fizzgate/fizz/function/CodecFunc.java | 34 ++++++++++++++++++- .../fizz/function/CodecFuncTests.java | 7 ++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java b/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java index 23ad4b1..8044e04 100644 --- a/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java +++ b/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java @@ -27,6 +27,8 @@ import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import org.apache.commons.codec.digest.HmacAlgorithms; +import org.apache.commons.codec.digest.HmacUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +48,7 @@ public class CodecFunc implements IFunc { private static final String CHARSET_UTF8 = "UTF-8"; private static final String IV = "12345678"; - + private static CodecFunc singleton; public static CodecFunc getInstance() { @@ -77,6 +79,12 @@ public class CodecFunc implements IFunc { FuncExecutor.register(NAME_SPACE_PREFIX + "codec.aesDecrypt", this); FuncExecutor.register(NAME_SPACE_PREFIX + "codec.desEncrypt", this); FuncExecutor.register(NAME_SPACE_PREFIX + "codec.desDecrypt", this); + FuncExecutor.register(NAME_SPACE_PREFIX + "codec.hmacMd5", this); + FuncExecutor.register(NAME_SPACE_PREFIX + "codec.hmacSha1", this); + FuncExecutor.register(NAME_SPACE_PREFIX + "codec.hmacSha224", this); + FuncExecutor.register(NAME_SPACE_PREFIX + "codec.hmacSha256", this); + FuncExecutor.register(NAME_SPACE_PREFIX + "codec.hmacSha384", this); + FuncExecutor.register(NAME_SPACE_PREFIX + "codec.hmacSha512", this); } public String md5(String data) { @@ -180,5 +188,29 @@ public class CodecFunc implements IFunc { throw e; } } + + public String hmacMd5(String secretKey, String data) { + return new HmacUtils(HmacAlgorithms.HMAC_MD5, secretKey).hmacHex(data); + } + + public String hmacSha1(String secretKey, String data) { + return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, secretKey).hmacHex(data); + } + + public String hmacSha224(String secretKey, String data) { + return new HmacUtils(HmacAlgorithms.HMAC_SHA_224, secretKey).hmacHex(data); + } + + public String hmacSha256(String secretKey, String data) { + return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secretKey).hmacHex(data); + } + + public String hmacSha384(String secretKey, String data) { + return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, secretKey).hmacHex(data); + } + + public String hmacSha512(String secretKey, String data) { + return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, secretKey).hmacHex(data); + } } diff --git a/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java b/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java index 750abc9..4c79872 100644 --- a/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java +++ b/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java @@ -122,5 +122,12 @@ class CodecFuncTests { Object result = FuncExecutor.getInstance().exec(null, funcExpression); assertEquals("abc", result.toString()); } + + @Test + void testHmacSha256() { + String funcExpression = "fn.codec.hmacSha256(\"635e8562b968bc05bb80cacf124ebd53285280ee6845df0000faa33acafc38f0\", \"12345678123456781234567812345678\")"; + Object result = FuncExecutor.getInstance().exec(null, funcExpression); + assertEquals("c61be0237ec186df1c5f51425e607093b260a76e5de43a62cb3e821103303990", result.toString()); + } } \ No newline at end of file From b6b3bc474a0de08014c5d201082bb1211caf9d7e Mon Sep 17 00:00:00 2001 From: Francis Dong Date: Thu, 16 Mar 2023 14:31:47 +0800 Subject: [PATCH 03/10] Support HMAC algorithm functions #470 --- .../java/com/fizzgate/fizz/function/CodecFunc.java | 12 ++++++------ .../com/fizzgate/fizz/function/CodecFuncTests.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java b/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java index 8044e04..23553cc 100644 --- a/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java +++ b/fizz-core/src/main/java/com/fizzgate/fizz/function/CodecFunc.java @@ -189,27 +189,27 @@ public class CodecFunc implements IFunc { } } - public String hmacMd5(String secretKey, String data) { + public String hmacMd5(String data, String secretKey) { return new HmacUtils(HmacAlgorithms.HMAC_MD5, secretKey).hmacHex(data); } - public String hmacSha1(String secretKey, String data) { + public String hmacSha1(String data, String secretKey) { return new HmacUtils(HmacAlgorithms.HMAC_SHA_1, secretKey).hmacHex(data); } - public String hmacSha224(String secretKey, String data) { + public String hmacSha224(String data, String secretKey) { return new HmacUtils(HmacAlgorithms.HMAC_SHA_224, secretKey).hmacHex(data); } - public String hmacSha256(String secretKey, String data) { + public String hmacSha256(String data, String secretKey) { return new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secretKey).hmacHex(data); } - public String hmacSha384(String secretKey, String data) { + public String hmacSha384(String data, String secretKey) { return new HmacUtils(HmacAlgorithms.HMAC_SHA_384, secretKey).hmacHex(data); } - public String hmacSha512(String secretKey, String data) { + public String hmacSha512(String data, String secretKey) { return new HmacUtils(HmacAlgorithms.HMAC_SHA_512, secretKey).hmacHex(data); } diff --git a/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java b/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java index 4c79872..0c1609b 100644 --- a/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java +++ b/fizz-core/src/test/java/com/fizzgate/fizz/function/CodecFuncTests.java @@ -125,7 +125,7 @@ class CodecFuncTests { @Test void testHmacSha256() { - String funcExpression = "fn.codec.hmacSha256(\"635e8562b968bc05bb80cacf124ebd53285280ee6845df0000faa33acafc38f0\", \"12345678123456781234567812345678\")"; + String funcExpression = "fn.codec.hmacSha256(\"12345678123456781234567812345678\", \"635e8562b968bc05bb80cacf124ebd53285280ee6845df0000faa33acafc38f0\")"; Object result = FuncExecutor.getInstance().exec(null, funcExpression); assertEquals("c61be0237ec186df1c5f51425e607093b260a76e5de43a62cb3e821103303990", result.toString()); } From 8c9ba12db6b5f2f003c4be47f8552501b770a9c7 Mon Sep 17 00:00:00 2001 From: hongqiaowei Date: Sat, 4 Mar 2023 11:43:05 +0800 Subject: [PATCH 04/10] Fix flow control problem --- fizz-bootstrap/pom.xml | 4 +- fizz-common/pom.xml | 2 +- fizz-core/pom.xml | 2 +- .../filter/FilterExceptionHandlerConfig.java | 14 +- .../com/fizzgate/filter/FizzLogFilter.java | 4 +- .../fizzgate/filter/FlowControlFilter.java | 126 +++++++++--------- .../com/fizzgate/filter/PreprocessFilter.java | 19 ++- .../java/com/fizzgate/filter/RouteFilter.java | 106 +++++++-------- .../plugin/FizzPluginFilterChain.java | 12 ++ .../com/fizzgate/plugin/PluginFilter.java | 11 +- .../plugin/auth/AuthPluginFilter.java | 1 - .../plugin/requestbody/RequestBodyPlugin.java | 23 +++- .../plugin/stat/StatPluginFilter.java | 1 + .../com/fizzgate/proxy/FizzWebClient.java | 10 +- .../java/com/fizzgate/stats/FlowStat.java | 32 ++--- fizz-plugin/pom.xml | 2 +- fizz-spring-boot-starter/pom.xml | 2 +- pom.xml | 38 +++++- 18 files changed, 231 insertions(+), 178 deletions(-) diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index f30a1a4..b95c7f0 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -6,7 +6,7 @@ fizz-gateway-community com.fizzgate - 2.7.1 + 2.7.2-SNAPSHOT ../pom.xml @@ -18,7 +18,7 @@ Dragonfruit-SR3 Dysprosium-SR25 5.3.7.RELEASE - 4.1.89.Final + 4.1.90.Final 4.4.16 2.17.2 1.7.36 diff --git a/fizz-common/pom.xml b/fizz-common/pom.xml index 9953932..e3e6140 100644 --- a/fizz-common/pom.xml +++ b/fizz-common/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.1 + 2.7.2-SNAPSHOT ../pom.xml 4.0.0 diff --git a/fizz-core/pom.xml b/fizz-core/pom.xml index d4278cd..4f67eed 100644 --- a/fizz-core/pom.xml +++ b/fizz-core/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.1 + 2.7.2-SNAPSHOT ../pom.xml 4.0.0 diff --git a/fizz-core/src/main/java/com/fizzgate/filter/FilterExceptionHandlerConfig.java b/fizz-core/src/main/java/com/fizzgate/filter/FilterExceptionHandlerConfig.java index c71bf75..e773488 100644 --- a/fizz-core/src/main/java/com/fizzgate/filter/FilterExceptionHandlerConfig.java +++ b/fizz-core/src/main/java/com/fizzgate/filter/FilterExceptionHandlerConfig.java @@ -56,13 +56,19 @@ public class FilterExceptionHandlerConfig { public static class FilterExceptionHandler implements WebExceptionHandler { - private static final Logger log = LoggerFactory.getLogger(FilterExceptionHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(FilterExceptionHandler.class); private static final String filterExceptionHandler = "filterExceptionHandler"; @Override public Mono handle(ServerWebExchange exchange, Throwable t) { exchange.getAttributes().put(WebUtils.ORIGINAL_ERROR, t); String traceId = WebUtils.getTraceId(exchange); + + if (LOGGER.isDebugEnabled()) { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + LOGGER.debug(Consts.S.EMPTY, t); + } + ServerHttpResponse resp = exchange.getResponse(); if (SystemConfig.FIZZ_ERR_RESP_HTTP_STATUS_ENABLE) { if (t instanceof ResponseStatusException) { @@ -113,9 +119,8 @@ public class FilterExceptionHandlerConfig { if (t instanceof FizzRuntimeException) { FizzRuntimeException ex = (FizzRuntimeException) t; - // log.error(traceId + ' ' + tMsg, LogService.BIZ_ID, traceId, ex); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); - log.error(traceId + ' ' + tMsg, ex); + LOGGER.error(tMsg, ex); respHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); RespEntity rs = null; if (ex.getStepContext() != null && ex.getStepContext().returnContext()) { @@ -132,9 +137,8 @@ public class FilterExceptionHandlerConfig { if (fc == null) { // t came from flow control filter StringBuilder b = ThreadContext.getStringBuilder(); WebUtils.request2stringBuilder(exchange, b); - // log.error(b.toString(), LogService.BIZ_ID, traceId, t); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); - log.error(b.toString(), t); + LOGGER.error(b.toString(), t); String s = WebUtils.jsonRespBody(HttpStatus.INTERNAL_SERVER_ERROR.value(), tMsg, traceId); respHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); vm = resp.writeWith(Mono.just(resp.bufferFactory().wrap(s.getBytes()))); diff --git a/fizz-core/src/main/java/com/fizzgate/filter/FizzLogFilter.java b/fizz-core/src/main/java/com/fizzgate/filter/FizzLogFilter.java index 9878ce4..9fa7e0b 100644 --- a/fizz-core/src/main/java/com/fizzgate/filter/FizzLogFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/filter/FizzLogFilter.java @@ -51,14 +51,14 @@ public class FizzLogFilter implements WebFilter { long start = System.currentTimeMillis(); return chain.filter(exchange).doFinally( (c) -> { - if (log.isInfoEnabled()) { + if (log.isDebugEnabled()) { StringBuilder b = ThreadContext.getStringBuilder(); WebUtils.request2stringBuilder(exchange, b); b.append(resp).append(exchange.getResponse().getStatusCode()) .append(in) .append(System.currentTimeMillis() - start); // log.info(b.toString(), LogService.BIZ_ID, WebUtils.getTraceId(exchange)); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, WebUtils.getTraceId(exchange)); - log.info(b.toString()); + log.debug(b.toString()); } } ); diff --git a/fizz-core/src/main/java/com/fizzgate/filter/FlowControlFilter.java b/fizz-core/src/main/java/com/fizzgate/filter/FlowControlFilter.java index 6446d11..8eb7bd3 100644 --- a/fizz-core/src/main/java/com/fizzgate/filter/FlowControlFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/filter/FlowControlFilter.java @@ -17,19 +17,6 @@ package com.fizzgate.filter; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.server.WebFilterChain; - import com.fizzgate.config.SystemConfig; import com.fizzgate.monitor.FizzMonitorService; import com.fizzgate.plugin.auth.ApiConfigService; @@ -44,7 +31,19 @@ import com.fizzgate.stats.degrade.DegradeRule; import com.fizzgate.stats.ratelimit.ResourceRateLimitConfig; import com.fizzgate.stats.ratelimit.ResourceRateLimitConfigService; import com.fizzgate.util.*; - +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; import reactor.core.publisher.SignalType; @@ -63,7 +62,7 @@ public class FlowControlFilter extends FizzWebFilter { public static final String FLOW_CONTROL_FILTER = "flowControlFilter"; - private static final Logger log = LoggerFactory.getLogger(FlowControlFilter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(FlowControlFilter.class); private static final String admin = "admin"; @@ -160,7 +159,6 @@ public class FlowControlFilter extends FizzWebFilter { if (!favReq && flowControlFilterProperties.isFlowControl() && !adminReq && !proxyTestReq && !fizzApiReq) { String traceId = WebUtils.getTraceId(exchange); - // LogService.setBizId(traceId); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); if (!apiConfigService.serviceConfigMap.containsKey(service)) { String json = WebUtils.jsonRespBody(HttpStatus.FORBIDDEN.value(), "no service " + service + " in flow config", traceId); @@ -178,12 +176,10 @@ public class FlowControlFilter extends FizzWebFilter { }); if (result != null && !result.isSuccess()) { - long currentTimeMillis = System.currentTimeMillis(); String blockedResourceId = result.getBlockedResourceId(); if (BlockType.CIRCUIT_BREAK == result.getBlockType()) { fizzMonitorService.alarm(service, path, FizzMonitorService.CIRCUIT_BREAK_ALARM, null); - // log.info("{} trigger {} circuit breaker limit", traceId, blockedResourceId, LogService.BIZ_ID, traceId); - log.info("{} trigger {} circuit breaker limit", traceId, blockedResourceId); + LOGGER.info("{} trigger {} circuit breaker limit", traceId, blockedResourceId); String responseContentType = flowControlFilterProperties.getDegradeDefaultResponseContentType(); String responseContent = flowControlFilterProperties.getDegradeDefaultResponseContent(); @@ -214,12 +210,10 @@ public class FlowControlFilter extends FizzWebFilter { } else { if (BlockType.CONCURRENT_REQUEST == result.getBlockType()) { fizzMonitorService.alarm(service, path, FizzMonitorService.RATE_LIMIT_ALARM, concurrents); - // log.info("{} exceed {} flow limit, blocked by maximum concurrent requests", traceId, blockedResourceId, LogService.BIZ_ID, traceId); - log.info("{} exceed {} flow limit, blocked by maximum concurrent requests", traceId, blockedResourceId); + LOGGER.info("{} exceed {} flow limit, blocked by maximum concurrent requests", traceId, blockedResourceId); } else { fizzMonitorService.alarm(service, path, FizzMonitorService.RATE_LIMIT_ALARM, qps); - // log.info("{} exceed {} flow limit, blocked by maximum QPS", traceId, blockedResourceId, LogService.BIZ_ID, traceId); - log.info("{} exceed {} flow limit, blocked by maximum QPS", traceId, blockedResourceId); + LOGGER.info("{} exceed {} flow limit, blocked by maximum QPS", traceId, blockedResourceId); } ResourceRateLimitConfig c = resourceRateLimitConfigService.getResourceRateLimitConfig(ResourceIdUtils.NODE_RESOURCE); @@ -240,42 +234,50 @@ public class FlowControlFilter extends FizzWebFilter { return resp.writeWith(Mono.just(resp.bufferFactory().wrap(rc.getBytes()))); } } else { - long start = System.currentTimeMillis(); - setTraceId(exchange); - String finalService = service; - String finalPath = path; - return chain.filter(exchange).doFinally(s -> { - long rt = System.currentTimeMillis() - start; - CircuitBreaker cb = exchange.getAttribute(CircuitBreaker.DETECT_REQUEST); - HttpStatus statusCode = exchange.getResponse().getStatusCode(); - Throwable t = exchange.getAttribute(WebUtils.ORIGINAL_ERROR); - if (t instanceof TimeoutException) { - statusCode = HttpStatus.GATEWAY_TIMEOUT; - } - // if (s == SignalType.ON_ERROR || statusCode.is4xxClientError() || statusCode.is5xxServerError()) { - if (s == SignalType.ON_ERROR || statusCode.is5xxServerError()) { - flowStat.addRequestRT(resourceConfigs, currentTimeSlot, rt, false, statusCode); - if (cb != null) { - cb.transit(CircuitBreaker.State.RESUME_DETECTIVE, CircuitBreaker.State.OPEN, currentTimeSlot, flowStat); - } - if (statusCode == HttpStatus.GATEWAY_TIMEOUT) { - fizzMonitorService.alarm(finalService, finalPath, FizzMonitorService.TIMEOUT_ALARM, t.getMessage()); - } else if (statusCode.is5xxServerError()) { - fizzMonitorService.alarm(finalService, finalPath, FizzMonitorService.ERROR_ALARM, String.valueOf(statusCode.value())); - } else if (s == SignalType.ON_ERROR && t != null) { - fizzMonitorService.alarm(finalService, finalPath, FizzMonitorService.ERROR_ALARM, t.getMessage()); - } - } else { - flowStat.addRequestRT(resourceConfigs, currentTimeSlot, rt, true, statusCode); - if (cb != null) { - cb.transit(CircuitBreaker.State.RESUME_DETECTIVE, CircuitBreaker.State.CLOSED, currentTimeSlot, flowStat); - } - } - }); + long start = System.currentTimeMillis(); + String finalService = service; + String finalPath = path; + return chain.filter(exchange).doFinally(s -> { + + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + long rt = System.currentTimeMillis() - start; + CircuitBreaker cb = exchange.getAttribute(CircuitBreaker.DETECT_REQUEST); + HttpStatus statusCode = exchange.getResponse().getStatusCode(); + Throwable t = exchange.getAttribute(WebUtils.ORIGINAL_ERROR); + if (t instanceof TimeoutException) { + statusCode = HttpStatus.GATEWAY_TIMEOUT; + } + + if (s == SignalType.ON_ERROR || statusCode.is5xxServerError()) { + flowStat.addRequestRT(resourceConfigs, currentTimeSlot, rt, false, statusCode); + if (cb != null) { + cb.transit(CircuitBreaker.State.RESUME_DETECTIVE, CircuitBreaker.State.OPEN, currentTimeSlot, flowStat); + } + if (statusCode == HttpStatus.GATEWAY_TIMEOUT) { + fizzMonitorService.alarm(finalService, finalPath, FizzMonitorService.TIMEOUT_ALARM, t.getMessage()); + } else if (statusCode.is5xxServerError()) { + fizzMonitorService.alarm(finalService, finalPath, FizzMonitorService.ERROR_ALARM, String.valueOf(statusCode.value())); + } else if (s == SignalType.ON_ERROR && t != null) { + fizzMonitorService.alarm(finalService, finalPath, FizzMonitorService.ERROR_ALARM, t.getMessage()); + } + } else { + flowStat.addRequestRT(resourceConfigs, currentTimeSlot, rt, true, statusCode); + if (cb != null) { + cb.transit(CircuitBreaker.State.RESUME_DETECTIVE, CircuitBreaker.State.CLOSED, currentTimeSlot, flowStat); + } + } + + if (s == SignalType.CANCEL) { + ClientResponse remoteResp = exchange.getAttribute("remoteResp"); + if (remoteResp != null) { + remoteResp.bodyToMono(Void.class).subscribe(); + LOGGER.warn("client cancel, and dispose remote response"); + } + } + }); } } - // setTraceId(exchange); return chain.filter(exchange); } @@ -340,15 +342,15 @@ public class FlowControlFilter extends FizzWebFilter { check = true; } } - if (log.isDebugEnabled()) { - log.debug("getResourceConfigItselfAndParents:\n" + JacksonUtils.writeValueAsString(rc) + '\n' + JacksonUtils.writeValueAsString(result)); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("getResourceConfigItselfAndParents:\n" + JacksonUtils.writeValueAsString(rc) + '\n' + JacksonUtils.writeValueAsString(result)); } return result; } private List getFlowControlConfigs(String app, String ip, String node, String service, String path) { - if (log.isDebugEnabled()) { - log.debug("get flow control configs by app={}, ip={}, node={}, service={}, path={}", app, ip, node, service, path); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("get flow control configs by app={}, ip={}, node={}, service={}, path={}", app, ip, node, service, path); } boolean hasHost = (StringUtils.isNotBlank(node) && !node.equals(ResourceIdUtils.NODE)); int sz = hasHost ? 10 : 9; @@ -377,8 +379,8 @@ public class FlowControlFilter extends FizzWebFilter { checkRateLimitConfigAndAddTo(resourceConfigs, b, null, ip, null, service, path, null); } - if (log.isDebugEnabled()) { - log.debug("resource configs: " + JacksonUtils.writeValueAsString(resourceConfigs)); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("resource configs: " + JacksonUtils.writeValueAsString(resourceConfigs)); } return resourceConfigs; } diff --git a/fizz-core/src/main/java/com/fizzgate/filter/PreprocessFilter.java b/fizz-core/src/main/java/com/fizzgate/filter/PreprocessFilter.java index 0a30972..1060b32 100644 --- a/fizz-core/src/main/java/com/fizzgate/filter/PreprocessFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/filter/PreprocessFilter.java @@ -17,6 +17,7 @@ package com.fizzgate.filter; +import com.fizzgate.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; @@ -35,10 +36,6 @@ import com.fizzgate.plugin.auth.GatewayGroup; import com.fizzgate.plugin.auth.GatewayGroupService; import com.fizzgate.plugin.stat.StatPluginFilter; import com.fizzgate.proxy.Route; -import com.fizzgate.util.ReactorUtils; -import com.fizzgate.util.Result; -import com.fizzgate.util.ThreadContext; -import com.fizzgate.util.WebUtils; import reactor.core.publisher.Mono; @@ -54,7 +51,7 @@ import java.util.function.Function; @Order(10) public class PreprocessFilter extends FizzWebFilter { - private static final Logger log = LoggerFactory.getLogger(PreprocessFilter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PreprocessFilter.class); public static final String PREPROCESS_FILTER = "preprocessFilter"; @@ -72,6 +69,12 @@ public class PreprocessFilter extends FizzWebFilter { @Override public Mono doFilter(ServerWebExchange exchange, WebFilterChain chain) { + String traceId = WebUtils.getTraceId(exchange); + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("preprocess filter start"); + } + Map fc = new HashMap<>(); fc.put(WebUtils.PREV_FILTER_RESULT, succFr); Map appendHdrs = new HashMap<>(8); Map eas = exchange.getAttributes(); eas.put(WebUtils.FILTER_CONTEXT, fc); @@ -85,8 +88,14 @@ public class PreprocessFilter extends FizzWebFilter { .thenReturn(ReactorUtils.Void) .flatMap( v -> { + + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + Result auth = (Result) WebUtils.getFilterResultDataItem(exchange, AuthPluginFilter.AUTH_PLUGIN_FILTER, AuthPluginFilter.RESULT); if (auth.code == Result.FAIL) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("preprocess filter end 403"); + } return WebUtils.responseError(exchange, HttpStatus.FORBIDDEN.value(), auth.msg); } ApiConfig ac = auth.data; diff --git a/fizz-core/src/main/java/com/fizzgate/filter/RouteFilter.java b/fizz-core/src/main/java/com/fizzgate/filter/RouteFilter.java index 65d9863..8ea9fdd 100644 --- a/fizz-core/src/main/java/com/fizzgate/filter/RouteFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/filter/RouteFilter.java @@ -17,11 +17,22 @@ package com.fizzgate.filter; +import com.fizzgate.config.SystemConfig; +import com.fizzgate.plugin.auth.ApiConfig; +import com.fizzgate.proxy.FizzWebClient; +import com.fizzgate.proxy.Route; +import com.fizzgate.proxy.dubbo.ApacheDubboGenericService; +import com.fizzgate.proxy.dubbo.DubboInterfaceDeclaration; +import com.fizzgate.service_registry.RegistryCenterService; +import com.fizzgate.stats.FlowStat; +import com.fizzgate.stats.ResourceConfig; +import com.fizzgate.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; @@ -32,22 +43,13 @@ import org.springframework.web.reactive.function.BodyExtractors; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; - -import com.fizzgate.config.SystemConfig; -import com.fizzgate.plugin.auth.ApiConfig; -import com.fizzgate.proxy.FizzWebClient; -import com.fizzgate.proxy.Route; -import com.fizzgate.proxy.dubbo.ApacheDubboGenericService; -import com.fizzgate.proxy.dubbo.DubboInterfaceDeclaration; -import com.fizzgate.service_registry.RegistryCenterService; -import com.fizzgate.util.*; - import reactor.core.publisher.Mono; import javax.annotation.Resource; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Function; +import java.util.stream.Collectors; /** * @author hongqiaowei @@ -57,7 +59,7 @@ import java.util.function.Function; @Order(Ordered.LOWEST_PRECEDENCE) public class RouteFilter extends FizzWebFilter { - private static final Logger log = LoggerFactory.getLogger(RouteFilter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(RouteFilter.class); @Resource private FizzWebClient fizzWebClient; @@ -68,6 +70,9 @@ public class RouteFilter extends FizzWebFilter { @Resource private SystemConfig systemConfig; + @Resource + private FlowControlFilter flowControlFilter; + @Override public Mono doFilter(ServerWebExchange exchange, WebFilterChain chain) { @@ -77,16 +82,13 @@ public class RouteFilter extends FizzWebFilter { } else { Mono resp = WebUtils.getDirectResponse(exchange); if (resp == null) { // should not reach here - ServerHttpRequest clientReq = exchange.getRequest(); String traceId = WebUtils.getTraceId(exchange); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); String msg = traceId + ' ' + pfr.id + " fail"; if (pfr.cause == null) { - // log.error(msg, LogService.BIZ_ID, traceId); - log.error(msg); + LOGGER.error(msg); } else { - // log.error(msg, LogService.BIZ_ID, traceId, pfr.cause); - log.error(msg, pfr.cause); + LOGGER.error(msg, pfr.cause); } HttpStatus s = HttpStatus.INTERNAL_SERVER_ERROR; if (!SystemConfig.FIZZ_ERR_RESP_HTTP_STATUS_ENABLE) { @@ -101,8 +103,13 @@ public class RouteFilter extends FizzWebFilter { private Mono doFilter0(ServerWebExchange exchange, WebFilterChain chain) { - ServerHttpRequest req = exchange.getRequest(); String traceId = WebUtils.getTraceId(exchange); + if (LOGGER.isDebugEnabled()) { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + LOGGER.debug("route filter start"); + } + + ServerHttpRequest req = exchange.getRequest(); Route route = exchange.getAttribute(WebUtils.ROUTE); HttpHeaders hdrs = null; @@ -112,32 +119,17 @@ public class RouteFilter extends FizzWebFilter { } if (route == null) { - /*String pathQuery = WebUtils.getClientReqPathQuery(exchange); - return fizzWebClient.send2service(traceId, req.getMethod(), WebUtils.getClientService(exchange), pathQuery, hdrs, req.getBody(), 0, 0, 0) - .flatMap(genServerResponse(exchange));*/ - Map.Entry> pathQueryTemplate = WebUtils.getClientReqPathQueryTemplate(exchange).entrySet().iterator().next(); return fizzWebClient.send2service(traceId, req.getMethod(), WebUtils.getClientService(exchange), pathQueryTemplate.getKey(), hdrs, req.getBody(), 0, 0, 0, pathQueryTemplate.getValue().toArray(new String[0])) .flatMap(genServerResponse(exchange)); } else if (route.type == ApiConfig.Type.SERVICE_DISCOVERY) { - /*String pathQuery = getBackendPathQuery(req, route); - String svc = RegistryCenterService.getServiceNameSpace(route.registryCenter, route.backendService); - return fizzWebClient.send2service(traceId, route.method, svc, pathQuery, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval) - .flatMap(genServerResponse(exchange));*/ - Map.Entry> pathQueryTemplate = getBackendPathQueryTemplate(req, route).entrySet().iterator().next(); String svc = RegistryCenterService.getServiceNameSpace(route.registryCenter, route.backendService); return fizzWebClient.send2service(traceId, route.method, svc, pathQueryTemplate.getKey(), hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval, pathQueryTemplate.getValue().toArray(new String[0])) .flatMap(genServerResponse(exchange)); } else if (route.type == ApiConfig.Type.REVERSE_PROXY) { - /*String uri = ThreadContext.getStringBuilder().append(route.nextHttpHostPort) - .append(getBackendPathQuery(req, route)) - .toString(); - return fizzWebClient.send(traceId, route.method, uri, hdrs, req.getBody(), route.timeout, route.retryCount, route.retryInterval) - .flatMap(genServerResponse(exchange));*/ - Map.Entry> pathQueryTemplate = getBackendPathQueryTemplate(req, route).entrySet().iterator().next(); String uri = ThreadContext.getStringBuilder().append(route.nextHttpHostPort) .append(pathQueryTemplate.getKey()) @@ -150,20 +142,6 @@ public class RouteFilter extends FizzWebFilter { } } - private String getBackendPathQuery(ServerHttpRequest request, Route route) { - String qry = route.query; - if (qry == null) { - MultiValueMap queryParams = request.getQueryParams(); - if (queryParams.isEmpty()) { - return route.backendPath; - } else { - return route.backendPath + Consts.S.QUESTION + WebUtils.toQueryString(queryParams); - } - } else { - return route.backendPath + Consts.S.QUESTION + qry; - } - } - private Map> getBackendPathQueryTemplate(ServerHttpRequest request, Route route) { String qry = route.query; if (qry == null) { @@ -183,6 +161,7 @@ public class RouteFilter extends FizzWebFilter { private Function> genServerResponse(ServerWebExchange exchange) { return remoteResp -> { + String traceId = WebUtils.getTraceId(exchange); ServerHttpResponse clientResp = exchange.getResponse(); clientResp.setStatusCode(remoteResp.statusCode()); HttpHeaders clientRespHeaders = clientResp.getHeaders(); @@ -203,24 +182,36 @@ public class RouteFilter extends FizzWebFilter { } } ); - if (log.isDebugEnabled()) { + if (LOGGER.isDebugEnabled()) { StringBuilder b = ThreadContext.getStringBuilder(); - String traceId = WebUtils.getTraceId(exchange); WebUtils.response2stringBuilder(traceId, remoteResp, b); - // log.debug(b.toString(), LogService.BIZ_ID, traceId); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); - log.debug(b.toString()); + LOGGER.debug(b.toString()); } return clientResp.writeWith(remoteResp.body(BodyExtractors.toDataBuffers())) - .doOnError(throwable -> cleanup(remoteResp)).doOnCancel(() -> cleanup(remoteResp)); + .doOnError( + t -> { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + exchange.getAttributes().put("remoteResp", remoteResp); + LOGGER.error("response client error", t); + } + ) + .doOnCancel( + () -> { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + exchange.getAttributes().put("remoteResp", remoteResp); + LOGGER.error("client signal cancel"); + // cleanup(remoteResp); + } + ); }; } - private void cleanup(ClientResponse clientResponse) { - if (clientResponse != null) { - clientResponse.bodyToMono(Void.class).subscribe(); - } - } + // private void cleanup(ClientResponse clientResponse) { + // if (clientResponse != null) { + // clientResponse.bodyToMono(Void.class).subscribe(); + // } + // } private Mono dubboRpc(ServerWebExchange exchange, Route route) { final String[] ls = {null}; @@ -272,9 +263,8 @@ public class RouteFilter extends FizzWebFilter { if (ls[0] != null) { b.append('\n').append(ls[0]); } - // log.error(b.toString(), LogService.BIZ_ID, WebUtils.getTraceId(exchange), t); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, WebUtils.getTraceId(exchange)); - log.error(b.toString(), t); + LOGGER.error(b.toString(), t); } ) ; diff --git a/fizz-core/src/main/java/com/fizzgate/plugin/FizzPluginFilterChain.java b/fizz-core/src/main/java/com/fizzgate/plugin/FizzPluginFilterChain.java index ff50658..9fc6995 100644 --- a/fizz-core/src/main/java/com/fizzgate/plugin/FizzPluginFilterChain.java +++ b/fizz-core/src/main/java/com/fizzgate/plugin/FizzPluginFilterChain.java @@ -17,6 +17,9 @@ package com.fizzgate.plugin; +import com.fizzgate.util.Consts; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilterChain; @@ -38,6 +41,8 @@ import java.util.Map; public final class FizzPluginFilterChain { + private static final Logger LOGGER = LoggerFactory.getLogger(FizzPluginFilterChain.class); + private static final String pluginConfigsIt = "pcsit@"; public static final String WEB_FILTER_CHAIN = "wfc@"; @@ -62,6 +67,13 @@ public final class FizzPluginFilterChain { if (it.hasNext()) { PluginConfig pc = it.next(); FizzPluginFilter pf = Fizz.context.getBean(pc.plugin, FizzPluginFilter.class); + + String traceId = WebUtils.getTraceId(exchange); + if (LOGGER.isDebugEnabled()) { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + LOGGER.debug("{} start", pc.plugin); + } + Mono m = pf.filter(exchange, pc.config); if (pf instanceof PluginFilter) { boolean f = false; diff --git a/fizz-core/src/main/java/com/fizzgate/plugin/PluginFilter.java b/fizz-core/src/main/java/com/fizzgate/plugin/PluginFilter.java index de70d66..2665019 100644 --- a/fizz-core/src/main/java/com/fizzgate/plugin/PluginFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/plugin/PluginFilter.java @@ -43,7 +43,7 @@ import java.util.Map; @Deprecated public abstract class PluginFilter implements FizzPluginFilter { - private static final Logger log = LoggerFactory.getLogger(PluginFilter.class); + private final Logger LOGGER = LoggerFactory.getLogger(getClass()); @Override public Mono filter(ServerWebExchange exchange, Map config) { @@ -55,9 +55,8 @@ public abstract class PluginFilter implements FizzPluginFilter { FilterResult pfr = WebUtils.getPrevFilterResult(exchange); String traceId = WebUtils.getTraceId(exchange); ThreadContext.put(Consts.TRACE_ID, traceId); - if (log.isDebugEnabled()) { - // log.debug(traceId + ' ' + this + ": " + pfr.id + " execute " + (pfr.success ? "success" : "fail"), LogService.BIZ_ID, traceId); - log.debug(traceId + ' ' + this + ": " + pfr.id + " execute " + (pfr.success ? "success" : "fail")); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("{} execute {}", pfr.id, pfr.success ? "success" : "fail"); } if (pfr.success) { return doFilter(exchange, config, fixedConfig); @@ -65,9 +64,9 @@ public abstract class PluginFilter implements FizzPluginFilter { if (WebUtils.getDirectResponse(exchange) == null) { // should not reach here String msg = traceId + ' ' + pfr.id + " fail"; if (pfr.cause == null) { - log.error(msg); + LOGGER.error(msg); } else { - log.error(msg, pfr.cause); + LOGGER.error(msg, pfr.cause); } HttpStatus s = HttpStatus.OK; if (SystemConfig.FIZZ_ERR_RESP_HTTP_STATUS_ENABLE) { diff --git a/fizz-core/src/main/java/com/fizzgate/plugin/auth/AuthPluginFilter.java b/fizz-core/src/main/java/com/fizzgate/plugin/auth/AuthPluginFilter.java index 87312ca..1048548 100644 --- a/fizz-core/src/main/java/com/fizzgate/plugin/auth/AuthPluginFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/plugin/auth/AuthPluginFilter.java @@ -56,7 +56,6 @@ public class AuthPluginFilter extends PluginFilter { r -> { if (log.isDebugEnabled()) { String traceId = WebUtils.getTraceId(exchange); - // log.debug("{} req auth: {}", traceId, r, LogService.BIZ_ID, traceId); ThreadContext.put(Consts.TRACE_ID, traceId); log.debug("{} req auth: {}", traceId, r); } diff --git a/fizz-core/src/main/java/com/fizzgate/plugin/requestbody/RequestBodyPlugin.java b/fizz-core/src/main/java/com/fizzgate/plugin/requestbody/RequestBodyPlugin.java index 542b034..2a53c12 100644 --- a/fizz-core/src/main/java/com/fizzgate/plugin/requestbody/RequestBodyPlugin.java +++ b/fizz-core/src/main/java/com/fizzgate/plugin/requestbody/RequestBodyPlugin.java @@ -46,13 +46,19 @@ import java.util.Map; @Component(RequestBodyPlugin.REQUEST_BODY_PLUGIN) public class RequestBodyPlugin implements FizzPluginFilter { - private static final Logger log = LoggerFactory.getLogger(RequestBodyPlugin.class); + private final Logger LOGGER = LoggerFactory.getLogger(getClass()); public static final String REQUEST_BODY_PLUGIN = "requestBodyPlugin"; @Override public Mono filter(ServerWebExchange exchange, Map config) { + // String traceId = WebUtils.getTraceId(exchange); + // if (LOGGER.isDebugEnabled()) { + // org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + // LOGGER.debug("{} start", getClass().getSimpleName()); + // } + ServerHttpRequest req = exchange.getRequest(); if (req instanceof FizzServerHttpRequestDecorator) { return doFilter(exchange, config); @@ -76,18 +82,21 @@ public class RequestBodyPlugin implements FizzPluginFilter { if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) { newExchange = new FizzServerWebExchangeDecorator(mutatedExchange); } - if (log.isDebugEnabled()) { - String traceId = WebUtils.getTraceId(exchange); - // log.debug("{} request is decorated", traceId, LogService.BIZ_ID, traceId); - ThreadContext.put(Consts.TRACE_ID, traceId); - log.debug("{} request is decorated", traceId); - } + // if (LOGGER.isDebugEnabled()) { + // ThreadContext.put(Consts.TRACE_ID, traceId); + // LOGGER.debug("{} request is decorated", traceId); + // } return doFilter(newExchange, config); } ); } public Mono doFilter(ServerWebExchange exchange, Map config) { + String traceId = WebUtils.getTraceId(exchange); + if (LOGGER.isDebugEnabled()) { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); + LOGGER.debug("{} end", getClass().getSimpleName()); + } return FizzPluginFilterChain.next(exchange); } } diff --git a/fizz-core/src/main/java/com/fizzgate/plugin/stat/StatPluginFilter.java b/fizz-core/src/main/java/com/fizzgate/plugin/stat/StatPluginFilter.java index e5ed774..c12a54f 100644 --- a/fizz-core/src/main/java/com/fizzgate/plugin/stat/StatPluginFilter.java +++ b/fizz-core/src/main/java/com/fizzgate/plugin/stat/StatPluginFilter.java @@ -90,6 +90,7 @@ public class StatPluginFilter extends PluginFilter { accessStat.reqTime = System.currentTimeMillis(); accessStat.reqs++; if (LOGGER.isDebugEnabled()) { + org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, WebUtils.getTraceId(exchange)); LOGGER.debug("update access stat: {}, which request at {}", accessStat, DateTimeUtils.convert(accessStat.reqTime, Consts.DP.DP19)); } } diff --git a/fizz-core/src/main/java/com/fizzgate/proxy/FizzWebClient.java b/fizz-core/src/main/java/com/fizzgate/proxy/FizzWebClient.java index a29fc01..a430b74 100644 --- a/fizz-core/src/main/java/com/fizzgate/proxy/FizzWebClient.java +++ b/fizz-core/src/main/java/com/fizzgate/proxy/FizzWebClient.java @@ -220,7 +220,6 @@ public class FizzWebClient { if (log.isDebugEnabled()) { StringBuilder b = ThreadContext.getStringBuilder(); WebUtils.request2stringBuilder(traceId, method, uri, headers, null, b); - // log.debug(b.toString(), LogService.BIZ_ID, traceId); org.apache.logging.log4j.ThreadContext.put(Consts.TRACE_ID, traceId); log.debug(b.toString()); } @@ -243,10 +242,6 @@ public class FizzWebClient { } setHostHeader(uri, hdrs); if (systemConfig.isFizzWebClientXForwardedForEnable()) { - List values = hdrs.get(X_FORWARDED_FOR); - /* if (CollectionUtils.isEmpty(values)) { - hdrs.add(X_FORWARDED_FOR, WebUtils.getOriginIp(null)); - } */ if (systemConfig.isFizzWebClientXForwardedForAppendGatewayIp()) { hdrs.add(X_FORWARDED_FOR, NetworkUtils.getServerIp()); } @@ -269,8 +264,9 @@ public class FizzWebClient { Mono cr = req.exchange(); if (timeout == 0) { - if (systemConfig.getRouteTimeout() != 0) { - timeout = systemConfig.getRouteTimeout(); + long systemConfigRouteTimeout = systemConfig.getRouteTimeout(); + if (systemConfigRouteTimeout != 0) { + timeout = systemConfigRouteTimeout; } } if (timeout > 0) { diff --git a/fizz-core/src/main/java/com/fizzgate/stats/FlowStat.java b/fizz-core/src/main/java/com/fizzgate/stats/FlowStat.java index 16417ec..919177a 100644 --- a/fizz-core/src/main/java/com/fizzgate/stats/FlowStat.java +++ b/fizz-core/src/main/java/com/fizzgate/stats/FlowStat.java @@ -17,8 +17,20 @@ package com.fizzgate.stats; -import java.util.*; +import com.fizzgate.stats.circuitbreaker.CircuitBreakManager; +import com.fizzgate.stats.circuitbreaker.CircuitBreaker; +import com.fizzgate.util.Consts; +import com.fizzgate.util.ResourceIdUtils; +import com.fizzgate.util.WebUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ServerWebExchange; + +import java.util.ArrayList; +import java.util.List; import java.util.Map.Entry; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; @@ -26,17 +38,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.BiFunction; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.http.HttpStatus; -import org.springframework.web.server.ServerWebExchange; - -import com.fizzgate.stats.circuitbreaker.CircuitBreakManager; -import com.fizzgate.stats.circuitbreaker.CircuitBreaker; -import com.fizzgate.util.ResourceIdUtils; -import com.fizzgate.util.WebUtils; +import java.util.stream.Collectors; /** * Flow Statistic @@ -524,7 +526,7 @@ public class FlowStat { long slotInterval = slotIntervalInSec * 1000; if (resourceId == null) { - Set> entrys = resourceStats.entrySet(); + Set> entrys = resourceStats.entrySet(); for (Entry entry : entrys) { String rid = entry.getKey(); ResourceTimeWindowStat resourceWin = new ResourceTimeWindowStat(rid); @@ -585,7 +587,7 @@ public class FlowStat { } }*/ for (long i = lastSlotId; i < slotId;) { - Set> entrys = stat.resourceStats.entrySet(); + Set> entrys = stat.resourceStats.entrySet(); for (Entry entry : entrys) { String resourceId = entry.getKey(); ConcurrentMap timeSlots = entry.getValue().getTimeSlots(); @@ -649,7 +651,7 @@ public class FlowStat { long curTimeSlotId = stat.currentTimeSlotId(); if (lastTimeSlotId == null || lastTimeSlotId.longValue() != curTimeSlotId) { // log.debug("PeakConcurrentJob start"); - Set> entrys = stat.resourceStats.entrySet(); + Set> entrys = stat.resourceStats.entrySet(); for (Entry entry : entrys) { String resource = entry.getKey(); // log.debug("PeakConcurrentJob: resourceId={} slotId=={}", resourceId, diff --git a/fizz-plugin/pom.xml b/fizz-plugin/pom.xml index 1c192eb..52ec30d 100644 --- a/fizz-plugin/pom.xml +++ b/fizz-plugin/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.1 + 2.7.2-SNAPSHOT ../pom.xml 4.0.0 diff --git a/fizz-spring-boot-starter/pom.xml b/fizz-spring-boot-starter/pom.xml index 6cae080..eecfae5 100644 --- a/fizz-spring-boot-starter/pom.xml +++ b/fizz-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.1 + 2.7.2-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 142c19f..121ca24 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ Dysprosium-SR25 5.3.7.RELEASE 2.2.7.RELEASE - 4.1.89.Final + 4.1.90.Final 4.4.16 2.17.2 1.7.36 @@ -38,7 +38,7 @@ fizz-gateway-community ${project.artifactId} fizz gateway community - 2.7.1 + 2.7.2-SNAPSHOT pom fizz-common @@ -418,7 +418,7 @@ io.netty - netty-tcnative + netty-tcnative-classes ${netty-tcnative.version} @@ -428,7 +428,37 @@ io.netty - netty-tcnative-classes + netty-tcnative-boringssl-static + ${netty-tcnative.version} + linux-x86_64 + + + io.netty + netty-tcnative-boringssl-static + ${netty-tcnative.version} + linux-aarch_64 + + + io.netty + netty-tcnative-boringssl-static + ${netty-tcnative.version} + osx-x86_64 + + + io.netty + netty-tcnative-boringssl-static + ${netty-tcnative.version} + osx-aarch_64 + + + io.netty + netty-tcnative-boringssl-static + ${netty-tcnative.version} + windows-x86_64 + + + io.netty + netty-tcnative ${netty-tcnative.version} From 6c4fa7720d715f5f51cb1c1c6eefff8e04500f42 Mon Sep 17 00:00:00 2001 From: hongqiaowei Date: Sat, 25 Mar 2023 11:03:18 +0800 Subject: [PATCH 05/10] Upgrade spring Framework to 5.2.23 to fix cve-2023-20861 --- fizz-bootstrap/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index b95c7f0..1d22b7d 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -14,7 +14,7 @@ 2.2.13.RELEASE - 5.2.22.RELEASE + 5.2.23.RELEASE Dysprosium-SR25 5.3.7.RELEASE 2.2.7.RELEASE From 6383b4fd9e53dab87caf4584843c7e7879ff6d6b Mon Sep 17 00:00:00 2001 From: dxfeng10 Date: Mon, 20 Mar 2023 11:14:15 +0800 Subject: [PATCH 06/10] Update README.en-us.md --- README.en-us.md | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/README.en-us.md b/README.en-us.md index f2bcb7e..c0f2707 100644 --- a/README.en-us.md +++ b/README.en-us.md @@ -103,29 +103,7 @@ Starting from v1.3.0, the frontend and backend of the management backend are mer | Fizz-gateway-community | Fizz-manager-professional | |------------------------|---------------------------| | v1.3.0 | v1.3.0 | -| v1.4.0 | v1.4.0 | -| v1.4.1 | v1.4.1 | -| v1.5.0 | v1.5.0 | -| v1.5.1 | v1.5.1 | -| v2.0.0 | v2.0.0 | -| v2.1.0 | v2.1.0 | -| v2.2.0 | v2.2.0 | -| v2.2.1 | v2.2.1 | -| v2.2.3 | v2.2.3 | -| v2.3.0 | v2.3.0 | -| v2.3.2 | v2.3.2 | -| v2.3.3 | v2.3.3 | -| v2.4.0 | v2.4.0 | -| v2.4.1 | v2.4.1 | -| v2.5.0 | v2.5.0 | -| v2.5.1 | v2.5.1 | -| v2.5.2 | v2.5.2 | -| v2.6.0 | v2.6.0 | -| v2.6.1 | v2.6.1 | -| v2.6.2 | v2.6.2 | -| v2.6.3 | v2.6.3 | -| v2.6.4 | v2.6.4 | -| v2.6.5 | v2.6.5 | +| ... | ... | | v2.6.6 | v2.6.6 | | v2.7.0 | v2.7.0 | | v2.7.1 | v2.7.1 | From eaf89aaff40690fdaa2c3845ffd3d5317ebaedec Mon Sep 17 00:00:00 2001 From: hongqiaowei Date: Tue, 4 Apr 2023 14:33:22 +0800 Subject: [PATCH 07/10] Ip plugin --- fizz-bootstrap/pom.xml | 2 +- .../java/com/fizzgate/plugin/ip/IpPlugin.java | 148 ++++++++++ .../com/fizzgate/plugin/ip/PluginConfig.java | 18 ++ .../com/fizzgate/plugin/ip/RouterConfig.java | 19 ++ .../fizzgate/plugin/ip/util/ConfigUtils.java | 36 +++ .../fizzgate/plugin/ip/util/IpMatchUtils.java | 271 ++++++++++++++++++ .../com/fizzgate/plugin/ip/util/IpUtils.java | 191 ++++++++++++ pom.xml | 2 +- 8 files changed, 685 insertions(+), 2 deletions(-) create mode 100644 fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java create mode 100644 fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java create mode 100644 fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java create mode 100644 fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java create mode 100644 fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java create mode 100644 fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index 1d22b7d..9e1fb67 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -18,7 +18,7 @@ Dragonfruit-SR3 Dysprosium-SR25 5.3.7.RELEASE - 4.1.90.Final + 4.1.91.Final 4.4.16 2.17.2 1.7.36 diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java new file mode 100644 index 0000000..1bb537d --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/IpPlugin.java @@ -0,0 +1,148 @@ +package com.fizzgate.plugin.ip; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fizzgate.plugin.ip.util.ConfigUtils; +import com.fizzgate.plugin.ip.util.IpMatchUtils; +import com.fizzgate.plugin.ip.util.IpUtils; +import com.fizzgate.plugin.FizzPluginFilter; +import com.fizzgate.plugin.FizzPluginFilterChain; +import com.fizzgate.plugin.auth.ApiConfig; +import com.fizzgate.plugin.auth.ApiConfigService; +import com.fizzgate.util.WebUtils; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +import javax.annotation.Resource; +import java.net.SocketException; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static com.fizzgate.plugin.ip.RouterConfig.FieldName.*; + +/** + * @author hua.huang + */ +@Slf4j +@Component(value = IpPlugin.PLUGIN_NAME) +public class IpPlugin implements FizzPluginFilter { + public static final String PLUGIN_NAME = "fizz_plugin_ip"; + @Resource + private ObjectMapper objectMapper; + @Resource + private ApiConfigService apiConfigService; + + @Override + @SuppressWarnings("unchecked") + public Mono filter(ServerWebExchange exchange, Map config) { + RouterConfig routerConfig = routerConfig(exchange, config); + List pluginConfigItemList = null;/* pluginConfig(exchange, config); */ + if (access(exchange, routerConfig, pluginConfigItemList)) { + log.trace("pass..."); + return FizzPluginFilterChain.next(exchange); + } + log.trace("forbidden!"); + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.CONTENT_TYPE, routerConfig.getErrorRespContentType()); + return WebUtils.buildDirectResponse(exchange, HttpStatus.FORBIDDEN, + headers, routerConfig.getErrorRespContent()); + } + + private boolean access(ServerWebExchange exchange, + RouterConfig routerConfig, List pluginConfigItemList) { + Set fixedWhiteIpSet = Sets.newHashSet(); + Set fixedBlackIpSet = Sets.newHashSet(); + ApiConfig apiConfig = apiConfig(exchange); + Set gatewayGroups = (apiConfig == null || apiConfig.gatewayGroups == null) ? Sets.newHashSet() : apiConfig.gatewayGroups; + /* if (!CollectionUtils.isEmpty(pluginConfigItemList)) { + for (PluginConfig.Item fixedConfigItem : pluginConfigItemList) { + if (gatewayGroups.contains(fixedConfigItem.getGwGroup())) { + fixedWhiteIpSet.addAll(IpMatchUtils.ipConfigList(fixedConfigItem.getWhiteIp())); + fixedBlackIpSet.addAll(IpMatchUtils.ipConfigList(fixedConfigItem.getBlackIp())); + } + } + } */ + Set whiteIpSet = ConfigUtils.string2set(routerConfig.getWhiteIp()); + Set blackIpSet = ConfigUtils.string2set(routerConfig.getBlackIp()); + + String ip = null; + try { + ip = IpUtils.getServerHttpRequestIp(exchange.getRequest()); + } catch (SocketException e) { + log.warn(e.getMessage(), e); + } + log.trace("clientIp:{}, fixedWhiteIpSet:{}, fixedBlackIpSet:{}, whiteIpSet:{}, blackIpSet:{}", + ip, fixedWhiteIpSet, fixedBlackIpSet, whiteIpSet, blackIpSet); + // 未获取到client ip,返回false + if (StringUtils.isBlank(ip)) { + return false; + } + + // 优先匹配路由级别配置,然后再匹配插件级别配置 + + // 路由级别::白名单匹配到就直接返回true + if (IpMatchUtils.match(ip, whiteIpSet)) { + return true; + } + // 路由级别::黑名单匹配到就直接返回false + if (IpMatchUtils.match(ip, blackIpSet)) { + return false; + } + // 插件级别::白名单匹配到就直接返回true + /* if (IpMatchUtils.match(ip, fixedWhiteIpSet)) { + return true; + } */ + // 插件级别::黑名单匹配到就直接返回false + /* if (IpMatchUtils.match(ip, fixedBlackIpSet)) { + return false; + } */ + // 路由级别和插件级别都没匹配到 + if (CollectionUtils.isEmpty(whiteIpSet) /* || CollectionUtils.isEmpty(fixedWhiteIpSet) */) { + // 都没有配置白名单,默认返回true + return true; + } else { + return false; + } + } + + private RouterConfig routerConfig(ServerWebExchange exchange, Map config) { + RouterConfig routerConfig = new RouterConfig(); + routerConfig.setErrorRespContentType((String) config.getOrDefault(ERROR_RESP_CONTENT_TYPE + , routerConfig.getErrorRespContentType())); + routerConfig.setErrorRespContent((String) config.getOrDefault(ERROR_RESP_CONTENT + , routerConfig.getErrorRespContent())); + routerConfig.setWhiteIp((String) config.getOrDefault(WHITE_IP, StringUtils.EMPTY)); + routerConfig.setBlackIp((String) config.getOrDefault(BLACK_IP, StringUtils.EMPTY)); + return routerConfig; + } + + private List pluginConfig(ServerWebExchange exchange, Map config) { + String fixedConfig = (String) config.get(com.fizzgate.plugin.PluginConfig.CUSTOM_CONFIG); + try { + PluginConfig pluginConfig = objectMapper.readValue(fixedConfig, PluginConfig.class); + if (pluginConfig != null && pluginConfig.getConfigs() != null) { + return pluginConfig.getConfigs(); + } + } catch (JsonProcessingException e) { + throw new RuntimeException(e.getMessage(), e); + } + return Lists.newArrayList(); + } + + private ApiConfig apiConfig(ServerWebExchange exchange) { + ServerHttpRequest req = exchange.getRequest(); + return apiConfigService.getApiConfig(WebUtils.getAppId(exchange), + WebUtils.getClientService(exchange), req.getMethod(), WebUtils.getClientReqPath(exchange)); + } + +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java new file mode 100644 index 0000000..c642c19 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/PluginConfig.java @@ -0,0 +1,18 @@ +package com.fizzgate.plugin.ip; + +import com.google.common.collect.Lists; +import lombok.Data; + +import java.util.List; + +@Data +public class PluginConfig { + private List configs = Lists.newArrayList(); + + @Data + public static class Item { + private String gwGroup; + private String whiteIp; + private String blackIp; + } +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java new file mode 100644 index 0000000..9db1741 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/RouterConfig.java @@ -0,0 +1,19 @@ +package com.fizzgate.plugin.ip; + +import lombok.Data; +import org.springframework.http.MediaType; + +@Data +public class RouterConfig { + private String errorRespContentType = MediaType.APPLICATION_JSON_UTF8_VALUE; + private String errorRespContent = "{\"msg\":\"非法IP\",\"code\":-1}"; + private String whiteIp; + private String blackIp; + + public interface FieldName { + String ERROR_RESP_CONTENT_TYPE = "errorRespContentType"; + String ERROR_RESP_CONTENT = "errorRespContent"; + String WHITE_IP = "whiteIp"; + String BLACK_IP = "blackIp"; + } +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java new file mode 100644 index 0000000..a29d03a --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/ConfigUtils.java @@ -0,0 +1,36 @@ +package com.fizzgate.plugin.ip.util; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Splitter; +import com.google.common.collect.Sets; +import org.apache.commons.lang3.StringUtils; + +import java.util.Set; +import java.util.stream.Collectors; + +public abstract class ConfigUtils { + public static final String DEFAULT_CHAR_MATCHER_ANY_OF = ",\n"; + + public static Set string2set(String strVal, String charMatcherAnyOf) { + Set finalSet = Sets.newHashSet(); + if (StringUtils.isBlank(strVal)) { + return finalSet; + } + charMatcherAnyOf = StringUtils.isBlank(charMatcherAnyOf) ? DEFAULT_CHAR_MATCHER_ANY_OF : charMatcherAnyOf; + Set set = Sets.newHashSet( + Splitter.on(CharMatcher.anyOf(charMatcherAnyOf)).trimResults().split(strVal)); + set = set.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet()); + for (String s : set) { + if (StringUtils.isBlank(s)) { + continue; + } + finalSet.add(StringUtils.trimToEmpty(s)); + } + return finalSet; + } + + public static Set string2set(String strVal) { + return string2set(strVal, DEFAULT_CHAR_MATCHER_ANY_OF); + } + +} diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java new file mode 100644 index 0000000..70124b6 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpMatchUtils.java @@ -0,0 +1,271 @@ +package com.fizzgate.plugin.ip.util; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Splitter; +import com.google.common.collect.Sets; +import inet.ipaddr.AddressStringException; +import inet.ipaddr.IPAddress; +import inet.ipaddr.IPAddressString; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +/** + * ipv4匹配工具 + */ +public final class IpMatchUtils { + // IP正则 + private static final Pattern IP_PATTERN = Pattern.compile( + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})\\." + "(1\\d{1,2}|2[0-4]\\d|25[0-5]|\\d{1,2})"); + public static final String DEFAULT_ALLOW_ALL_FLAG = "*";// 允许所有ip标志位 + public static final String DEFAULT_DENY_ALL_FLAG = "0"; // 禁止所有ip标志位 + private static final String RANGE_SPLITTER = "-"; // ip范围分隔符 + + /** + * 根据IP白名单设置获取可用的IP列表 + */ + public static Set ipConfigList(String allowIp) { + // 拆分出白名单正则 + Set set = Sets.newHashSet(Splitter.on(CharMatcher.anyOf(",\n")).trimResults().split(allowIp)); + set = set.stream().filter(StringUtils::isNotBlank).collect(Collectors.toSet()); + return ipConfigList(Sets.newHashSet(set)); + } + + /** + * 根据IP白名单设置获取可用的IP列表 + */ + public static Set ipConfigList(Set allowIpList) { + Set ipList = new HashSet<>(allowIpList.size()); + for (String allow : allowIpList) { + if (allow.contains("*")) { // 处理通配符 * + String[] ips = allow.split("\\."); + String[] from = new String[]{"0", "0", "0", "0"}; + String[] end = new String[]{"255", "255", "255", "255"}; + List tem = new ArrayList<>(); + for (int i = 0; i < ips.length; i++) + if (ips[i].contains("*")) { + tem = complete(ips[i]); + from[i] = null; + end[i] = null; + } else { + from[i] = ips[i]; + end[i] = ips[i]; + } + + StringBuilder fromIP = new StringBuilder(); + StringBuilder endIP = new StringBuilder(); + for (int i = 0; i < 4; i++) { + if (from[i] != null) { + fromIP.append(from[i]).append("."); + endIP.append(end[i]).append("."); + } else { + fromIP.append("[*]."); + endIP.append("[*]."); + } + } + fromIP.deleteCharAt(fromIP.length() - 1); + endIP.deleteCharAt(endIP.length() - 1); + + for (String s : tem) { + String ip = fromIP.toString().replace("[*]", s.split(";")[0]) + RANGE_SPLITTER + + endIP.toString().replace("[*]", s.split(";")[1]); + if (validate(ip)) { + ipList.add(ip); + } + } + } else if (allow.contains("/")) { // 处理 网段 xxx.xxx.xxx./24 + ipList.add(allow); + } else { // 处理单个 ip 或者 范围 + if (validate(allow)) { + ipList.add(allow); + } + } + + } + + return ipList; + } + + /** + * 对单个IP节点进行范围限定 + * + * @param arg + * @return 返回限定后的IP范围,格式为List[10;19, 100;199] + */ + private static List complete(String arg) { + List com = new ArrayList<>(); + int len = arg.length(); + if (len == 1) { + com.add("0;255"); + } else if (len == 2) { + String s1 = complete(arg, 1); + if (s1 != null) { + com.add(s1); + } + String s2 = complete(arg, 2); + if (s2 != null) { + com.add(s2); + } + } else { + String s1 = complete(arg, 1); + if (s1 != null) { + com.add(s1); + } + } + return com; + } + + private static String complete(String arg, int length) { + String from = ""; + String end = ""; + if (length == 1) { + from = arg.replace("*", "0"); + end = arg.replace("*", "9"); + } else { + from = arg.replace("*", "00"); + end = arg.replace("*", "99"); + } + if (Integer.parseInt(from) > 255) { + return null; + } + if (Integer.parseInt(end) > 255) { + end = "255"; + } + return from + ";" + end; + } + + /** + * 在添加至白名单时进行格式校验 + */ + private static boolean validate(String ip) { + String[] temp = ip.split(RANGE_SPLITTER); + for (String s : temp) { + if (!IP_PATTERN.matcher(s).matches()) { + return false; + } + } + return true; + } + + /** + * 根据IP,及可用Ip列表来判断ip是否包含在白名单之中 + */ + public static boolean match(String ip, Set ipList) { + if (CollectionUtils.isEmpty(ipList)) { + return false; + } + if (ipList.contains(ip)) { + return true; + } + IPAddress ipAddress = null; + try { + ipAddress = new IPAddressString(ip).toAddress(); + } catch (AddressStringException e) { + throw new RuntimeException(e); + } + for (String allow : ipList) { + if (allow.contains(RANGE_SPLITTER)) { // 处理 类似 192.168.0.0-192.168.2.1 + String[] tempAllow = allow.split(RANGE_SPLITTER); + String[] from = tempAllow[0].split("\\."); + String[] end = tempAllow[1].split("\\."); + String[] tag = ip.split("\\."); + boolean check = true; + for (int i = 0; i < 4; i++) { // 对IP从左到右进行逐段匹配 + int s = Integer.parseInt(from[i]); + int t = Integer.parseInt(tag[i]); + int e = Integer.parseInt(end[i]); + if (!(s <= t && t <= e)) { + check = false; + break; + } + } + if (check) { + return true; + } + } else if (allow.contains("/")) { // 处理 网段 xxx.xxx.xxx./24 + int splitIndex = allow.indexOf("/"); + // 取出子网段 + String ipSegment = allow.substring(0, splitIndex); // 192.168.3.0 + // 子网数 + String netmask = allow.substring(splitIndex + 1); // 24 + // ip 转二进制 + long ipLong = ipToLong(ip); + // 子网二进制 + long maskLong = (2L << 32 - 1) - (2L << (32 - Integer.parseInt(netmask)) - 1); + // ip与和子网相与 得到 网络地址 + String calcSegment = longToIP(ipLong & maskLong); + // 如果计算得出网络地址和库中网络地址相同 则合法 + if (ipSegment.equals(calcSegment)) { + return true; + } + } else if (allow.contains("*")) { + IPAddress rangeAddress = new IPAddressString(allow).getAddress(); + if (rangeAddress.contains(ipAddress)) { + return true; + } + } + } + return false; + } + + /** + * 根据IP地址,及IP白名单设置规则判断IP是否包含在白名单 + */ + public static boolean match(String ip, String ipWhiteConfig) { + if (null == ip || "".equals(ip)) { + return false; + } + // ip格式不对 + if (!IP_PATTERN.matcher(ip).matches()) { + return false; + } + if (DEFAULT_ALLOW_ALL_FLAG.equals(ipWhiteConfig)) { + return true; + } + if (DEFAULT_DENY_ALL_FLAG.equals(ipWhiteConfig)) { + return false; + } + Set ipList = ipConfigList(ipWhiteConfig); + return match(ip, ipList); + } + + /** + * 将 127.0.0.1形式的IP地址 转换成 10进制整数形式 + */ + private static long ipToLong(String strIP) { + long[] ip = new long[4]; + // 先找到IP地址字符串中.的位置 + int position1 = strIP.indexOf("."); + int position2 = strIP.indexOf(".", position1 + 1); + int position3 = strIP.indexOf(".", position2 + 1); + // 将每个.之间的字符串转换成整型 + ip[0] = Long.parseLong(strIP.substring(0, position1)); + ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2)); + ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3)); + ip[3] = Long.parseLong(strIP.substring(position3 + 1)); + return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3]; + } + + /** + * 将 10进制整数形式 转换成 127.0.0.1形式的IP地址 + */ + private static String longToIP(long longIP) { + // 直接右移24位 + return "" + (longIP >>> 24) + + "." + + // 将高8位置0,然后右移16位 + ((longIP & 0x00FFFFFF) >>> 16) + + "." + + ((longIP & 0x0000FFFF) >>> 8) + + "." + + (longIP & 0x000000FF); + } + +} \ No newline at end of file diff --git a/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java new file mode 100644 index 0000000..64917c7 --- /dev/null +++ b/fizz-plugin/src/main/java/com/fizzgate/plugin/ip/util/IpUtils.java @@ -0,0 +1,191 @@ +package com.fizzgate.plugin.ip.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.server.reactive.ServerHttpRequest; + +import java.net.*; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author huahua + */ +public class IpUtils { + + /* + * 取所有IP段的私有IP段 + * A类 私有地址 10.0.0.0---10.255.255.255 保留地址 127.0.0.0---127.255.255.255 + * B类 私有地址 172.16.0.0-172.31.255.255 + * C类 私有地址 192.168.0.0-192.168.255.255 + * D类 地址不分网络地址和主机地址 + * E类 地址不分网络地址和主机地址 + */ + private static long + aBegin = ipToLong("10.0.0.0"), + aEnd = ipToLong("10.255.255.255"), + bBegin = ipToLong("172.16.0.0"), + bEnd = ipToLong("172.31.255.255"), + cBegin = ipToLong("192.168.0.0"), + cEnd = ipToLong("192.168.255.255"), + saveBegin = ipToLong("127.0.0.0"), + saveEnd = ipToLong("127.255.255.255"); + + // 跟IP有关需要做判断的header参数 + private static String + CLIENT_IP = "clientip", + X_FORWARDED_FOR = "x-forwarded-for", + PROXY_CLIENT_IP = "proxy-client-ip", + WL_PROXY_CLIENT_IP = "wl-proxy-client-ip"; + private static Set ipHeaderNames = Sets.newHashSet(CLIENT_IP, X_FORWARDED_FOR, PROXY_CLIENT_IP, WL_PROXY_CLIENT_IP); + + public static String getServerHttpRequestIp(ServerHttpRequest request) throws SocketException { + // 防止在header中的参数名有大小写之分,重新将需要处理的参数值和内容装填入Map中 + Map> ipHeaders = Maps.newHashMap(); + Set>> headers = request.getHeaders().entrySet(); + for (Map.Entry> header : headers) { + String name = header.getKey(); + String lowerCaseName = name.toLowerCase(); + if (ipHeaderNames.contains(lowerCaseName)) { + List values = Lists.newArrayList(); + for (String headerValue : header.getValue()) { + if (StringUtils.indexOf(headerValue, ",") >= 0) { + String[] headerValueArr = StringUtils.split(headerValue, ","); + if (headerValueArr.length > 0) { + for (String s : headerValueArr) { + values.add(StringUtils.trimToEmpty(s)); + } + } + } else { + values.add(headerValue); + } + } + ipHeaders.put(lowerCaseName, values); // 装填key和value + } + } + //取正确的IP + String ipAddress = null; + // 取clientip + List clientIpList = ipHeaders.get(CLIENT_IP); // 取clientip与client-ip有区别 + ipAddress = fetchPublicIp(clientIpList); + // 若clientip为空或者是内网IP则取x-forwarded-for + if (StringUtils.isBlank(ipAddress)) { + List xForwardedIpList = ipHeaders.get(X_FORWARDED_FOR); + ipAddress = fetchPublicIp(xForwardedIpList); + } + // 若x-forwarded-for为空则取proxy-client-ip + if (StringUtils.isBlank(ipAddress)) { + List proxyClientIpList = ipHeaders.get(PROXY_CLIENT_IP); + ipAddress = fetchPublicIp(proxyClientIpList); + } + // 若proxy-client-ip为空则取wl-proxy-client-ip + if (StringUtils.isBlank(ipAddress)) { + List wlProxyClientIpList = ipHeaders.get(WL_PROXY_CLIENT_IP); + ipAddress = fetchPublicIp(wlProxyClientIpList); + } + // 若wl-proxy-client-ip为空则取RemoteAddr + if (StringUtils.isBlank(ipAddress)) { + InetSocketAddress inetSocketAddress = request.getRemoteAddress(); + if (inetSocketAddress != null) { + InetAddress inetAddress = inetSocketAddress.getAddress(); + if (inetAddress instanceof Inet4Address) { + ipAddress = inetAddress.getHostAddress(); + } + } + if (StringUtils.equals(ipAddress, "127.0.0.1")) { + // 根据网卡取本机配置的IP + ipAddress = getLocalIp(); + } + } + return ipAddress; + } + + public static String getLocalIp() throws SocketException { + Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); + InetAddress ip; + while (allNetInterfaces.hasMoreElements()) { + NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement(); + Enumeration addresses = netInterface.getInetAddresses(); + while (addresses.hasMoreElements()) { + ip = (InetAddress) addresses.nextElement(); + if (ip instanceof Inet4Address) { + return ip.getHostAddress(); + } + } + } + return ""; + } + + public static long localIpNumber() throws SocketException { + return ipToLong(getLocalIp()); + } + + private static long ipToLong(String ipAddress) { + long result = 0L; + String[] ipAddressInArray = ipAddress.split("\\."); + if (ipAddressInArray.length != 4) { + return 0; + } + for (int i = 3; i >= 0; i--) { + long ip = 0; + try { + ip = Long.parseLong(ipAddressInArray[3 - i]); + } catch (NumberFormatException e) { + // ignore + } + result |= ip << (i * 8); + } + return result; + } + + public static String fetchPublicIp(List ipAddressList) { + String ipAddress = null; + if (ipAddressList == null || ipAddressList.size() <= 0) { + return ipAddress; + } + for (String ip : ipAddressList) { + long ipNum = ipToLong(ip); + if (isIpAddress(ip) + && !isInner(ipNum, aBegin, aEnd) + && !isInner(ipNum, bBegin, bEnd) + && !isInner(ipNum, cBegin, cEnd) + && !isInner(ipNum, saveBegin, saveEnd)) { + ipAddress = ip; + break; + } + } + return ipAddress; + } + + public static boolean isInnerIP(String ipAddress) { + long ipNum = ipToLong(ipAddress); + return isInner(ipNum, aBegin, aEnd) || isInner(ipNum, bBegin, bEnd) || isInner(ipNum, cBegin, cEnd) || isInner(ipNum, saveBegin, saveEnd); + } + + private static boolean isInner(long userIp, long begin, long end) { + return (userIp >= begin) && (userIp <= end); + } + + /** + * 检验是否是合法的IP地址 + * + * @param address String IP地址 + * @return boolean IP地址是否合法 + */ + public static boolean isIpAddress(String address) { + if (StringUtils.isEmpty(address)) { + return false; + } + String regex = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}"; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(address); + return m.matches(); + } + +} diff --git a/pom.xml b/pom.xml index a6e3601..5309cc0 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ Dysprosium-SR25 5.3.7.RELEASE 2.2.7.RELEASE - 4.1.90.Final + 4.1.91.Final 4.4.16 2.17.2 1.7.36 From 39ebd94d561a2b5b0af5afe95b79b592eb4e3a7a Mon Sep 17 00:00:00 2001 From: Francis Dong Date: Mon, 10 Apr 2023 17:54:01 +0800 Subject: [PATCH 08/10] correct comment --- fizz-bootstrap/js/common.js | 4 ++-- fizz-bootstrap/src/main/resources/js/common.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fizz-bootstrap/js/common.js b/fizz-bootstrap/js/common.js index cccb334..c8eb437 100644 --- a/fizz-bootstrap/js/common.js +++ b/fizz-bootstrap/js/common.js @@ -166,11 +166,11 @@ var common = { }, /** - * 获取步骤中调用的接口的响应头 + * 获取步骤中调用的接口的响应体 * @param {*} ctx 上下文 【必填】 * @param {*} stepName 步骤名【必填】 * @param {*} requestName 请求的接口名 【必填】 - * @param {*} field 字段名 【选填】,不传时返回整个响应头 + * @param {*} field 字段名 【选填】,不传时返回整个响应体 */ getStepRespBody: function (ctx, stepName, requestName, field){ var resp = this.getStepResp(ctx, stepName, requestName); diff --git a/fizz-bootstrap/src/main/resources/js/common.js b/fizz-bootstrap/src/main/resources/js/common.js index cccb334..c8eb437 100644 --- a/fizz-bootstrap/src/main/resources/js/common.js +++ b/fizz-bootstrap/src/main/resources/js/common.js @@ -166,11 +166,11 @@ var common = { }, /** - * 获取步骤中调用的接口的响应头 + * 获取步骤中调用的接口的响应体 * @param {*} ctx 上下文 【必填】 * @param {*} stepName 步骤名【必填】 * @param {*} requestName 请求的接口名 【必填】 - * @param {*} field 字段名 【选填】,不传时返回整个响应头 + * @param {*} field 字段名 【选填】,不传时返回整个响应体 */ getStepRespBody: function (ctx, stepName, requestName, field){ var resp = this.getStepResp(ctx, stepName, requestName); From 0ad6cc2df33da043f93c5554f2b4ef6ecf0ea61f Mon Sep 17 00:00:00 2001 From: hongqiaowei Date: Mon, 10 Apr 2023 18:08:58 +0800 Subject: [PATCH 09/10] Release 2.7.2 --- README.en-us.md | 3 ++- README.md | 3 ++- docker-compose.yml | 6 +++--- fizz-bootstrap/pom.xml | 2 +- fizz-common/pom.xml | 2 +- fizz-core/pom.xml | 2 +- fizz-plugin/pom.xml | 2 +- fizz-spring-boot-starter/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.en-us.md b/README.en-us.md index c0f2707..5c7de49 100644 --- a/README.en-us.md +++ b/README.en-us.md @@ -4,7 +4,7 @@ English | [简体中文](./README.md)

- Version + Version Documentation @@ -107,6 +107,7 @@ Starting from v1.3.0, the frontend and backend of the management backend are mer | v2.6.6 | v2.6.6 | | v2.7.0 | v2.7.0 | | v2.7.1 | v2.7.1 | +| v2.7.2 | v2.7.2 | Please download the corresponding management backend version according to the version of the community version diff --git a/README.md b/README.md index 7c34a62..539f8cc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@

- Version + Version Documentation @@ -109,6 +109,7 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] | v2.6.6 | v2.6.6 | | v2.7.0 | v2.7.0 | | v2.7.1 | v2.7.1 | +| v2.7.2 | v2.7.2 | 请根据社区版的版本下载对应的管理后台版本 diff --git a/docker-compose.yml b/docker-compose.yml index 77d39ae..3436910 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.6" services: fizz-mysql: - image: "fizzgate/fizz-mysql:2.7.1" + image: "fizzgate/fizz-mysql:2.7.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.7.1" + image: "fizzgate/fizz-gateway-community:2.7.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.7.1" + image: "fizzgate/fizz-manager-professional:2.7.2" container_name: fizz-manager-professional restart: always hostname: fizz-manager-professional diff --git a/fizz-bootstrap/pom.xml b/fizz-bootstrap/pom.xml index 9e1fb67..7e46f76 100644 --- a/fizz-bootstrap/pom.xml +++ b/fizz-bootstrap/pom.xml @@ -6,7 +6,7 @@ fizz-gateway-community com.fizzgate - 2.7.2-SNAPSHOT + 2.7.2 ../pom.xml diff --git a/fizz-common/pom.xml b/fizz-common/pom.xml index e3e6140..b109203 100644 --- a/fizz-common/pom.xml +++ b/fizz-common/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.2-SNAPSHOT + 2.7.2 ../pom.xml 4.0.0 diff --git a/fizz-core/pom.xml b/fizz-core/pom.xml index 4f67eed..d35ef94 100644 --- a/fizz-core/pom.xml +++ b/fizz-core/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.2-SNAPSHOT + 2.7.2 ../pom.xml 4.0.0 diff --git a/fizz-plugin/pom.xml b/fizz-plugin/pom.xml index 52ec30d..c07b832 100644 --- a/fizz-plugin/pom.xml +++ b/fizz-plugin/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.2-SNAPSHOT + 2.7.2 ../pom.xml 4.0.0 diff --git a/fizz-spring-boot-starter/pom.xml b/fizz-spring-boot-starter/pom.xml index eecfae5..a73333b 100644 --- a/fizz-spring-boot-starter/pom.xml +++ b/fizz-spring-boot-starter/pom.xml @@ -5,7 +5,7 @@ fizz-gateway-community com.fizzgate - 2.7.2-SNAPSHOT + 2.7.2 ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 5309cc0..c1a0cd4 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ fizz-gateway-community ${project.artifactId} fizz gateway community - 2.7.2-SNAPSHOT + 2.7.2 pom fizz-common From 003f078a6e43c41c4656b9b3339e9bcda68bbff6 Mon Sep 17 00:00:00 2001 From: linwaiwai Date: Wed, 26 Apr 2023 17:42:42 +0800 Subject: [PATCH 10/10] update name Update README.md Update README.md Update README.en-us.md Update README.md Update README.md Update README.md --- README.en-us.md | 125 +++++++++++++++++----------------- README.md | 173 ++++++++++++++++++++++++++++-------------------- 2 files changed, 164 insertions(+), 134 deletions(-) diff --git a/README.en-us.md b/README.en-us.md index 5c7de49..4717f02 100644 --- a/README.en-us.md +++ b/README.en-us.md @@ -1,26 +1,26 @@ English | [简体中文](./README.md)

- +

Version - + Documentation - License: GPL--3.0 + License: AGPL--3.0 - - Java CI with Maven + + Java CI with Maven

- **latest QQ group**: 512164278 -## What 's Fizz Gateway? +## What 's FizzGate? -An Aggregation API Gateway in Java . Fizz Gateway is a Java-based microservice gateway that can realize hot service aggregation, automatic authorization selection, online service script coding, online testing, high-performance routing, API audit management and other purposes. It has a powerful The custom plug-in system can be extended by youself, and provides a friendly graphical configuration interface, which can quickly help enterprises to manage API services, reduce middle layer glue code, reduce coding investment, and improve the stability and security of API services. +An Aggregation API Gateway in Java . FizzGate is a Java-based microservice gateway that can realize hot service aggregation, automatic authorization selection, online service script coding, online testing, high-performance routing, API audit management and other purposes. It has a powerful The custom plug-in system can be extended by youself, and provides a friendly graphical configuration interface, which can quickly help enterprises to manage API services, reduce middle layer glue code, reduce coding investment, and improve the stability and security of API services. ## Demo @@ -33,17 +33,17 @@ health checking url:http://demo.fizzgate.com/admin/health API access:http://demo.fizzgate.com/proxy/[Service Name]/[API Path] -## Fizz's Design +## FizzGate's Design -## Fizz's typical scene +## FizzGate's typical scene ## Product Features -- Cluster management: Fizz gateway nodes are stateless with configuration information that is automatically synchronized, and horizontal expansion of nodes and multi-cluster deployment are supported. +- Cluster management: FizzGate nodes are stateless with configuration information that is automatically synchronized, and horizontal expansion of nodes and multi-cluster deployment are supported. - Service aggregation: supports hot http/dubbo/grpc service aggregation capabilities, support front-end and back-end coding, and update API anytime and anywhere; - Load balancing: supports round-robin load balancing; - Multiple Registration Center: supports discovery of back-end servers from the Eureka or Nacos registry; @@ -64,7 +64,7 @@ API access:http://demo.fizzgate.com/proxy/[Service Name]/[API Path] ## Benchmarks -We compare FIZZ with the major gateway products on the market, using the same environment and conditions, and the test objects are under single node. The Mock interface simulates a 20ms latency with a packet size of about 2K. +We compare FzzGate with the major gateway products on the market, using the same environment and conditions, and the test objects are under single node. The Mock interface simulates a 20ms latency with a packet size of about 2K. - Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.30GHz * 4 - Linux version 3.10.0-957.21.3.el7.x86_64 @@ -74,20 +74,20 @@ We compare FIZZ with the major gateway products on the market, using the same en | :------------------ | :------------------ | :-------: | :-------: | :-------: | :-------: | | Backend Service | direct access | 23540| 32.19 | 27325| 52.09 | | Traffic Gateway | kong
v2.4.1 | 15662 | 50.87 | 17152 | 84.3 | -| Application Gateway | fizz-gateway-community
v2.0.0 | 12206 | 65.76 | 12766 | 100.34 | +| Application Gateway | fizz-gateway-node
v2.0.0 | 12206 | 65.76 | 12766 | 100.34 | | Application Gateway | spring-cloud-gateway
v2.2.9 | 11323 | 68.57 | 10472 | 127.59 | | Application Gateway | shenyu
v2.3.0 | 9284 | 92.98 | 9939 | 148.61 | ## Version comparison -- Fizz-gateway-community: Community Edition +- fizz-gateway-node: Community Edition -- Fizz-manager-professional:Management backend professional version (backend) +- fizz-manager-professional:Management backend professional version (backend) -- Fizz-admin-professional:Management backend professional version (frontend) +- fizz-admin-professional:Management backend professional version (frontend) -| Fizz-gateway-community | Fizz-manager-professional | Fizz-admin-professional | +| fizz-gateway-node | fizz-manager-professional | fizz-admin-professional | | ---------------------- | ------------------------- | ----------------------- | | v1.0.0 | v1.0.0 | v1.0.0 | | v1.1.0 | v1.1.0 | v1.1.0 | @@ -96,11 +96,11 @@ We compare FIZZ with the major gateway products on the market, using the same en Starting from v1.3.0, the frontend and backend of the management backend are merged into one package -- Fizz-gateway-community: Community Edition +- fizz-gateway-node: Community Edition -- Fizz-manager-professional:Management backend professional version +- fizz-manager-professional:Management backend professional version -| Fizz-gateway-community | Fizz-manager-professional | +| fizz-gateway-node | fizz-manager-professional | |------------------------|---------------------------| | v1.3.0 | v1.3.0 | | ... | ... | @@ -127,7 +127,7 @@ Install the following dependent software: Dependent installation can refer to detailed deployment tutorial -### Install Fizz +### Install FizzGate #### 一、Install management backend @@ -149,7 +149,7 @@ installation method 1: binary package: Installation method 2: docker: -Download SQL script from page: https://github.com/fizzgate/fizz-gateway-community/releases/tag/{version} (replace {version} with corresponding version number) +Download SQL script from page: https://github.com/fizzgate/fizz-gateway-node/releases/tag/{version} (replace {version} with corresponding version number) For the first installation, execute the `fizz-manager-professional-{version}-mysql.sql` database script, upgrade from a low version to a high version, and choose to execute the corresponding upgrade script in the update directory @@ -178,7 +178,7 @@ docker run --rm -d -p 8000:8000 \ After the service is started, visit http://{deployment machine IP address}:8000/#/login, and log in with the super administrator account `admin` password `Aa123!` -#### 二、Install fizz-gateway-community community edition +#### 二、Install fizz-gateway-node community edition Description: @@ -188,7 +188,7 @@ Description: Installation method 1: binary package: -1. Download the latest binary package of fizz-gateway-community and upzip to a directory, modify the configuration of the configuration center, registry, and redis in the application.yml configuration file (redis configuration needs to be consistent with the management backend). +1. Download the latest binary package of fizz-gateway-node and upzip to a directory, modify the configuration of the configuration center, registry, and redis in the application.yml configuration file (redis configuration needs to be consistent with the management backend). 2. Modify the apollo connection and JVM memory configuration of the boot.sh script 3. Linux startup Execute `./boot.sh start` command to start the service, support start/stop/restart/status command 4. Windows startup Execute `.\boot.cmd start` command to start the service, support start/stop/restart/status command @@ -196,13 +196,13 @@ Installation method 1: binary package: Installation method 2: source code: 1. The latest code on the local clone warehouse, modify the configuration of the configuration center, registry, and redis in the application.yml configuration file (redis configuration needs to be consistent with the management backend) -2. Execute the Maven command `mvn clean package install -DskipTests=true` package in the project root directory fizz-gateway-community -3. Execute the Maven command `mvn clean package -DskipTests=true` package in the project directory fizz-gateway-community/fizz-bootstrap -4. Enter fizz-gateway-community/fizz-bootstrap/target/fizz-gateway-community directory and Execute `./boot.sh start` command to start the service, support start/stop/restart/status command +2. Execute the Maven command `mvn clean package install -DskipTests=true` package in the project root directory fizz-gateway-node +3. Execute the Maven command `mvn clean package -DskipTests=true` package in the project directory fizz-gateway-node/fizz-bootstrap +4. Enter fizz-gateway-node/fizz-bootstrap/target/fizz-gateway-node directory and Execute `./boot.sh start` command to start the service, support start/stop/restart/status command Installation method 3: docker: -1. Download docker image:docker pull fizzgate/fizz-gateway-community:{version} +1. Download docker image:docker pull fizzgate/fizz-gateway-node:{version} 2. Modify Redis configuration by env parameters and run with below docker command ```sh docker run --rm -d -p 8600:8600 \ @@ -210,88 +210,89 @@ docker run --rm -d -p 8600:8600 \ -e "aggregate.redis.port={your redis port}" \ -e "aggregate.redis.password={your redis password}" \ -e "aggregate.redis.database={your redis database}" \ -fizzgate/fizz-gateway-community:{version} +fizzgate/fizz-gateway-node:{version} ``` -or using external configuration file and output log to host server by mount volume, configuration file could be achieved from source code or binary package, create fizz-gateway-community/config and fizz-gateway-community/logs directories in host server, place application.yml and log4j2-spring.xml configuration files to config folder, run with below docker command in fizz-gateway-community folder: +or using external configuration file and output log to host server by mount volume, configuration file could be achieved from source code or binary package, create fizz-gateway-node/config and fizz-gateway-node/logs directories in host server, place application.yml and log4j2-spring.xml configuration files to config folder, run with below docker command in fizz-gateway-node folder: ```sh -cd fizz-gateway-community +cd fizz-gateway-node docker run --rm -d -p 8600:8600 \ --v $PWD/config:/opt/fizz-gateway-community/config \ --v $PWD/logs:/opt/fizz-gateway-community/logs fizzgate/fizz-gateway-community:{version} +-v $PWD/config:/opt/fizz-gateway-node/config \ +-v $PWD/logs:/opt/fizz-gateway-node/logs fizzgate/fizz-gateway-node:{version} ``` Finally visit the gateway, the address format is: http://127.0.0.1:8600/[Service name]/[API Path] ## Official technical exchange group -Fizz官方技术交流①群(已满) +FizzGate官方技术交流①群(已满) -Fizz官方技术交流②群(已满) +FizzGate官方技术交流②群(已满) -Fizz官方技术交流③群:512164278 +FizzGate官方技术交流③群:512164278 ## Related acticles -[服务器减少50%,研发效率提高86%,我们的管理型网关Fizz自研之路](https://www.infoq.cn/article/9wdfiOILJ0CYsVyBQFpl) +[服务器减少50%,研发效率提高86%,我们的管理型网关FizzGate自研之路](https://www.infoq.cn/article/9wdfiOILJ0CYsVyBQFpl) -[简单易用的微服务聚合网关首选:Fizz Gateway安装教程](https://my.oschina.net/linwaiwai/blog/4696224) +[简单易用的微服务聚合网关首选:FizzGate安装教程](https://my.oschina.net/linwaiwai/blog/4696224) -[大厂推荐使用的网关解密:Fizz Gateway管理后台使用教程](https://my.oschina.net/linwaiwai/blog/4696124) +[大厂推荐使用的网关解密:FizzGate管理后台使用教程](https://my.oschina.net/linwaiwai/blog/4696124) -[架构师效率快的终极原因:Fizz Gateway网关之服务编排](https://my.oschina.net/linwaiwai/blog/4696116) +[架构师效率快的终极原因:FizzGate网关之服务编排](https://my.oschina.net/linwaiwai/blog/4696116) -[高阶架构师支招:Fizz Gateway的插件开发](https://my.oschina.net/linwaiwai/blog/4696131) +[高阶架构师支招:FizzGate的插件开发](https://my.oschina.net/linwaiwai/blog/4696131) -[高阶程序员必备技能:Fizz Gateway网关的二次开发](https://my.oschina.net/linwaiwai/blog/4696133) +[高阶程序员必备技能:FizzGate网关的二次开发](https://my.oschina.net/linwaiwai/blog/4696133) -[Fizz网关入门教程-安装](https://zhuanlan.zhihu.com/p/501305059) +[FizzGate网关入门教程-安装](https://zhuanlan.zhihu.com/p/501305059) -[Fizz网关入门教程-路由初体验](https://zhuanlan.zhihu.com/p/501381970) +[FizzGate网关入门教程-路由初体验](https://zhuanlan.zhihu.com/p/501381970) -[Fizz网关入门教程-权限校验](https://zhuanlan.zhihu.com/p/501384396) +[FizzGate网关入门教程-权限校验](https://zhuanlan.zhihu.com/p/501384396) -[Fizz网关入门教程-快速聚合多接口,提高页面数据的加载速度](https://zhuanlan.zhihu.com/p/501387154) +[FizzGate网关入门教程-快速聚合多接口,提高页面数据的加载速度](https://zhuanlan.zhihu.com/p/501387154) -[Fizz网关入门教程-服务编排,祭出终结BFF层的大杀器](https://zhuanlan.zhihu.com/p/501389075) +[FizzGate网关入门教程-服务编排,祭出终结BFF层的大杀器](https://zhuanlan.zhihu.com/p/501389075) -[企业级微服务API网关Fizz-常用插件介绍](https://zhuanlan.zhihu.com/p/513656382) +[企业级微服务API网关FizzGate-常用插件介绍](https://zhuanlan.zhihu.com/p/513656382) -[企业级微服务API网关Fizz-如何自定义插件](https://zhuanlan.zhihu.com/p/513662893) +[企业级微服务API网关FizzGate-如何自定义插件](https://zhuanlan.zhihu.com/p/513662893) -[企业级微服务API网关Fizz-服务编排内置函数](https://zhuanlan.zhihu.com/p/513404417) +[企业级微服务API网关FizzGate-服务编排内置函数](https://zhuanlan.zhihu.com/p/513404417) -[Fizz企业级微服务API网关进阶系列教程-服务编排处理列表数据(上)-展开与合并](https://zhuanlan.zhihu.com/p/515056309) +[FizzGate企业级微服务API网关进阶系列教程-服务编排处理列表数据(上)-展开与合并](https://zhuanlan.zhihu.com/p/515056309) -[Fizz企业级微服务API网关进阶系列教程-服务编排处理列表数据(中)-数据提取与数据关联](https://zhuanlan.zhihu.com/p/515070075) +[FizzGate企业级微服务API网关进阶系列教程-服务编排处理列表数据(中)-数据提取与数据关联](https://zhuanlan.zhihu.com/p/515070075) -[Fizz企业级微服务API网关进阶系列教程-服务编排处理列表数据(下)-字段重命名&字段移除](https://zhuanlan.zhihu.com/p/515509832) +[FizzGate企业级微服务API网关进阶系列教程-服务编排处理列表数据(下)-字段重命名&字段移除](https://zhuanlan.zhihu.com/p/515509832) ## Authorization instructions -1. The fizz-gateway-community community version of the gateway core project is opened in the form of GNU V3 and can be used free of charge in non-commercial projects following the GNU protocol. +1. The fizz-gateway-node community version of the gateway core project is opened in the form of GNU V3 and can be used free of charge in non-commercial projects following the GNU protocol. 2. Management backend projects (fizz-manager-professional) as commercial versions only open binary packages [free download](https://wj.qq.com/s2/8682608/8fe2/), and For commercial projects, please contact us (sale@fizzgate.com) for authorization. ## System screenshot -![homepage](https://user-images.githubusercontent.com/6129661/156333191-1b9901f5-e086-4514-84f0-4a74684fdf2d.png) -![aggr1](https://user-images.githubusercontent.com/6129661/156333163-e2aade71-081c-49f0-9c7b-deb19239be84.png) +![homepage](https://cdn.fizzgate.com/fizz/assets/img/manager_source_statistics_1.991ec114.png) -![aggr2](https://user-images.githubusercontent.com/6129661/156333175-770ac66d-0295-43b1-948a-a91d9a1922dd.png) +![aggr1](https://cdn.fizzgate.com/fizz/assets/img/manager_aggregate_add_2.72b385b5.png) -![route](https://user-images.githubusercontent.com/6129661/156333194-9a4051a8-c59c-493f-8dd9-f004c364b8c4.png) +![aggr2](https://cdn.fizzgate.com/fizz/assets/img/manager_aggregate_add_9.662f119e.png) -![plugin](https://user-images.githubusercontent.com/6129661/156333193-b0bdfae3-4660-42a0-93e3-118333c5b246.png) +![route](https://cdn.fizzgate.com/fizz/assets/img/route1.1fd8abd1.png) -![appid](https://user-images.githubusercontent.com/6129661/156333180-55d4167b-1eba-4fde-900d-6499f971b97f.png) +![plugin](https://cdn.fizzgate.com/fizz/assets/img/manager_plugin_add_2.e1b5a24e.png) -![breaker](https://user-images.githubusercontent.com/6129661/156333182-40986e36-0f80-46b7-aced-1c16406ba2ce.png) +![appid](https://cdn.fizzgate.com/fizz/assets/img/manager_app_id_add_2.49208bf6.png) -![flowcontrol](https://user-images.githubusercontent.com/6129661/156333189-0b209c2b-5026-4a6e-9880-9fc08ee72077.png) +![breaker](https://cdn.fizzgate.com/fizz/assets/img/component2.7e77c716.png) -![doc](https://user-images.githubusercontent.com/6129661/156333188-6a2dae42-24b2-48c6-b401-1b6bbd9f6030.png) +![flowcontrol](https://cdn.fizzgate.com/fizz/assets/img/manager_flow_control_rule_default_edit_2.130223a7.png) + +![doc](https://cdn.fizzgate.com/fizz/assets/img/manager_interface_collection_preview_2.eee99e97.png) diff --git a/README.md b/README.md index 539f8cc..1b898ff 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,48 @@ [English](./README.en-us.md) | 简体中文

- +

- Version - + Version + Documentation - License: GPL--3.0 + License: AGPL--3.0 - - Java CI with Maven + + Java CI with Maven

- **最新QQ交流群**: 512164278 -## Fizz Gateway是什么? +## FizzGate是什么? -An Aggregation API Gateway in Java . Fizz Gateway 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。 +An Aggregation API Gateway in Java . FizzGate 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。 +## 官方网站 + +https://www.fizzgate.com/ + +备用地址:https://www.fizzcrm.com/ ## 演示环境(Demo) -http://demo.fizzgate.com/ +https://demo.fizzgate.com/ + +备用站点:https://demo.fizzcrm.com/ 账号/密码:`admin`/`Aa123!` -健康检查地址:http://demo.fizzgate.com/admin/health (线上版本请限制admin路径的外网访问) +健康检查地址:https://demo.fizzgate.com/admin/health (线上版本请限制admin路径的外网访问) -API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] +API地址:https://demo.fizzgate.com/proxy/[服务名]/[API_Path] -## Fizz的设计 +## FizzGate的设计 -## Fizz典型应用场景 +## FizzGate典型应用场景 @@ -44,7 +51,7 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] - API管理:支持API定义后端服务的配置; - 分组管理:支持通过分组管理实现同一分组的API使用相关的配置; - 服务鉴权:通过插件可对服务进行应用访问权限、检验等链式的拦截策略; -- 集群管理:Fizz网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。 +- 集群管理:FizzGate网关节点是无状态的,配置信息自动同步,支持节点水平拓展和多集群部署。 - 安全授权:支持内置的key-auth, JWT, basic-auth授权方式,并且可以方便控制。 - 服务编排:支持HTTP、Dubbo、gRPC、Soap协议热服务编排能力,支持前后端编码,支持JSON/XML输出,随时随地更新API。 - 负载均衡:支持round-robin负载均衡。 @@ -67,7 +74,7 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] ## 基准测试 -我们将Fizz与市面上主要的网关产品进行比较,使用相同的环境和条件,测试对象均为单个节点。Mock接口模拟20ms时延,报文大小约2K。 +我们将FizzGate与市面上主要的网关产品进行比较,使用相同的环境和条件,测试对象均为单个节点。Mock接口模拟20ms时延,报文大小约2K。 - Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.30GHz * 4 - Linux version 3.10.0-957.21.3.el7.x86_64 @@ -77,19 +84,19 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] | :------------------ | :------------------ | :-------: | :-------: | :-------: | :-------: | | 后端服务 | 直接访问后端服务 | 23540| 32.19 | 27325| 52.09 | | 流量网关 | kong
v2.4.1 | 15662 | 50.87 | 17152 | 84.3 | -| 应用网关 | fizz-gateway-community
v2.0.0 | 12206 | 65.76 | 12766 | 100.34 | +| 应用网关 | fizz-gateway-node
v2.0.0 | 12206 | 65.76 | 12766 | 100.34 | | 应用网关 | spring-cloud-gateway
v2.2.9| 11323 | 68.57 | 10472 | 127.59 | | 应用网关 | shenyu
v2.3.0| 9284 | 92.98 | 9939 | 148.61 | ## 版本对照 -- Fizz-gateway-community: 社区版 +- fizz-gateway-node: 节点端 -- Fizz-manager-professional:管理后台专业版(服务端) +- fizz-manager-professional:管理后台专业版(服务端) -- Fizz-admin-professional:管理后台专业版(前端) +- fizz-admin-professional:管理后台专业版(前端) -| Fizz-gateway-community | Fizz-manager-professional | Fizz-admin-professional | +| fizz-gateway-node | fizz-manager-professional | fizz-admin-professional | | ---------------------- | ------------------------- | ----------------------- | | v1.0.0 | v1.0.0 | v1.0.0 | | v1.1.0 | v1.1.0 | v1.1.0 | @@ -98,21 +105,43 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] 从v1.3.0开始管理后台的前端和服务端合并成一个包 -- Fizz-gateway-community: 社区版 +- fizz-gateway-node: 节点端 -- Fizz-manager-professional:管理后台 +- fizz-manager-professional:管理后台 -| Fizz-gateway-community | Fizz-manager-professional | +| fizz-gateway-node | fizz-manager-professional | |------------------------|---------------------------| | v1.3.0 | v1.3.0 | -| ... | ... | +| v1.4.0 | v1.4.0 | +| v1.4.1 | v1.4.1 | +| v1.5.0 | v1.5.0 | +| v1.5.1 | v1.5.1 | +| v2.0.0 | v2.0.0 | +| v2.1.0 | v2.1.0 | +| v2.2.0 | v2.2.0 | +| v2.2.1 | v2.2.1 | +| v2.2.3 | v2.2.3 | +| v2.3.0 | v2.3.0 | +| v2.3.2 | v2.3.2 | +| v2.3.3 | v2.3.3 | +| v2.4.0 | v2.4.0 | +| v2.4.1 | v2.4.1 | +| v2.5.0 | v2.5.0 | +| v2.5.1 | v2.5.1 | +| v2.5.2 | v2.5.2 | +| v2.6.0 | v2.6.0 | +| v2.6.1 | v2.6.1 | +| v2.6.2 | v2.6.2 | +| v2.6.3 | v2.6.3 | +| v2.6.4 | v2.6.4 | +| v2.6.5 | v2.6.5 | | v2.6.6 | v2.6.6 | | v2.7.0 | v2.7.0 | | v2.7.1 | v2.7.1 | | v2.7.2 | v2.7.2 | -请根据社区版的版本下载对应的管理后台版本 +请根据节点端的版本下载对应的管理后台版本 ## 部署说明 @@ -129,7 +158,7 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] 依赖的安装可参考详细部署教程 -### 安装Fizz +### 安装FizzGate #### 一、安装管理后台 @@ -151,7 +180,7 @@ API地址:http://demo.fizzgate.com/proxy/[服务名]/[API_Path] 安装方式二(v2.0.0或以上版本):docker: -SQL脚本下载页:https://github.com/fizzgate/fizz-gateway-community/releases/tag/{version} (把{version}替换为对应版本号) +SQL脚本下载页:https://github.com/fizzgate/fizz-gateway-node/releases/tag/{version} (把{version}替换为对应版本号) 首次安装执行`fizz-manager-professional-{version}-mysql.sql`数据库脚本,从低版本升级至高版本选择执行update目录下对应升级脚本(如有脚本则执行) @@ -180,7 +209,7 @@ docker run --rm -d -p 8000:8000 \ 服务启动后访问 http://{部署机器IP地址}:8000/#/login,使用超级管理员账户`admin`密码`Aa123!`登录 -#### 二、安装fizz-gateway-community社区版 +#### 二、安装fizz-gateway-node节点端 说明: @@ -190,7 +219,7 @@ docker run --rm -d -p 8000:8000 \ 安装方式一:二进制安装包 -1. 下载fizz-gateway-community的二进制安装包,解压修改application.yml配置文件里配置中心、注册中心、redis(redis配置需与管理后台一致)的配置 +1. 下载fizz-gateway-node的二进制安装包,解压修改application.yml配置文件里配置中心、注册中心、redis(redis配置需与管理后台一致)的配置 2. 根据需要修改boot.sh脚本的apollo连接,不使用apollo配置中心可跳过 3. Linux启动 执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令 4. Windows启动 执行`.\boot.cmd start` 命令启动服务,支持 start/stop/restart/status命令 @@ -198,12 +227,12 @@ docker run --rm -d -p 8000:8000 \ 安装方式二:源码安装: 1. 本地clone仓库上的最新代码,修改application.yml配置文件里配置中心、注册中心、redis(redis配置需与管理后台一致)的配置 -2. 在项目根目录fizz-gateway-community下执行Maven命令`mvn clean package install -DskipTests=true` -3. 在项目目录fizz-gateway-community/fizz-bootstrap下执行Maven命令`mvn clean package -DskipTests=true` -4. 进入fizz-gateway-community/fizz-bootstrap/target/fizz-gateway-community目录,执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令 +2. 在项目根目录fizz-gateway-node下执行Maven命令`mvn clean package install -DskipTests=true` +3. 在项目目录fizz-gateway-node/fizz-bootstrap下执行Maven命令`mvn clean package -DskipTests=true` +4. 进入fizz-gateway-node/fizz-bootstrap/target/fizz-gateway-node目录,执行 `./boot.sh start` 命令启动服务,支持 start/stop/restart/status命令 安装方式三(v2.0.0或以上版本):docker: -1. 下载对应版本的镜像:docker pull fizzgate/fizz-gateway-community:{version} +1. 下载对应版本的镜像:docker pull fizzgate/fizz-gateway-node:{version} 2. 通过环境变量方式修改redis配置(其它配置同理)并运行镜像 ```sh docker run --rm -d -p 8600:8600 \ @@ -211,94 +240,94 @@ docker run --rm -d -p 8600:8600 \ -e "aggregate.redis.port={your redis port}" \ -e "aggregate.redis.password={your redis password}" \ -e "aggregate.redis.database={your redis database}" \ -fizzgate/fizz-gateway-community:{version} +fizzgate/fizz-gateway-node:{version} ``` -或通过映射目录方式使用外部配置文件和输出日志到宿主机, 配置文件可从安装包或源码里获取,在宿主机创建fizz-gateway-community/config和fizz-gateway-community/logs目录,把application.yml和log4j2-spring.xml配置文件放置config下,在fizz-gateway-community目录下运行镜像 +或通过映射目录方式使用外部配置文件和输出日志到宿主机, 配置文件可从安装包或源码里获取,在宿主机创建fizz-gateway-node/config和fizz-gateway-node/logs目录,把application.yml和log4j2-spring.xml配置文件放置config下,在fizz-gateway-node目录下运行镜像 ```sh -cd fizz-gateway-community +cd fizz-gateway-node docker run --rm -d -p 8600:8600 \ --v $PWD/config:/opt/fizz-gateway-community/config \ --v $PWD/logs:/opt/fizz-gateway-community/logs fizzgate/fizz-gateway-community:{version} +-v $PWD/config:/opt/fizz-gateway-node/config \ +-v $PWD/logs:/opt/fizz-gateway-node/logs fizzgate/fizz-gateway-node:{version} ``` 最后访问网关,地址形式为:http://127.0.0.1:8600/[服务名]/[API_Path] ## 官方技术交流群 -Fizz官方技术交流④群:170145598 (推荐) +FizzGate官方技术交流④群:170145598 (推荐) -Fizz官方技术交流①群(已满) +FizzGate官方技术交流①群(已满) -Fizz官方技术交流②群(已满) +FizzGate官方技术交流②群(已满) -Fizz官方技术交流③群:512164278 +FizzGate官方技术交流③群:512164278 -Fizz官方微信群(请加入群之后再询问群主) +FizzGate官方微信群(请加入群之后再询问群主) ## 相关文章 -[服务器减少50%,研发效率提高86%,我们的管理型网关Fizz自研之路](https://www.infoq.cn/article/9wdfiOILJ0CYsVyBQFpl) +[服务器减少50%,研发效率提高86%,我们的管理型网关FizzGate自研之路](https://www.infoq.cn/article/9wdfiOILJ0CYsVyBQFpl) -[简单易用的微服务聚合网关首选:Fizz Gateway安装教程](https://my.oschina.net/linwaiwai/blog/4696224) +[简单易用的微服务聚合网关首选:FizzGate安装教程](https://my.oschina.net/linwaiwai/blog/4696224) -[大厂推荐使用的网关解密:Fizz Gateway管理后台使用教程](https://my.oschina.net/linwaiwai/blog/4696124) +[大厂推荐使用的网关解密:FizzGate管理后台使用教程](https://my.oschina.net/linwaiwai/blog/4696124) -[架构师效率快的终极原因:Fizz Gateway网关之服务编排](https://my.oschina.net/linwaiwai/blog/4696116) +[架构师效率快的终极原因:FizzGate网关之服务编排](https://my.oschina.net/linwaiwai/blog/4696116) -[高阶架构师支招:Fizz Gateway的插件开发](https://my.oschina.net/linwaiwai/blog/4696131) +[高阶架构师支招:FizzGate的插件开发](https://my.oschina.net/linwaiwai/blog/4696131) -[高阶程序员必备技能:Fizz Gateway网关的二次开发](https://my.oschina.net/linwaiwai/blog/4696133) +[高阶程序员必备技能:FizzGate网关的二次开发](https://my.oschina.net/linwaiwai/blog/4696133) -[Fizz网关入门教程-安装](https://zhuanlan.zhihu.com/p/501305059) +[FizzGate网关入门教程-安装](https://zhuanlan.zhihu.com/p/501305059) -[Fizz网关入门教程-路由初体验](https://zhuanlan.zhihu.com/p/501381970) +[FizzGate网关入门教程-路由初体验](https://zhuanlan.zhihu.com/p/501381970) -[Fizz网关入门教程-权限校验](https://zhuanlan.zhihu.com/p/501384396) +[FizzGate网关入门教程-权限校验](https://zhuanlan.zhihu.com/p/501384396) -[Fizz网关入门教程-快速聚合多接口,提高页面数据的加载速度](https://zhuanlan.zhihu.com/p/501387154) +[FizzGate网关入门教程-快速聚合多接口,提高页面数据的加载速度](https://zhuanlan.zhihu.com/p/501387154) -[Fizz网关入门教程-服务编排,祭出终结BFF层的大杀器](https://zhuanlan.zhihu.com/p/501389075) +[FizzGate网关入门教程-服务编排,祭出终结BFF层的大杀器](https://zhuanlan.zhihu.com/p/501389075) -[企业级微服务API网关Fizz-常用插件介绍](https://zhuanlan.zhihu.com/p/513656382) +[企业级微服务API网关FizzGate-常用插件介绍](https://zhuanlan.zhihu.com/p/513656382) -[企业级微服务API网关Fizz-如何自定义插件](https://zhuanlan.zhihu.com/p/513662893) +[企业级微服务API网关FizzGate-如何自定义插件](https://zhuanlan.zhihu.com/p/513662893) -[企业级微服务API网关Fizz-服务编排内置函数](https://zhuanlan.zhihu.com/p/513404417) +[企业级微服务API网关FizzGate-服务编排内置函数](https://zhuanlan.zhihu.com/p/513404417) -[Fizz企业级微服务API网关进阶系列教程-服务编排处理列表数据(上)-展开与合并](https://zhuanlan.zhihu.com/p/515056309) +[FizzGate企业级微服务API网关进阶系列教程-服务编排处理列表数据(上)-展开与合并](https://zhuanlan.zhihu.com/p/515056309) -[Fizz企业级微服务API网关进阶系列教程-服务编排处理列表数据(中)-数据提取与数据关联](https://zhuanlan.zhihu.com/p/515070075) +[FizzGate企业级微服务API网关进阶系列教程-服务编排处理列表数据(中)-数据提取与数据关联](https://zhuanlan.zhihu.com/p/515070075) -[Fizz企业级微服务API网关进阶系列教程-服务编排处理列表数据(下)-字段重命名&字段移除](https://zhuanlan.zhihu.com/p/515509832) +[FizzGate企业级微服务API网关进阶系列教程-服务编排处理列表数据(下)-字段重命名&字段移除](https://zhuanlan.zhihu.com/p/515509832) ## 授权说明 -1. 网关核心项目fizz-gateway-community社区版本以GNU v3的方式进行的开放,在遵循GNU协议的个人非商业化项目中可以免费使用。 +1. 网关核心项目fizz-gateway-node节点端本以GNU v3的方式进行的开放,任何商业使用都需要经过我们授权。 -2. 管理后台项目(fizz-manager-professional)作为商业版本仅开放二进制包 [免费下载](https://wj.qq.com/s2/8682608/8fe2/),而商业项目请注明公司名称联系我们(sale@fizzgate.com)进行授权,了解商业授权规则请点击[商业授权规则](https://github.com/fizzgate/fizz-gateway-community/wiki/%E5%95%86%E4%B8%9A%E6%8E%88%E6%9D%83) +2. 管理后台项目(fizz-manager-professional)作为商业版本仅开放二进制包 [免费下载](https://wj.qq.com/s2/8682608/8fe2/),而商业项目请注明公司名称联系我们(sale@fizzgate.com)进行授权,了解商业授权规则请点击[商业授权规则](https://github.com/fizzgate/fizz-gateway-node/wiki/%E5%95%86%E4%B8%9A%E6%8E%88%E6%9D%83) -3. 在选择Fizz Gateway之前,我们强烈建议您先试用一下我们的DEMO站点,试用我们的产品,并且思考与自身的业务结合,并且考虑产品推行落地方式,在查阅我们的官网价格(https://www.fizzgate.com) 之后再进一步与我们联系。 +3. 在选择FizzGate之前,我们强烈建议您先试用一下我们的DEMO站点,试用我们的产品,并且思考与自身的业务结合,并且考虑产品推行落地方式,在查阅我们的官网价格(https://www.fizzgate.com) 之后再进一步与我们联系。 ## 系统截图 -![homepage](https://user-images.githubusercontent.com/6129661/156333191-1b9901f5-e086-4514-84f0-4a74684fdf2d.png) +![homepage](https://cdn.fizzgate.com/fizz/assets/img/manager_source_statistics_1.991ec114.png) -![aggr1](https://user-images.githubusercontent.com/6129661/156333163-e2aade71-081c-49f0-9c7b-deb19239be84.png) +![aggr1](https://cdn.fizzgate.com/fizz/assets/img/manager_aggregate_add_2.72b385b5.png) -![aggr2](https://user-images.githubusercontent.com/6129661/156333175-770ac66d-0295-43b1-948a-a91d9a1922dd.png) +![aggr2](https://cdn.fizzgate.com/fizz/assets/img/manager_aggregate_add_9.662f119e.png) -![route](https://user-images.githubusercontent.com/6129661/156333194-9a4051a8-c59c-493f-8dd9-f004c364b8c4.png) +![route](https://cdn.fizzgate.com/fizz/assets/img/route1.1fd8abd1.png) -![plugin](https://user-images.githubusercontent.com/6129661/156333193-b0bdfae3-4660-42a0-93e3-118333c5b246.png) +![plugin](https://cdn.fizzgate.com/fizz/assets/img/manager_plugin_add_2.e1b5a24e.png) -![appid](https://user-images.githubusercontent.com/6129661/156333180-55d4167b-1eba-4fde-900d-6499f971b97f.png) +![appid](https://cdn.fizzgate.com/fizz/assets/img/manager_app_id_add_2.49208bf6.png) -![breaker](https://user-images.githubusercontent.com/6129661/156333182-40986e36-0f80-46b7-aced-1c16406ba2ce.png) +![breaker](https://cdn.fizzgate.com/fizz/assets/img/component2.7e77c716.png) -![flowcontrol](https://user-images.githubusercontent.com/6129661/156333189-0b209c2b-5026-4a6e-9880-9fc08ee72077.png) +![flowcontrol](https://cdn.fizzgate.com/fizz/assets/img/manager_flow_control_rule_default_edit_2.130223a7.png) -![doc](https://user-images.githubusercontent.com/6129661/156333188-6a2dae42-24b2-48c6-b401-1b6bbd9f6030.png) +![doc](https://cdn.fizzgate.com/fizz/assets/img/manager_interface_collection_preview_2.eee99e97.png)