Commit 584096c3bcc58a2c98d6e98beb34640097f968f9
1 parent
89cac1a5
api metric测试入库
Showing
15 changed files
with
315 additions
and
47 deletions
gateway-business/src/main/java/com/diligrp/xtrade/business/XtradeGatewayApplication.java
@@ -16,7 +16,7 @@ import org.springframework.cloud.context.config.annotation.RefreshScope; | @@ -16,7 +16,7 @@ import org.springframework.cloud.context.config.annotation.RefreshScope; | ||
16 | public class XtradeGatewayApplication { | 16 | public class XtradeGatewayApplication { |
17 | 17 | ||
18 | public static void main(String[] args) { | 18 | public static void main(String[] args) { |
19 | - ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); | 19 | + //ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.ADVANCED); |
20 | SpringApplication.run(XtradeGatewayApplication.class, args); | 20 | SpringApplication.run(XtradeGatewayApplication.class, args); |
21 | } | 21 | } |
22 | 22 |
gateway-business/src/main/java/com/diligrp/xtrade/business/application/TestAggregationApplication.java
@@ -4,8 +4,22 @@ import com.diligrp.xtrade.business.domain.TestRequestDto; | @@ -4,8 +4,22 @@ import com.diligrp.xtrade.business.domain.TestRequestDto; | ||
4 | import com.diligrp.xtrade.core.common.annotation.DispatchMapping; | 4 | import com.diligrp.xtrade.core.common.annotation.DispatchMapping; |
5 | import com.diligrp.xtrade.core.support.dispatch.DispatchContext; | 5 | import com.diligrp.xtrade.core.support.dispatch.DispatchContext; |
6 | import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher; | 6 | import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher; |
7 | +import org.springframework.beans.factory.annotation.Autowired; | ||
8 | +import org.springframework.http.server.reactive.ServerHttpRequest; | ||
7 | import org.springframework.stereotype.Component; | 9 | import org.springframework.stereotype.Component; |
8 | import org.springframework.validation.annotation.Validated; | 10 | import org.springframework.validation.annotation.Validated; |
11 | +import reactor.core.publisher.Mono; | ||
12 | +import reactor.core.scheduler.Scheduler; | ||
13 | +import reactor.core.scheduler.Schedulers; | ||
14 | + | ||
15 | +import java.time.Duration; | ||
16 | +import java.util.concurrent.CompletableFuture; | ||
17 | +import java.util.concurrent.ExecutionException; | ||
18 | +import java.util.concurrent.TimeUnit; | ||
19 | +import java.util.concurrent.TimeoutException; | ||
20 | +import java.util.function.Consumer; | ||
21 | +import java.util.function.Function; | ||
22 | +import java.util.function.Supplier; | ||
9 | 23 | ||
10 | /** | 24 | /** |
11 | * @Auther: miaoguoxin | 25 | * @Auther: miaoguoxin |
@@ -16,14 +30,17 @@ import org.springframework.validation.annotation.Validated; | @@ -16,14 +30,17 @@ import org.springframework.validation.annotation.Validated; | ||
16 | @Component | 30 | @Component |
17 | @DispatchMapping | 31 | @DispatchMapping |
18 | public class TestAggregationApplication { | 32 | public class TestAggregationApplication { |
19 | - | 33 | + @Autowired |
34 | + private ServerHttpRequest request; | ||
20 | @DispatchMapping("/test") | 35 | @DispatchMapping("/test") |
21 | - public String test(DispatchContext<TestRequestDto> dispatchContext) { | 36 | + public String test(DispatchContext<TestRequestDto> dispatchContext) throws InterruptedException { |
37 | + System.out.println(request.getURI().getRawPath()); | ||
38 | + Thread.sleep(10000); | ||
22 | return "ffff"; | 39 | return "ffff"; |
23 | } | 40 | } |
24 | 41 | ||
25 | @DispatchMapping("test2") | 42 | @DispatchMapping("test2") |
26 | - public void test2(@Validated DispatchContext<TestRequestDto> dispatchContext){ | 43 | + public void test2(@Validated DispatchContext<TestRequestDto> dispatchContext) { |
27 | 44 | ||
28 | } | 45 | } |
29 | 46 |
gateway-business/src/main/resources/bootstrap-dev.yml
@@ -2,12 +2,12 @@ spring: | @@ -2,12 +2,12 @@ spring: | ||
2 | cloud: | 2 | cloud: |
3 | nacos: | 3 | nacos: |
4 | discovery: | 4 | discovery: |
5 | - username: nacos | ||
6 | - password: microtest | ||
7 | - server-addr: apitest.51shiban.com:80/n | ||
8 | - namespace: c86d8673-4d0a-469f-8bb8-1434c57c236c | 5 | + username: xtrade |
6 | + password: abcd1234 | ||
7 | + server-addr: http://10.28.1.79:8848 | ||
8 | + namespace: 35211f71-92a9-4f3e-975e-37b1132e05c8 | ||
9 | config: | 9 | config: |
10 | - username: nacos | ||
11 | - password: microtest | ||
12 | - server-addr: apitest.51shiban.com:80/n | ||
13 | - namespace: c86d8673-4d0a-469f-8bb8-1434c57c236c | 10 | + username: xtrade |
11 | + password: abcd1234 | ||
12 | + server-addr: http://10.28.1.79:8848 | ||
13 | + namespace: 35211f71-92a9-4f3e-975e-37b1132e05c8 |
gateway-core/src/main/java/com/diligrp/xtrade/core/common/utils/ResponseUtils.java
@@ -18,7 +18,7 @@ public class ResponseUtils { | @@ -18,7 +18,7 @@ public class ResponseUtils { | ||
18 | 18 | ||
19 | 19 | ||
20 | public static Mono<Void> writeForbidden(ServerHttpResponse response){ | 20 | public static Mono<Void> writeForbidden(ServerHttpResponse response){ |
21 | - Message<Object> message = Message.failure( | 21 | + Message<Object> message = Message.builder().failure( |
22 | HttpStatus.FORBIDDEN.value(),HttpStatus.FORBIDDEN.toString()); | 22 | HttpStatus.FORBIDDEN.value(),HttpStatus.FORBIDDEN.toString()); |
23 | return writeResponse(response,message); | 23 | return writeResponse(response,message); |
24 | } | 24 | } |
gateway-core/src/main/java/com/diligrp/xtrade/core/filters/factory/DispatchGatewayFilterFactory.java
@@ -4,6 +4,7 @@ import com.diligrp.xtrade.core.common.constant.GatewayConst; | @@ -4,6 +4,7 @@ import com.diligrp.xtrade.core.common.constant.GatewayConst; | ||
4 | import com.diligrp.xtrade.core.common.utils.ResponseUtils; | 4 | import com.diligrp.xtrade.core.common.utils.ResponseUtils; |
5 | import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher; | 5 | import com.diligrp.xtrade.core.support.dispatch.RequestDispatcher; |
6 | import com.diligrp.xtrade.shared.domain.Message; | 6 | import com.diligrp.xtrade.shared.domain.Message; |
7 | +import com.diligrp.xtrade.shared.type.ErrorCode; | ||
7 | import org.springframework.beans.factory.annotation.Autowired; | 8 | import org.springframework.beans.factory.annotation.Autowired; |
8 | import org.springframework.cloud.gateway.filter.GatewayFilter; | 9 | import org.springframework.cloud.gateway.filter.GatewayFilter; |
9 | import org.springframework.cloud.gateway.filter.GatewayFilterChain; | 10 | import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
@@ -13,6 +14,9 @@ import org.springframework.http.MediaType; | @@ -13,6 +14,9 @@ import org.springframework.http.MediaType; | ||
13 | import org.springframework.stereotype.Component; | 14 | import org.springframework.stereotype.Component; |
14 | import org.springframework.web.server.ServerWebExchange; | 15 | import org.springframework.web.server.ServerWebExchange; |
15 | import reactor.core.publisher.Mono; | 16 | import reactor.core.publisher.Mono; |
17 | +import reactor.core.scheduler.Schedulers; | ||
18 | + | ||
19 | +import java.time.Duration; | ||
16 | 20 | ||
17 | import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR; | 21 | import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR; |
18 | 22 | ||
@@ -23,7 +27,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.O | @@ -23,7 +27,7 @@ import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.O | ||
23 | */ | 27 | */ |
24 | @Component | 28 | @Component |
25 | public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<DispatchGatewayFilterFactory.Config> { | 29 | public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<DispatchGatewayFilterFactory.Config> { |
26 | - | 30 | + private static final Duration EXECUTE_TIMEOUT = Duration.ofSeconds(5); |
27 | @Autowired | 31 | @Autowired |
28 | private RequestDispatcher requestDispatcher; | 32 | private RequestDispatcher requestDispatcher; |
29 | 33 | ||
@@ -36,8 +40,8 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<D | @@ -36,8 +40,8 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<D | ||
36 | return new DispatchGatewayFilter(requestDispatcher); | 40 | return new DispatchGatewayFilter(requestDispatcher); |
37 | } | 41 | } |
38 | 42 | ||
39 | - private static class DispatchGatewayFilter implements GatewayFilter,Ordered{ | ||
40 | - private final RequestDispatcher requestDispatcher; | 43 | + private static class DispatchGatewayFilter implements GatewayFilter, Ordered { |
44 | + private final RequestDispatcher requestDispatcher; | ||
41 | 45 | ||
42 | public DispatchGatewayFilter(RequestDispatcher requestDispatcher) { | 46 | public DispatchGatewayFilter(RequestDispatcher requestDispatcher) { |
43 | this.requestDispatcher = requestDispatcher; | 47 | this.requestDispatcher = requestDispatcher; |
@@ -47,10 +51,13 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<D | @@ -47,10 +51,13 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<D | ||
47 | public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { | 51 | public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { |
48 | String rawPath = exchange.getRequest().getURI().getRawPath(); | 52 | String rawPath = exchange.getRequest().getURI().getRawPath(); |
49 | String paramsJson = exchange.getAttribute(GatewayConst.CACHED_REQUEST_BODY_STR_ATTR); | 53 | String paramsJson = exchange.getAttribute(GatewayConst.CACHED_REQUEST_BODY_STR_ATTR); |
50 | - Message<Object> message = requestDispatcher.executeMethod(rawPath, paramsJson, exchange); | ||
51 | - //throw new RuntimeException("gggg"); | ||
52 | exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, MediaType.APPLICATION_JSON_VALUE); | 54 | exchange.getAttributes().put(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR, MediaType.APPLICATION_JSON_VALUE); |
53 | - return ResponseUtils.writeResponse(exchange.getResponse(),message); | 55 | + //callable处理,防止阻塞,netty的work thread比较敏感 |
56 | + return Mono.fromCallable( | ||
57 | + () -> requestDispatcher.executeMethod(rawPath, paramsJson, exchange)) | ||
58 | + .subscribeOn(Schedulers.elastic()) | ||
59 | + .timeout(EXECUTE_TIMEOUT) | ||
60 | + .flatMap(message -> ResponseUtils.writeResponse(exchange.getResponse(), message)); | ||
54 | } | 61 | } |
55 | 62 | ||
56 | @Override | 63 | @Override |
@@ -63,4 +70,5 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<D | @@ -63,4 +70,5 @@ public class DispatchGatewayFilterFactory extends AbstractGatewayFilterFactory<D | ||
63 | public static class Config { | 70 | public static class Config { |
64 | } | 71 | } |
65 | 72 | ||
73 | + | ||
66 | } | 74 | } |
gateway-core/src/main/java/com/diligrp/xtrade/core/filters/global/CacheRequestBodyGlobalFilter.java
@@ -40,7 +40,7 @@ public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered { | @@ -40,7 +40,7 @@ public class CacheRequestBodyGlobalFilter implements GlobalFilter, Ordered { | ||
40 | @Override | 40 | @Override |
41 | public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { | 41 | public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { |
42 | String contentType = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); | 42 | String contentType = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); |
43 | - if (StringUtils.isNotBlank(contentType) && !contentType.startsWith("multipart")) { | 43 | + if (StringUtils.isNotBlank(contentType) && contentType.startsWith("multipart")) { |
44 | return chain.filter(exchange); | 44 | return chain.filter(exchange); |
45 | } | 45 | } |
46 | ServerRequest serverRequest = ServerRequest.create(exchange, | 46 | ServerRequest serverRequest = ServerRequest.create(exchange, |
gateway-core/src/main/java/com/diligrp/xtrade/core/filters/web/FacadeWebFilter.java
@@ -21,6 +21,8 @@ import org.springframework.web.server.WebFilter; | @@ -21,6 +21,8 @@ import org.springframework.web.server.WebFilter; | ||
21 | import org.springframework.web.server.WebFilterChain; | 21 | import org.springframework.web.server.WebFilterChain; |
22 | import reactor.core.publisher.Mono; | 22 | import reactor.core.publisher.Mono; |
23 | 23 | ||
24 | +import java.util.concurrent.TimeoutException; | ||
25 | + | ||
24 | 26 | ||
25 | /** | 27 | /** |
26 | * @Auther: miaoguoxin | 28 | * @Auther: miaoguoxin |
@@ -67,19 +69,23 @@ public class FacadeWebFilter implements WebFilter { | @@ -67,19 +69,23 @@ public class FacadeWebFilter implements WebFilter { | ||
67 | if (dispatchEx.getCause() != null) { | 69 | if (dispatchEx.getCause() != null) { |
68 | return handleException(dispatchEx.getCause()); | 70 | return handleException(dispatchEx.getCause()); |
69 | } else { | 71 | } else { |
70 | - return Message.failure( | 72 | + return Message.builder().failure( |
71 | ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName()); | 73 | ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName()); |
72 | } | 74 | } |
73 | } else if (ex instanceof ResponseStatusException) { | 75 | } else if (ex instanceof ResponseStatusException) { |
74 | ResponseStatusException statusException = (ResponseStatusException) ex; | 76 | ResponseStatusException statusException = (ResponseStatusException) ex; |
75 | log.warn("response status error:{}", statusException.getMessage()); | 77 | log.warn("response status error:{}", statusException.getMessage()); |
76 | - return Message.failure(statusException.getStatus().value(), ex.getMessage()); | 78 | + return Message.builder().failure(statusException.getStatus().value(), ex.getMessage()); |
77 | } else if (ex instanceof GatewayParamNotValidException) { | 79 | } else if (ex instanceof GatewayParamNotValidException) { |
78 | - return Message.failure( | 80 | + return Message.builder().failure( |
79 | ErrorCode.ILLEGAL_PARAMS.getCode(), ex.getMessage()); | 81 | ErrorCode.ILLEGAL_PARAMS.getCode(), ex.getMessage()); |
82 | + } else if (ex instanceof TimeoutException){ | ||
83 | + log.error("api处理超时:", ex); | ||
84 | + return Message.builder().failure( | ||
85 | + ErrorCode.UNKNOWN_ERROR.getCode(), "请求超时"); | ||
80 | } else { | 86 | } else { |
81 | log.error("unknown error:", ex); | 87 | log.error("unknown error:", ex); |
82 | - return Message.failure( | 88 | + return Message.builder().failure( |
83 | ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName()); | 89 | ErrorCode.UNKNOWN_ERROR.getCode(), ErrorCode.UNKNOWN_ERROR.getName()); |
84 | } | 90 | } |
85 | } | 91 | } |
gateway-core/src/main/java/com/diligrp/xtrade/core/repository/GatewayRepository.java
@@ -2,10 +2,13 @@ package com.diligrp.xtrade.core.repository; | @@ -2,10 +2,13 @@ package com.diligrp.xtrade.core.repository; | ||
2 | 2 | ||
3 | import com.diligrp.xtrade.core.common.constant.GatewayAttrType; | 3 | import com.diligrp.xtrade.core.common.constant.GatewayAttrType; |
4 | import com.diligrp.xtrade.core.exception.GatewayRouteResourceException; | 4 | import com.diligrp.xtrade.core.exception.GatewayRouteResourceException; |
5 | +import com.diligrp.xtrade.core.repository.dao.ApiMetricsDao; | ||
5 | import com.diligrp.xtrade.core.repository.dao.AttrConfigDao; | 6 | import com.diligrp.xtrade.core.repository.dao.AttrConfigDao; |
6 | import com.diligrp.xtrade.core.repository.dao.RouteDao; | 7 | import com.diligrp.xtrade.core.repository.dao.RouteDao; |
8 | +import com.diligrp.xtrade.core.repository.entity.ApiMetricsInfoEntity; | ||
7 | import com.diligrp.xtrade.core.repository.entity.GatewayAttrConfig; | 9 | import com.diligrp.xtrade.core.repository.entity.GatewayAttrConfig; |
8 | import com.diligrp.xtrade.core.repository.entity.GatewayConfig; | 10 | import com.diligrp.xtrade.core.repository.entity.GatewayConfig; |
11 | +import com.diligrp.xtrade.core.support.ApiMetricsInfo; | ||
9 | import com.diligrp.xtrade.shared.util.JsonUtils; | 12 | import com.diligrp.xtrade.shared.util.JsonUtils; |
10 | import com.diligrp.xtrade.shared.util.ReflectUtils; | 13 | import com.diligrp.xtrade.shared.util.ReflectUtils; |
11 | import com.fasterxml.jackson.core.type.TypeReference; | 14 | import com.fasterxml.jackson.core.type.TypeReference; |
@@ -17,6 +20,7 @@ import org.springframework.cloud.gateway.route.RouteDefinition; | @@ -17,6 +20,7 @@ import org.springframework.cloud.gateway.route.RouteDefinition; | ||
17 | import org.springframework.stereotype.Repository; | 20 | import org.springframework.stereotype.Repository; |
18 | import org.springframework.util.CollectionUtils; | 21 | import org.springframework.util.CollectionUtils; |
19 | import org.springframework.web.util.UriComponentsBuilder; | 22 | import org.springframework.web.util.UriComponentsBuilder; |
23 | +import reactor.core.publisher.Mono; | ||
20 | 24 | ||
21 | import java.lang.reflect.InvocationTargetException; | 25 | import java.lang.reflect.InvocationTargetException; |
22 | import java.net.URI; | 26 | import java.net.URI; |
@@ -38,25 +42,39 @@ public class GatewayRepository implements IGatewayRepository { | @@ -38,25 +42,39 @@ public class GatewayRepository implements IGatewayRepository { | ||
38 | private RouteDao routeDao; | 42 | private RouteDao routeDao; |
39 | @Autowired | 43 | @Autowired |
40 | private AttrConfigDao attrConfigDao; | 44 | private AttrConfigDao attrConfigDao; |
45 | + @Autowired | ||
46 | + private ApiMetricsDao apiMetricsDao; | ||
41 | 47 | ||
42 | @Override | 48 | @Override |
43 | public List<RouteDefinition> getAll() { | 49 | public List<RouteDefinition> getAll() { |
44 | List<GatewayConfig> gatewayConfigs = routeDao.findAllForLoad(); | 50 | List<GatewayConfig> gatewayConfigs = routeDao.findAllForLoad(); |
45 | List<GatewayAttrConfig> allAttrConfigs = attrConfigDao.findAllForLoad(); | 51 | List<GatewayAttrConfig> allAttrConfigs = attrConfigDao.findAllForLoad(); |
46 | - Map<String , List<GatewayAttrConfig>> attrMap = allAttrConfigs.stream() | 52 | + Map<String, List<GatewayAttrConfig>> attrMap = allAttrConfigs.stream() |
47 | .collect(Collectors.groupingBy(GatewayAttrConfig::getServiceId)); | 53 | .collect(Collectors.groupingBy(GatewayAttrConfig::getServiceId)); |
48 | - gatewayConfigs.forEach(config->{ | 54 | + gatewayConfigs.forEach(config -> { |
49 | List<GatewayAttrConfig> attrConfigs = attrMap.get(config.getServiceId()); | 55 | List<GatewayAttrConfig> attrConfigs = attrMap.get(config.getServiceId()); |
50 | - if (!CollectionUtils.isEmpty(attrConfigs)){ | 56 | + if (!CollectionUtils.isEmpty(attrConfigs)) { |
51 | attrConfigs.sort(Comparator.comparing(GatewayAttrConfig::getSortOrder)); | 57 | attrConfigs.sort(Comparator.comparing(GatewayAttrConfig::getSortOrder)); |
52 | config.setAttrConfigs(attrConfigs); | 58 | config.setAttrConfigs(attrConfigs); |
53 | } | 59 | } |
54 | }); | 60 | }); |
55 | - return gatewayConfigs.stream() | 61 | + return gatewayConfigs.stream() |
56 | .map(this::generateRouteDefinition) | 62 | .map(this::generateRouteDefinition) |
57 | .collect(Collectors.toList()); | 63 | .collect(Collectors.toList()); |
58 | } | 64 | } |
59 | 65 | ||
66 | + @Override | ||
67 | + public void addApiMetrics(List<ApiMetricsInfo> apiMetricsInfos) { | ||
68 | + if (CollectionUtils.isEmpty(apiMetricsInfos)) { | ||
69 | + return; | ||
70 | + } | ||
71 | + List<ApiMetricsInfoEntity> entityList = apiMetricsInfos.stream() | ||
72 | + .map(this::convert2ApiMetricsEntity) | ||
73 | + .collect(Collectors.toList()); | ||
74 | + apiMetricsDao.insertBatch(entityList); | ||
75 | + } | ||
76 | + | ||
77 | + | ||
60 | private RouteDefinition generateRouteDefinition(GatewayConfig gatewayConfig) { | 78 | private RouteDefinition generateRouteDefinition(GatewayConfig gatewayConfig) { |
61 | RouteDefinition definition = new RouteDefinition(); | 79 | RouteDefinition definition = new RouteDefinition(); |
62 | definition.setId(gatewayConfig.getServiceId()); | 80 | definition.setId(gatewayConfig.getServiceId()); |
@@ -70,7 +88,7 @@ public class GatewayRepository implements IGatewayRepository { | @@ -70,7 +88,7 @@ public class GatewayRepository implements IGatewayRepository { | ||
70 | } | 88 | } |
71 | definition.setUri(uri); | 89 | definition.setUri(uri); |
72 | } catch (URISyntaxException e) { | 90 | } catch (URISyntaxException e) { |
73 | - throw new GatewayRouteResourceException("get url failed",e); | 91 | + throw new GatewayRouteResourceException("get url failed", e); |
74 | } | 92 | } |
75 | //设置predicate和filter | 93 | //设置predicate和filter |
76 | this.setPredicatesAndFilters(gatewayConfig, definition); | 94 | this.setPredicatesAndFilters(gatewayConfig, definition); |
@@ -86,9 +104,9 @@ public class GatewayRepository implements IGatewayRepository { | @@ -86,9 +104,9 @@ public class GatewayRepository implements IGatewayRepository { | ||
86 | List<FilterDefinition> filterDefinitions = new ArrayList<>(); | 104 | List<FilterDefinition> filterDefinitions = new ArrayList<>(); |
87 | for (GatewayAttrConfig gatewayAttrConfig : gatewayAttrConfigs) { | 105 | for (GatewayAttrConfig gatewayAttrConfig : gatewayAttrConfigs) { |
88 | if (GatewayAttrType.PREDICATE.getValue() == gatewayAttrConfig.getType()) { | 106 | if (GatewayAttrType.PREDICATE.getValue() == gatewayAttrConfig.getType()) { |
89 | - predicateDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig,PredicateDefinition.class)); | 107 | + predicateDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig, PredicateDefinition.class)); |
90 | } else { | 108 | } else { |
91 | - filterDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig,FilterDefinition.class)); | 109 | + filterDefinitions.add(this.generatePredicateOrFilter(gatewayAttrConfig, FilterDefinition.class)); |
92 | } | 110 | } |
93 | } | 111 | } |
94 | definition.setPredicates(predicateDefinitions); | 112 | definition.setPredicates(predicateDefinitions); |
@@ -96,7 +114,7 @@ public class GatewayRepository implements IGatewayRepository { | @@ -96,7 +114,7 @@ public class GatewayRepository implements IGatewayRepository { | ||
96 | } | 114 | } |
97 | 115 | ||
98 | 116 | ||
99 | - private <T> T generatePredicateOrFilter(GatewayAttrConfig gatewayAttrConfig,Class<T> clazz) { | 117 | + private <T> T generatePredicateOrFilter(GatewayAttrConfig gatewayAttrConfig, Class<T> clazz) { |
100 | T target; | 118 | T target; |
101 | try { | 119 | try { |
102 | target = clazz.getDeclaredConstructor().newInstance(); | 120 | target = clazz.getDeclaredConstructor().newInstance(); |
@@ -110,7 +128,8 @@ public class GatewayRepository implements IGatewayRepository { | @@ -110,7 +128,8 @@ public class GatewayRepository implements IGatewayRepository { | ||
110 | if (!Strings.isNullOrEmpty(gatewayAttrConfig.getAttrArgs())) { | 128 | if (!Strings.isNullOrEmpty(gatewayAttrConfig.getAttrArgs())) { |
111 | Map<String, String> args = JsonUtils.fromJsonString( | 129 | Map<String, String> args = JsonUtils.fromJsonString( |
112 | gatewayAttrConfig.getAttrArgs(), | 130 | gatewayAttrConfig.getAttrArgs(), |
113 | - new TypeReference<LinkedHashMap<String, String>>() {}); | 131 | + new TypeReference<LinkedHashMap<String, String>>() { |
132 | + }); | ||
114 | ReflectUtils.invokeMethod( | 133 | ReflectUtils.invokeMethod( |
115 | target, | 134 | target, |
116 | "setArgs", | 135 | "setArgs", |
@@ -121,11 +140,26 @@ public class GatewayRepository implements IGatewayRepository { | @@ -121,11 +140,26 @@ public class GatewayRepository implements IGatewayRepository { | ||
121 | } catch (IllegalAccessException | 140 | } catch (IllegalAccessException |
122 | | InvocationTargetException | 141 | | InvocationTargetException |
123 | | InstantiationException | 142 | | InstantiationException |
124 | - |NoSuchMethodException e) { | 143 | + | NoSuchMethodException e) { |
125 | throw new GatewayRouteResourceException("init gateway resource failed", | 144 | throw new GatewayRouteResourceException("init gateway resource failed", |
126 | e, | 145 | e, |
127 | new Object[]{JsonUtils.toJsonString(gatewayAttrConfig)}); | 146 | new Object[]{JsonUtils.toJsonString(gatewayAttrConfig)}); |
128 | } | 147 | } |
129 | return target; | 148 | return target; |
130 | } | 149 | } |
150 | + | ||
151 | + private ApiMetricsInfoEntity convert2ApiMetricsEntity(ApiMetricsInfo api) { | ||
152 | + ApiMetricsInfoEntity entity = new ApiMetricsInfoEntity(); | ||
153 | + entity.setCode(api.getCode()); | ||
154 | + entity.setMessage(api.getMessage()); | ||
155 | + entity.setServiceId(api.getServiceId()); | ||
156 | + entity.setUrl(api.getUrl()); | ||
157 | + entity.setRequestHeader(api.getRequestHeader()); | ||
158 | + entity.setRequestBody(api.getRequestBody()); | ||
159 | +// Throwable throwable = api.getThrowable(); | ||
160 | +// entity.setStackTrace(throwable != null? JsonUtils.toJsonString(throwable.getCause().getStackTrace()) : ""); | ||
161 | + entity.setExecuteTime(api.getExecuteTime()); | ||
162 | + entity.setCreatedTime(api.getCreatedTime()); | ||
163 | + return entity; | ||
164 | + } | ||
131 | } | 165 | } |
gateway-core/src/main/java/com/diligrp/xtrade/core/repository/IGatewayRepository.java
1 | package com.diligrp.xtrade.core.repository; | 1 | package com.diligrp.xtrade.core.repository; |
2 | 2 | ||
3 | +import com.diligrp.xtrade.core.support.ApiMetricsInfo; | ||
3 | import org.springframework.cloud.gateway.route.RouteDefinition; | 4 | import org.springframework.cloud.gateway.route.RouteDefinition; |
4 | 5 | ||
5 | import java.util.List; | 6 | import java.util.List; |
@@ -17,4 +18,6 @@ public interface IGatewayRepository { | @@ -17,4 +18,6 @@ public interface IGatewayRepository { | ||
17 | * @date 2020/4/10 | 18 | * @date 2020/4/10 |
18 | */ | 19 | */ |
19 | List<RouteDefinition> getAll(); | 20 | List<RouteDefinition> getAll(); |
21 | + | ||
22 | + void addApiMetrics(List<ApiMetricsInfo> apiMetricsInfos); | ||
20 | } | 23 | } |
gateway-core/src/main/java/com/diligrp/xtrade/core/repository/entity/ApiMetricsInfoEntity.java
1 | package com.diligrp.xtrade.core.repository.entity; | 1 | package com.diligrp.xtrade.core.repository.entity; |
2 | 2 | ||
3 | + | ||
3 | import java.io.Serializable; | 4 | import java.io.Serializable; |
5 | +import java.time.LocalDateTime; | ||
4 | 6 | ||
5 | /** | 7 | /** |
6 | * @Auther: miaoguoxin | 8 | * @Auther: miaoguoxin |
7 | * @Date: 2020/4/18 20:09 | 9 | * @Date: 2020/4/18 20:09 |
8 | - * @Description: | 10 | + * @Description: t_api_metrics实体 |
9 | */ | 11 | */ |
10 | public class ApiMetricsInfoEntity implements Serializable { | 12 | public class ApiMetricsInfoEntity implements Serializable { |
11 | - /**服务id*/ | 13 | + /** 主键id */ |
14 | + private Long id; | ||
15 | + /**响应code*/ | ||
16 | + private Integer code; | ||
17 | + /**响应消息*/ | ||
18 | + private String message; | ||
19 | + /**目标服务id*/ | ||
12 | private String serviceId; | 20 | private String serviceId; |
21 | + /**目标地址*/ | ||
22 | + private String url; | ||
23 | + /**请求头*/ | ||
24 | + private String requestHeader; | ||
25 | + /**请求体*/ | ||
26 | + private String requestBody; | ||
27 | + /**异常栈跟踪Json信息*/ | ||
28 | + private String stackTrace; | ||
29 | + /**方法执行时间,单位:ms*/ | ||
30 | + private Long executeTime; | ||
31 | + /**创建时间*/ | ||
32 | + private LocalDateTime createdTime; | ||
33 | + /**修改时间*/ | ||
34 | + private LocalDateTime modifiedTime; | ||
35 | + | ||
36 | + public Long getId() { | ||
37 | + return id; | ||
38 | + } | ||
39 | + | ||
40 | + public void setId(Long id) { | ||
41 | + this.id = id; | ||
42 | + } | ||
43 | + | ||
44 | + public Integer getCode() { | ||
45 | + return code; | ||
46 | + } | ||
47 | + | ||
48 | + public void setCode(Integer code) { | ||
49 | + this.code = code; | ||
50 | + } | ||
51 | + | ||
52 | + public String getMessage() { | ||
53 | + return message; | ||
54 | + } | ||
55 | + | ||
56 | + public void setMessage(String message) { | ||
57 | + this.message = message; | ||
58 | + } | ||
59 | + | ||
60 | + public String getServiceId() { | ||
61 | + return serviceId; | ||
62 | + } | ||
63 | + | ||
64 | + public void setServiceId(String serviceId) { | ||
65 | + this.serviceId = serviceId; | ||
66 | + } | ||
67 | + | ||
68 | + public String getUrl() { | ||
69 | + return url; | ||
70 | + } | ||
71 | + | ||
72 | + public void setUrl(String url) { | ||
73 | + this.url = url; | ||
74 | + } | ||
75 | + | ||
76 | + public String getRequestHeader() { | ||
77 | + return requestHeader; | ||
78 | + } | ||
79 | + | ||
80 | + public void setRequestHeader(String requestHeader) { | ||
81 | + this.requestHeader = requestHeader; | ||
82 | + } | ||
83 | + | ||
84 | + public String getRequestBody() { | ||
85 | + return requestBody; | ||
86 | + } | ||
87 | + | ||
88 | + public void setRequestBody(String requestBody) { | ||
89 | + this.requestBody = requestBody; | ||
90 | + } | ||
91 | + | ||
92 | + public String getStackTrace() { | ||
93 | + return stackTrace; | ||
94 | + } | ||
95 | + | ||
96 | + public void setStackTrace(String stackTrace) { | ||
97 | + this.stackTrace = stackTrace; | ||
98 | + } | ||
99 | + | ||
100 | + public Long getExecuteTime() { | ||
101 | + return executeTime; | ||
102 | + } | ||
103 | + | ||
104 | + public void setExecuteTime(Long executeTime) { | ||
105 | + this.executeTime = executeTime; | ||
106 | + } | ||
107 | + | ||
108 | + public LocalDateTime getCreatedTime() { | ||
109 | + return createdTime; | ||
110 | + } | ||
111 | + | ||
112 | + public void setCreatedTime(LocalDateTime createdTime) { | ||
113 | + this.createdTime = createdTime; | ||
114 | + } | ||
115 | + | ||
116 | + public LocalDateTime getModifiedTime() { | ||
117 | + return modifiedTime; | ||
118 | + } | ||
119 | + | ||
120 | + public void setModifiedTime(LocalDateTime modifiedTime) { | ||
121 | + this.modifiedTime = modifiedTime; | ||
122 | + } | ||
13 | } | 123 | } |
124 | + |
gateway-core/src/main/java/com/diligrp/xtrade/core/support/ApiMetricsCollector.java
1 | package com.diligrp.xtrade.core.support; | 1 | package com.diligrp.xtrade.core.support; |
2 | 2 | ||
3 | +import com.diligrp.xtrade.core.repository.IGatewayRepository; | ||
3 | import com.diligrp.xtrade.shared.util.JsonUtils; | 4 | import com.diligrp.xtrade.shared.util.JsonUtils; |
4 | import com.google.common.collect.Queues; | 5 | import com.google.common.collect.Queues; |
5 | import org.slf4j.Logger; | 6 | import org.slf4j.Logger; |
6 | import org.slf4j.LoggerFactory; | 7 | import org.slf4j.LoggerFactory; |
8 | +import org.springframework.beans.factory.annotation.Autowired; | ||
7 | import org.springframework.stereotype.Component; | 9 | import org.springframework.stereotype.Component; |
8 | 10 | ||
9 | import javax.annotation.PostConstruct; | 11 | import javax.annotation.PostConstruct; |
@@ -26,6 +28,9 @@ public class ApiMetricsCollector { | @@ -26,6 +28,9 @@ public class ApiMetricsCollector { | ||
26 | 28 | ||
27 | private static final BlockingQueue<ApiMetricsInfo> METRICS_QUEUE = new ArrayBlockingQueue<>(1000, true); | 29 | private static final BlockingQueue<ApiMetricsInfo> METRICS_QUEUE = new ArrayBlockingQueue<>(1000, true); |
28 | 30 | ||
31 | + @Autowired | ||
32 | + private IGatewayRepository gatewayRepository; | ||
33 | + | ||
29 | public static void addMetricsInfo(ApiMetricsInfo apiMetricsInfo) { | 34 | public static void addMetricsInfo(ApiMetricsInfo apiMetricsInfo) { |
30 | METRICS_QUEUE.add(apiMetricsInfo); | 35 | METRICS_QUEUE.add(apiMetricsInfo); |
31 | } | 36 | } |
@@ -54,9 +59,7 @@ public class ApiMetricsCollector { | @@ -54,9 +59,7 @@ public class ApiMetricsCollector { | ||
54 | //第五个,指定第四个参数的单位,是秒是分钟还是小时等等 | 59 | //第五个,指定第四个参数的单位,是秒是分钟还是小时等等 |
55 | try { | 60 | try { |
56 | Queues.drain(METRICS_QUEUE, metricsInfos, 50, 1, TimeUnit.MINUTES); | 61 | Queues.drain(METRICS_QUEUE, metricsInfos, 50, 1, TimeUnit.MINUTES); |
57 | - for (ApiMetricsInfo metricsInfo : metricsInfos) { | ||
58 | - log.info("消费的metrics:{}", JsonUtils.toJsonString(metricsInfo)); | ||
59 | - } | 62 | + gatewayRepository.addApiMetrics(metricsInfos); |
60 | } catch (Exception e) { | 63 | } catch (Exception e) { |
61 | log.error("collect api metrics error:", e); | 64 | log.error("collect api metrics error:", e); |
62 | } | 65 | } |
gateway-core/src/main/java/com/diligrp/xtrade/core/support/ApiMetricsInfo.java
@@ -35,7 +35,7 @@ public class ApiMetricsInfo { | @@ -35,7 +35,7 @@ public class ApiMetricsInfo { | ||
35 | /**目标地址*/ | 35 | /**目标地址*/ |
36 | private String url; | 36 | private String url; |
37 | /**请求头*/ | 37 | /**请求头*/ |
38 | - private String requestHeaders; | 38 | + private String requestHeader; |
39 | /**请求体*/ | 39 | /**请求体*/ |
40 | private String requestBody; | 40 | private String requestBody; |
41 | /**异常信息*/ | 41 | /**异常信息*/ |
@@ -58,7 +58,7 @@ public class ApiMetricsInfo { | @@ -58,7 +58,7 @@ public class ApiMetricsInfo { | ||
58 | this.message = message; | 58 | this.message = message; |
59 | this.serviceId = serviceId; | 59 | this.serviceId = serviceId; |
60 | this.url = url; | 60 | this.url = url; |
61 | - this.requestHeaders = requestHeaders; | 61 | + this.requestHeader = requestHeaders; |
62 | this.requestBody = requestBody; | 62 | this.requestBody = requestBody; |
63 | this.throwable = throwable; | 63 | this.throwable = throwable; |
64 | this.executeTime = executeTime; | 64 | this.executeTime = executeTime; |
@@ -78,8 +78,8 @@ public class ApiMetricsInfo { | @@ -78,8 +78,8 @@ public class ApiMetricsInfo { | ||
78 | return new ApiMetricsInfo( | 78 | return new ApiMetricsInfo( |
79 | message.getCode(), | 79 | message.getCode(), |
80 | message.getMessage(), | 80 | message.getMessage(), |
81 | - uri != null ? uri.toString() : "unknown", | ||
82 | route != null ? route.getId() : "unknown", | 81 | route != null ? route.getId() : "unknown", |
82 | + uri != null ? uri.toString() : "unknown", | ||
83 | getRequestHeaderJson(exchange.getRequest().getHeaders()), | 83 | getRequestHeaderJson(exchange.getRequest().getHeaders()), |
84 | requestBody, | 84 | requestBody, |
85 | throwable, | 85 | throwable, |
@@ -118,8 +118,8 @@ public class ApiMetricsInfo { | @@ -118,8 +118,8 @@ public class ApiMetricsInfo { | ||
118 | return requestBody; | 118 | return requestBody; |
119 | } | 119 | } |
120 | 120 | ||
121 | - public String getRequestHeaders() { | ||
122 | - return requestHeaders; | 121 | + public String getRequestHeader() { |
122 | + return requestHeader; | ||
123 | } | 123 | } |
124 | 124 | ||
125 | public Throwable getThrowable() { | 125 | public Throwable getThrowable() { |
gateway-core/src/main/java/com/diligrp/xtrade/core/support/dispatch/RequestDispatcher.java
@@ -68,7 +68,7 @@ public class RequestDispatcher { | @@ -68,7 +68,7 @@ public class RequestDispatcher { | ||
68 | } | 68 | } |
69 | //分发逻辑 | 69 | //分发逻辑 |
70 | Object resultData = this.beginDispatch(matchUri, paramsJson, exchange); | 70 | Object resultData = this.beginDispatch(matchUri, paramsJson, exchange); |
71 | - return Message.success(resultData); | 71 | + return Message.builder().success(resultData); |
72 | } catch (Throwable e) { | 72 | } catch (Throwable e) { |
73 | throw new GatewayDispatchException("dispatch method error", e); | 73 | throw new GatewayDispatchException("dispatch method error", e); |
74 | } | 74 | } |
gateway-core/src/main/resources/mapper/ApiMetricsMapper.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
3 | +<mapper namespace="com.diligrp.xtrade.core.repository.dao.ApiMetricsDao"> | ||
4 | + | ||
5 | + <resultMap type="com.diligrp.xtrade.core.repository.entity.ApiMetricsInfoEntity" id="ApiMetricsMap"> | ||
6 | + <result property="id" column="id"/> | ||
7 | + <result property="code" column="code"/> | ||
8 | + <result property="message" column="message"/> | ||
9 | + <result property="serviceId" column="service_id"/> | ||
10 | + <result property="url" column="url"/> | ||
11 | + <result property="requestHeader" column="request_header"/> | ||
12 | + <result property="requestBody" column="request_body"/> | ||
13 | + <result property="stackTrace" column="stack_trace"/> | ||
14 | + <result property="executeTime" column="execute_time"/> | ||
15 | + <result property="createdTime" column="created_time"/> | ||
16 | + <result property="modifiedTime" column="modified_time"/> | ||
17 | + </resultMap> | ||
18 | + <insert id="insertBatch" parameterType="java.util.List"> | ||
19 | + INSERT INTO t_api_metrics(code, | ||
20 | + message, | ||
21 | + service_id, | ||
22 | + url, | ||
23 | + request_header, | ||
24 | + request_body, | ||
25 | + stack_trace, | ||
26 | + execute_time, | ||
27 | + created_time, | ||
28 | + modified_time) | ||
29 | + VALUES | ||
30 | + <foreach collection="list" item="item" index="index" separator=","> | ||
31 | + ( | ||
32 | + #{item.code}, | ||
33 | + #{item.message}, | ||
34 | + #{item.serviceId}, | ||
35 | + #{item.url}, | ||
36 | + #{item.requestHeader}, | ||
37 | + #{item.requestBody}, | ||
38 | + #{item.stackTrace}, | ||
39 | + #{item.executeTime}, | ||
40 | + #{item.createdTime}, | ||
41 | + now() | ||
42 | + ) | ||
43 | + </foreach> | ||
44 | + </insert> | ||
45 | + | ||
46 | + <!--查询单个--> | ||
47 | + <select id="queryById" resultMap="ApiMetricsMap"> | ||
48 | + select id, | ||
49 | + code, | ||
50 | + message, | ||
51 | + service_id, | ||
52 | + url, | ||
53 | + request_header, | ||
54 | + request_body, | ||
55 | + stack_trace, | ||
56 | + execute_time, | ||
57 | + created_time, | ||
58 | + modified_time | ||
59 | + from xtrade_gateway.t_api_metrics | ||
60 | + where id = #{id} | ||
61 | + </select> | ||
62 | + | ||
63 | + | ||
64 | +</mapper> |
sql/gateway-1.0.0.sql
@@ -11,7 +11,7 @@ CREATE TABLE `xtrade_gateway`.`t_route` | @@ -11,7 +11,7 @@ CREATE TABLE `xtrade_gateway`.`t_route` | ||
11 | ) COMMENT = '路由表'; | 11 | ) COMMENT = '路由表'; |
12 | 12 | ||
13 | ALTER TABLE `xtrade_gateway`.`t_route` | 13 | ALTER TABLE `xtrade_gateway`.`t_route` |
14 | - ADD UNIQUE INDEX `uni_service_id`(`service_id`) USING BTREE COMMENT 'service_id唯一索引'; | 14 | + ADD UNIQUE INDEX `uni_service_id` (`service_id`) USING BTREE COMMENT 'service_id唯一索引'; |
15 | 15 | ||
16 | CREATE TABLE `xtrade_gateway`.`t_attr_config` | 16 | CREATE TABLE `xtrade_gateway`.`t_attr_config` |
17 | ( | 17 | ( |
@@ -32,4 +32,26 @@ ALTER TABLE `xtrade_gateway`.`t_attr_config` | @@ -32,4 +32,26 @@ ALTER TABLE `xtrade_gateway`.`t_attr_config` | ||
32 | MODIFY COLUMN `order` smallint(2) NOT NULL DEFAULT 0 COMMENT '排序字段' AFTER `desc`; | 32 | MODIFY COLUMN `order` smallint(2) NOT NULL DEFAULT 0 COMMENT '排序字段' AFTER `desc`; |
33 | 33 | ||
34 | ALTER TABLE `xtrade_gateway`.`t_attr_config` | 34 | ALTER TABLE `xtrade_gateway`.`t_attr_config` |
35 | - ADD UNIQUE INDEX `uni_service_id&attr_name`(`service_id`, `attr_name`) USING BTREE COMMENT 'service_id和attr_name唯一约束'; | 35 | + ADD UNIQUE INDEX `uni_service_id&attr_name` (`service_id`, `attr_name`) USING BTREE COMMENT 'service_id和attr_name唯一约束'; |
36 | + | ||
37 | +CREATE TABLE `t_api_metrics` | ||
38 | +( | ||
39 | + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', | ||
40 | + `code` int(10) NOT NULL COMMENT 'response code', | ||
41 | + `message` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'response提示消息', | ||
42 | + `service_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '服务id', | ||
43 | + `url` varchar(150) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '目标url', | ||
44 | + `request_header` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '请求头json', | ||
45 | + `request_body` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '请求体', | ||
46 | + `stack_trace` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '异常栈跟踪信息json', | ||
47 | + `execute_time` bigint(10) NOT NULL COMMENT 'api执行时间,单位:ms', | ||
48 | + `created_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', | ||
49 | + `modified_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', | ||
50 | + PRIMARY KEY (`id`) USING BTREE | ||
51 | +) ENGINE = InnoDB | ||
52 | + AUTO_INCREMENT = 1 | ||
53 | + CHARACTER SET = utf8mb4 | ||
54 | + COLLATE = utf8mb4_general_ci COMMENT = 'api请求指标记录表' | ||
55 | + ROW_FORMAT = Compact; | ||
56 | + | ||
57 | +SET FOREIGN_KEY_CHECKS = 1; |